如何在 fork() 创建的进程之间共享内存?

Posted

技术标签:

【中文标题】如何在 fork() 创建的进程之间共享内存?【英文标题】:How to share memory between processes created by fork()? 【发布时间】:2012-10-27 19:23:36 【问题描述】:

在fork child中,如果我们修改了一个全局变量,它不会在主程序中改变。

有没有办法改变子叉子中的全局变量?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int glob_var;

main (int ac, char **av)

  int pid;

  glob_var = 1;

  if ((pid = fork()) == 0) 
    /* child */
    glob_var = 5;
  
  else 
    /* Error */
    perror ("fork");
    exit (1);
  

  int status;
  while (wait(&status) != pid) 
  
   printf("%d\n",glob_var); // this will display 1 and not 5.

【问题讨论】:

How to use shared memory with Linux in C的可能重复 【参考方案1】:

您可以使用共享内存(shm_open()shm_unlink()mmap() 等)。

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

static int *glob_var;

int main(void)

    glob_var = mmap(NULL, sizeof *glob_var, PROT_READ | PROT_WRITE, 
                    MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    *glob_var = 1;

    if (fork() == 0) 
        *glob_var = 5;
        exit(EXIT_SUCCESS);
     else 
        wait(NULL);
        printf("%d\n", *glob_var);
        munmap(glob_var, sizeof *glob_var);
    
    return 0;

【讨论】:

你能提供一个简单的例子吗 你需要查找共享内存; google 上有很多例子。这允许两个独立的应用程序使用相同的内存来存储和读取变量。当您fork() 一个进程时,它会创建一个子进程,该子进程具有与父进程不同的内存堆。您的父级将维护其全局变量,而子级将分配自己的副本。 你可以找到一些解释很好的例子here @md5:在 mmap 函数调用中,文件描述符句柄为“-1”。 -1 表示什么? @TheLoneJoker。来自mmap:however, some implementations require fd to be -1 if MAP_ANONYMOUS (or MAP_ANON) is specified, and portable applications should ensure this的手册页【参考方案2】:

无法更改全局变量,因为新创建的进程(子进程)拥有自己的地址空间。

所以最好使用shmget(),shmat() from POSIX api

或者您可以使用 pthread ,因为 pthreads 共享 globaldata 并且全局变量的更改会反映在父级中。

然后阅读一些Pthreads tutorial。

【讨论】:

【参考方案3】:

这是另一种解决方案。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

typedef struct

  int id;
  size_t size;
 shm_t;

shm_t *shm_new(size_t size)

  shm_t *shm = calloc(1, sizeof *shm);
  shm->size = size;

  if ((shm->id = shmget(IPC_PRIVATE, size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) < 0)
  
    perror("shmget");
    free(shm);
    return NULL;
  

  return shm;


void shm_write(shm_t *shm, void *data)

  void *shm_data;

  if ((shm_data = shmat(shm->id, NULL, 0)) == (void *) -1)
  
    perror("write");
    return;
  

  memcpy(shm_data, data, shm->size);
  shmdt(shm_data);


void shm_read(void *data, shm_t *shm)

  void *shm_data;

  if ((shm_data = shmat(shm->id, NULL, 0)) == (void *) -1)
  
    perror("read");
    return;
  
  memcpy(data, shm_data, shm->size);
  shmdt(shm_data);


void shm_del(shm_t *shm)

  shmctl(shm->id, IPC_RMID, 0);
  free(shm);


int main()

  int var = 1;
  shm_t *shm = shm_new(sizeof var);

  int pid;
  if ((pid = fork()) == 0)
   /* child */
    var = 5;
    shm_write(shm, &var);
    printf("child: %d\n", var);
    return 0;
  
  /* Wait for child to return */
  int status;
  while (wait(&status) != pid);
  /* */
  shm_read(&var, shm);
  /* Parent is updated by child */
  printf("parent: %d\n", var);
  shm_del(shm);
  return 0;

构建:

$ gcc shm.c -o shm && ./shm

【讨论】:

以上是关于如何在 fork() 创建的进程之间共享内存?的主要内容,如果未能解决你的问题,请参考以下文章

与struct和malloc共享内存fork

linux vfork的子程序与父进程共享内存,那为啥子进程执行exec就不会覆盖父进程呢?

linux vfork的子程序与父进程共享内存,那为啥子进程执行exec就不会覆盖父进程呢?

撸代码--linux进程通信(基于共享内存)

fork后如何创建共享内存?

如何在 C 中与 Linux 一起使用共享内存