父进程动态分配的内存块无法共享给子进程问题咨询
问题核心原因
Linux 系统中fork()创建子进程后,父子进程拥有完全独立的虚拟地址空间,遵循写时复制机制:
- fork执行完成的初始阶段,父子进程的相同虚拟地址会映射到同一块物理内存,此时双方读操作共享同一份数据,所以你观察到子进程可以正常读取指针指向的数值,且两边打印的指针虚拟地址完全相同。
- 当任意一方尝试修改该内存内容时,内核会单独复制一份物理内存页给修改方使用,修改操作仅作用在自身地址空间内,完全不会影响对方的内存数据,这就是父进程感知不到子进程修改的根本原因。
另外你的代码还存在一个未定义行为隐患:子进程中定义int *value = NULL;后直接调用read(pipeVariable[0], value, sizeof(int));,相当于往空指针指向的内存地址写入数据,大概率会触发段错误,能正常运行属于概率性的异常情况。正确写法应该是读取父进程传递的指针值到value变量本身的存储地址,即read(pipeVariable[0], &value, sizeof(int*));。
可用解决方案
如果你需要实现父子进程内存共享,可选择以下三种常用方案:
方案1:使用mmap创建匿名共享映射(改造成本最低)
将父进程中malloc分配内存的逻辑替换为mmap创建共享映射即可,修改后的完整代码示例:
#include <sys/stat.h> #include <fcntl.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <sys/mman.h> int main() { int pipeVariable[2] = {0}; pipe(pipeVariable); int x = fork(); if(x == -1){ perror("Error spawning child process"); exit(1); } else if(x == 0){ int *value = NULL; read(pipeVariable[0], &value, sizeof(int*)); printf("Child \nMemory block : %p\nValue : %d\n", value, *value); printf("Child Changed the value\n"); *value = 10; printf("Child \nMemory block : %p\nValue : %d\n", value, *value); close(pipeVariable[1]); close(pipeVariable[0]); exit(0); } else{ int *testVariable = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); *testVariable = 1000; printf("Parent \nMemory block : %p\nValue : %d\n", testVariable, *testVariable); write(pipeVariable[1], &testVariable, sizeof(int*)); wait(NULL); printf("Parent \nMemory block : %p\nValue : %d\n", testVariable, *testVariable); munmap(testVariable, sizeof(int)); close(pipeVariable[1]); close(pipeVariable[0]); } return 0; }
方案2:使用System V共享内存
调用shmget、shmat、shmdt系列系统接口创建全局共享内存段,父子进程分别挂载该内存段即可实现数据共享。
方案3:通过管道回传修改结果
如果不需要实时共享内存,可在子进程修改完数值后,通过管道将新值反向发送给父进程,父进程读取后更新本地变量即可。
内容的提问来源于stack exchange,提问作者jugal Shah
相关产品推荐
相关产品推荐

