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

时间:2018-01-03 11:31:25

标签: c unix shared-memory

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

那时我注意到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;
}

1 个答案:

答案 0 :(得分:0)

简短回答当然是传递指针而不是值,而且

updatef(&arr[i], p);

在使用updatef调用addr[i]时,通过引用传递长值答案并通过引用传递

updatef(arr[i], p);

本质上该值被复制到调用函数并且永远不会被反映到附加指针viz addr,因此当我们传递像addr指针变得不变>

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

传递引用,其中inturn将更新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