【问题标题】:shared memory not updating共享内存不更新
【发布时间】:2019-10-03 16:06:38
【问题描述】:

所以我一直在尝试更多地了解共享内存。我正在我的主人中创建一个共享内存结构并分叉孩子。然后每个孩子都使用 execv 创建一个新进程。当我尝试从新进程更改共享内存的值时,父进程看不到该更改。我也期待父母将执行与孩子交错。例如

Child 1 exec 
parent 
child 2 exec 
parent 
child 3 exec
parent 

但是我得到了

child 1 exec 
child 2 exec 
child 3 exec 
parent
parent
parent

这是我的代码

simulate.c

# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <time.h>
# include <stdlib.h>
# include <dirent.h>
# include <stdio.h>
# include <string.h>
# include <getopt.h>
# include <stdbool.h>
# include <ctype.h>
# include <sys/wait.h>
# include <signal.h>
# include <sys/mman.h>
# include <sys/time.h>
# include <stdint.h>
# include <fcntl.h>
# include <sys/shm.h>
struct sharedregion{
    volatile int seconds;
    volatile int sharedmsg;
};
struct sharedregion *mystruct;
void spawnchild()
{
    int fd = shm_open("sharedmemory", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRWXG | S_IRWXU);
    if (fd == -1)
        perror("Error in opening");
    if (ftruncate(fd, sizeof(struct sharedregion)) == -1)
        perror("Unable to truncate");
    mystruct = mmap(NULL, sizeof(struct sharedregion),PROT_READ | PROT_WRITE, MAP_SHARED| MAP_ANONYMOUS, fd, 0);
    if (mystruct == MAP_FAILED)
        perror("mapping failed");
    mystruct->seconds=0;
    mystruct->sharedmsg=0;
    int i;
    for(i=0;i<4;i++)
    {
        pid_t pID = fork();

        if (pID == 0)
        {
            static char *args[]={"./child",NULL};

            execv(args[0], args);
            perror("failed to execv");
            exit(EXIT_FAILURE);

        }
        else if (pID < 0)            // failed to fork
        {
            perror(" Failed to fork:");
            exit(EXIT_FAILURE);
        }
        else if(pID>0)
        {

            printf("\nfrom parent= %d",mystruct->sharedmsg);
            mystruct->seconds=mystruct->seconds+1;
            if(mystruct->seconds==1000000000)
            {
                mystruct->seconds=1;
            }
        }
    }
}
int main(int argc, char **argv)
{
    spawnchild();
}

child.c

# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <time.h>
# include <stdlib.h>
# include <dirent.h>
# include <stdio.h>
# include <string.h>
# include <getopt.h>
# include <stdbool.h>
# include <ctype.h>
# include <sys/wait.h>
# include <signal.h>
# include <sys/mman.h>
# include <sys/time.h>
# include <stdint.h>
# include <fcntl.h>
# include <sys/shm.h>
struct sharedregion{
    volatile int seconds;
        volatile int sharedmsg;
};
struct sharedregion *mystruct;

int main(int argc, char **argv)
{
    int memFd = shm_open("sharedmemory", O_RDWR, S_IRUSR | S_IWUSR | S_IRWXG | S_IRWXU);
    if (memFd == -1)
    {
        perror("Can't open file");
        return 1;
    }

    mystruct = mmap(NULL, sizeof (struct sharedregion), PROT_READ | PROT_WRITE, MAP_SHARED| MAP_ANONYMOUS, memFd, 0);

    printf("\nhello from exec");
    mystruct->sharedmsg=8;
    printf("buffer %d",mystruct->sharedmsg);

    return 0;
}

我的输出

hello from execbuffer 8
hello from execbuffer 8
hello from execbuffer 8
hello from execbuffer 8
hello from execbuffer 8
from parent= 0
from parent= 0
from parent= 0
from parent= 0
from parent= 0

【问题讨论】:

  • 父子节点同时运行,你没有同步它们的东西。
  • 但这并不能解释为什么父级在mystruct-&gt;sharedmsg 中显示的值与子级不同。
  • 可能是父进程在子进程更新之前读取了共享内存。如果在父级读取共享内存之前添加一个wait 调用会发生什么?
  • 您应该将\n 放在printf 字符串的末尾stdout 是行缓冲的,因此您应该在消息后立即打印一个换行符,以确保它在您期望的时间打印。
  • @Barmar volatile 不是同步机制。 (至少,不是靠它自己。)

标签: c exec mmap


【解决方案1】:

删除标记 MAP_ANONYMOUS

根据手册:

MAP_ANONYMOUS [...] fd 参数被忽略;

因此它会忽略您的共享内存

【讨论】:

  • 也就是说,@Barmar 强调同步仍然是必要的,以确保存在确保每个进程不读取部分数据的内存屏障。您可以使用 IPC 信号量来实现(参见 man sem_init、sem_open 和朋友)
  • 做出改变仍然给出相同的输出
  • 两边?
  • 期望获得相同的输出,在您的测试中,您不要尝试读取其他进程写入的内容...尝试在启动时从父亲那里设置一些值,并在孩子身上看到它.我需要“交错”交互,需要进程之间的同步
  • printf("\nfrom parent= %d",mystruct-&gt;sharedmsg); 不尝试阅读孩子写的东西吗?
猜你喜欢
  • 2019-10-25
  • 1970-01-01
  • 2018-06-13
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多