如何读取/写入匿名共享映射?

How to read from /write to anonymous shared mapping?

正在尝试向子进程的匿名共享内存写入消息,终止它。然后让家长阅读消息。我已经看到使用通过 readwrite 调用获得的文件描述符映射输入和输出文件的示例。但是不知道如何正确处理这个问题。

int main(void) {
  char *shared; 
  int status;
  pid_t child;

  shared = mmap(0, sizeof(int) , PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);

  if (shared == MAP_FAILED) {
    perror("mmap");
    return 1;
  }

  child = fork();

  if ( child == -1 ) {
    perror("fork");
    return 1;
  } else if (child == 0) {
    sprintf(shared, "foo");

  } else {
    printf("%s", shared);
    wait(&status);
  }

  if (munmap (shared, sizeof(int)) == -1) {
      perror("munmap");
      return 1;
  }

  return 0;    
}

如果您的唯一目标是在子进程和父进程之间读/写,使用管道是一种更简单的方法。它看起来像这样:

    int fd[2]; 
    pipe(fd);

    if((child= fork()) == -1)
    {
            perror("fork");
            exit(1);
    }

    if(child == 0)
    {
            // close read side
            close(fd[0]);

            // write to pipe
            write(fd[1], msg, (strlen(msg));
    }
    else
    {
            //close write side
            close(fd[1]);

            //read what the child wrote. 
            nbytes = read(fd[0], buff, sizeof(buff));
    }

如果您要为共享内存烦恼,那么尝试通过对基础文件的 read()write() 调用来操纵它是愚蠢的(匿名映射不无论如何都存在)。如果您想通过 read()write() 进行通信,那么只需创建一个管道,而不必考虑映射和共享内存。这实际上是一种完全可行的方法。

如果你真的想为此使用共享内存,那么像 memory 一样使用它。将指向共享内存区域的指针转换为合适的pointer-to-object类型,写入使用普通赋值,读取使用普通变量/内存访问。共享内存确实引入了访问和同步冲突的潜在问题,但对于您描述的简单情况来说,这也没什么大不了的:只需让 parent 进程成功 wait() child(或其他方式)在它尝试读取 child 写的任何内容之前收到终止通知。

您在设置映射的方式上确实存在问题,但是:您映射 sizeof(int) 字节,但这可能不足以用于您尝试写入的消息。总的来说,它应该看起来更像这样:

int main(void) {
  char *message;
  int status;
  pid_t child;

  message = mmap(NULL, BUFSIZE , PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);

  if (message == MAP_FAILED) {
    perror("mmap");
    return 1;
  }

  child = fork();

  if ( child == -1 ) {
    perror("fork");
    return 1;
  } else if (child == 0) {
    strcpy( message, "foo\n");
  } else {
    wait(&status);
    printf("The child wrote:\n%s\n", message);
  }

  return 0;    
}