通过不同进程更新共享内存

Updating shared memory by different process

我正在为项目编写一些代码,当我尝试使用另一个进程更新共享内存区域时遇到问题。 基本上,一个进程创建一个共享内存,然后它创建一个子进程,该子进程使用 execve 执行一个进程,其目的是在知道其密钥的情况下更新该共享内存。 最后,主进程将所有数据从 shm 打印到标准输出。

此时我注意到 shm 尚未更新。 我不明白为什么。我尝试过常规赋值 (=) 或为每个字段分配一个函数 (updatef),但它不起作用。 (当然在真正的程序中我是用信号量来调节shm的访问,我写这段代码是为了最小化代码看到的问题)

进程 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/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.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);
    addr = (struct pdata*) shmat(shmid, NULL, 0);
    for(int i=0; i<shmsz; i++){
        addr[i].ppid = -1;
    }
    switch(fork()){
        case 0:
            {
            char *args[] = {"u", NULL};
            execve("u", args, NULL);
            }
            break;
    }
    sleep(2);
    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;
    }

处理你:

#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/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.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);
    addr = (struct pdata*) shmat(shmid, NULL, 0);
    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;
}

简短的回答当然是传递指针而不是值,这样就可以了

updatef(&arr[i], p);

长答案在于按值传递和按引用传递,当 updatefaddr[i] 调用时,如

updatef(arr[i], p);

本质上,该值被复制到调用函数并且永远不会反映到附加指针即 addr 因此,另一方面,当我们传递地址时,原始 addr 指针保持不变

updatef(&addr[i], p); 
//or
updatef(addr+i, p);

引用被传递,这反过来将更新addr+i指针指向的内容

添加 IMO 拆分代码将使它更易于呈现、可读和可维护,并且 bla bla bla 这里有点

文件 1 - s.h,在此处保留共享和全局数据

#ifndef S_H_INCLUDED
#define S_H_INCLUDED

#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/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.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; };



#endif

t.c

#include "s.h" // include global header here

int main(){
    int shmid;
    struct pdata *addr;

    shmid = shmget(mykey, sizeof(struct pdata) * shmsz, IPC_CREAT | perms);
    addr = (struct pdata*) shmat(shmid, NULL, 0);
    for(int i=0; i<shmsz; i++){
        addr[i].ppid = -1;
    }
    switch(fork()){
        case 0:
            {
            char *args[] = {"u", NULL};
            execve("u", args, NULL);
            }
            break;
    }
    sleep(2);
    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;
    }

u.c

#include "s.h" // common included here

static 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);
    addr = (struct pdata*) shmat(shmid, NULL, 0);
    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;
}

和最后的构建步骤

gcc t.c -o t
gcc u.c -o u