You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多进程更新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:06:21