首页 > 解决方案 > 使用 shm_open 将整数从父进程复制到子进程

问题描述

我正在尝试将整数从父进程复制到子进程。许多这种性质的问题都转向使用不同的 IPC 方法。这对我的情况不起作用。解决方案必须使用<sys/shm.h>. 这是一个更大计划的一部分。我正在初始化大小、指针、pid 和内存名称,如下所示:

          const int SIZE = 4*sizeof(int);
          const char *name = "OS";
          pid_t pid;
          int shm_fd;
          void *ptr;

我叫叉子

pid = fork();

父进程像这样使用整数

                  /* open the shared memory segment */
                  shm_fd = shm_open(name, O_RDONLY, 0666);
                  if (shm_fd == -1) {
                          fprintf(stderr,"open shared memory failed\n");
                          exit(-1);
                  }

                  /* now map the shared memory segment in the address space of the process */
                  ptr = mmap(0,SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
                  if (ptr == MAP_FAILED) {
                          fprintf(stderr,"Map failed in parent\n");
                          exit(-1);
                  }
                  printf("Parent got mapped pointer: %p\n",ptr);
                  /* now read from the shared memory region */
                  printf("Parent has received:");
                  for(int i=0; i < SIZE/sizeof(int); i++)
                        printf(" %d ", *(int *)(ptr +i));
                  printf("\n");

                  /* remove the shared memory segment */
                  if (shm_unlink(name) == -1) {
                          fprintf(stderr,"Error removing %s\n",name);
                          exit(-1);
                  }
                  printf("parent done\n");

孩子像这样产生整数

                  printf("In Child process. I am the producer: my pid=%d\n",getpid());
                  time_t t;
                  srand(time(&t));
                  int integers[SIZE];
                  printf("Generating random integers: ");
                  for(int i=0; i < SIZE/sizeof(int); i++){
                          int value = (rand() -49) %49;
                          integers[i] = value;
                          printf(" %d ", value);
                  }
                  printf("\n");


                  /* create the shared memory segment */
                  shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
                  if (shm_fd == -1) {
                          fprintf(stderr,"open shared memory failed\n");
                          exit(-1);
                  }

                  /* configure the size of the shared memory segment */
                  ftruncate(shm_fd,SIZE);

                  /* now map the shared memory segment in the address space of the process */
                  ptr = mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
                  if (ptr == MAP_FAILED) {
                          fprintf(stderr,"Map failed in child\n");
                          return -1;
                  }
                  printf("Child got mapped pointer: %p\n",ptr);
                  void *ptr2=ptr;//back up the pointer for later use
                  /* Now write to the shared memory region. Increment the value of ptr after each write. */
                  memcpy(ptr, integers, sizeof(int));
                  memcpy(ptr+1,integers+1, sizeof(int));
                  memcpy(ptr+2,integers+2, sizeof(int));
                  memcpy(ptr+3,integers+3, sizeof(int));

                  printf("Child has sent: ");
                  for(int i=0; i < SIZE/sizeof(int); i++)
                          printf(" %d ", *(int *)(ptr2+i));
                  printf("\n");

这是一个简单的消费者-生产者 IPC 程序,但由于某种原因,当我运行该程序时,我的输出不正确。例如,当我生成一组整数时,我得到

In Parent process. I am the consumer: my child pid=19187
In Child process. I am the producer: my pid=19187
Generating random integers:  8  10  37  48
Child got mapped pointer: 0x7f91c9c09000
Child has sent:  807733768  3155210  12325  48
Parent got mapped pointer: 0x7f91c9c09000
Parent has received: 807733768  3155210  12325  48
parent done

看起来最后一个内存位置是有效的,但前 3 个是不正确的。我非常感谢任何有关此问题的帮助。

标签: cshared-memory

解决方案


I'm afraid there is a typo in pointer arithmetic.
*(int *)(ptr +i) should be *((int *)ptr+i)
*(int *)(ptr2+i) should be *((int *)ptr2+i)

It meant "Increment from i bytes then consider as integer pointer" instead of "consider as integer pointer and increment from i elements".

There is the same problem with memcpy(ptr+i, that should be memcpy((int *)ptr+i,.

An advice: declare immediately ptr with the correct type, this will avoid plenty of dangerous casts.

By the way, I cannot see any synchronisation between the child writing and the parent reading.
Adding an ugly sleep(1); (don't do this in real life!) before printf("Parent has received:"); seems to give something correct.

And by another way, depending on the process scheduling, the shm_open(name, O_RDONLY, 0666); call in the parent can fail if the child has not yet called shm_open(name, O_CREAT | O_RDWR, 0666); (the segment does not exist yet).


推荐阅读