【问题标题】:Updating shared memory by different process通过不同的进程更新共享内存
【发布时间】:2018-06-13 01:50:39
【问题描述】:

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

那时我注意到 shm 还没有更新。 我不明白为什么。我尝试过常规分配(=)或为每个字段分配一个函数(updatef),但它不起作用。 (当然在实际程序中我使用信号量来规范对shm的访问,我写这段代码是为了尽量减少代码看问题)

进程时间:

#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;
}

【问题讨论】:

  • 你应该学习如何使用头文件和对常用结构和函数进行单独编译。并且还做了一些关于在C中模拟通过引用传递的研究。
  • updatef(addr[i], p); -->> addr[i] = p; 将是一个开始

标签: c unix shared-memory


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2016-07-23
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    相关资源
    最近更新 更多