多进程更新Shared Memory未生效问题技术求助
问题分析与解决方案
我一眼就发现问题出在你的updatef函数上——你是按值传递结构体的,这就导致你修改的只是函数内部的临时副本,根本没碰着共享内存里的实际数据!另外还有几个小细节需要调整,咱们一步步说:
1. 根本原因:updatef函数传值而非传引用
你定义的updatef函数参数是struct pdata a,这是按值传递——函数会创建一个a的临时副本,你在函数里做的所有修改都只作用于这个副本,和共享内存里的原结构体完全无关!不管你调用多少次这个函数,共享内存的数据都不会有变化。
2. 核心修正:把updatef改成传指针
把函数的第一个参数改成指针类型,这样就能直接操作共享内存里的结构体了:
void updatef(struct pdata *a, struct pdata p){ a->ppid = p.ppid; a->ptype = p.ptype; strcpy(a->pname, p.pname); a->pgenome = p.pgenome; }
然后在调用的时候,要传递共享内存里结构体的地址:
// Process u里的调用要改成这样 updatef(&addr[i], p);
3. 额外细节优化
- execve参数规范:你在子进程里调用
execve("u", args, NULL),第一个参数如果用相对路径,最好明确写成./u(确保当前目录下的可执行文件能被找到),同时args数组的第一个元素惯例上要和程序名称一致; - 替换sleep为wait:用
wait(NULL)替代sleep(2)更可靠——sleep是固定等待时间,而wait会准确等待子进程执行完毕,避免子进程还没写完共享内存,主进程就提前读取的情况; - 增加错误处理:给
shmget、shmat、execve加上失败判断,方便调试时定位问题。
修正后的完整代码
Process t(主进程)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <errno.h> #define mykey 100 #define maxname 100 #define shmsz 5 #define perms 0666 struct pdata{ pid_t ppid; char ptype; char pname[maxname]; unsigned long pgenome; }; // 修改为传指针 void updatef(struct pdata *a, struct pdata p){ a->ppid = p.ppid; a->ptype = p.ptype; strcpy(a->pname, p.pname); a->pgenome = p.pgenome; } int main(){ int shmid; struct pdata *addr; shmid = shmget(mykey, sizeof(struct pdata) * shmsz, IPC_CREAT | perms); if(shmid == -1){ perror("shmget failed"); exit(1); } addr = (struct pdata*) shmat(shmid, NULL, 0); if(addr == (void*)-1){ perror("shmat failed"); exit(1); } // 初始化共享内存 for(int i=0; i<shmsz; i++){ addr[i].ppid = -1; } switch(fork()){ case 0: { char *args[] = {"./u", NULL}; execve("./u", args, NULL); // 如果execve执行到这里,说明失败了 perror("execve failed"); exit(1); } break; default: wait(NULL); // 等待子进程执行完成 break; } // 打印共享内存内容 for(int i=0; i<shmsz; i++){ printf("%d %c %s %lu\n", addr[i].ppid, addr[i].ptype, addr[i].pname, addr[i].pgenome); } shmdt(addr); shmctl(shmid, IPC_RMID, 0); return 0; }
Process u(目标进程)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <errno.h> #define mykey 100 #define maxname 100 #define shmsz 5 #define perms 0666 struct pdata{ pid_t ppid; char ptype; char pname[maxname]; unsigned long pgenome; }; // 修改为传指针 void updatef(struct pdata *a, struct pdata p){ a->ppid = p.ppid; a->ptype = p.ptype; strcpy(a->pname, p.pname); a->pgenome = p.pgenome; } int main(){ int shmid; struct pdata *addr; struct pdata p; shmid = shmget(mykey, sizeof(struct pdata) * shmsz, perms); if(shmid == -1){ perror("shmget failed"); exit(1); } addr = (struct pdata*) shmat(shmid, NULL, 0); if(addr == (void*)-1){ perror("shmat failed"); exit(1); } // 准备要写入的数据 p.ppid = getpid(); p.ptype = 'A'; strncpy(p.pname, "PIPPO", maxname); p.pgenome = 10; // 更新共享内存(传结构体地址) for(int i=0; i<shmsz; i++){ updatef(&addr[i], p); } shmdt(addr); return 0; }
内容的提问来源于stack exchange,提问作者Stewe
相关产品推荐
相关产品推荐

