使用指针时是否会发生数据竞争?fork后指针与内存变化探究
fork与指针内存的疑问解答
先看你给出的示例代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int *ptr; int main(void) { ptr = malloc(sizeof(int)); if (ptr == NULL) return (1); if (fork() == 0) { (*ptr)++; printf("in child process\n"); printf("%d\n", *ptr); } (*ptr)++; printf("%d\n", *ptr); return (0); }
针对你的疑问逐一解答:
1. 子进程复制内存时,是仅复制指针ptr,还是其指向的实际内存也会被复制?
子进程会复制父进程的整个虚拟地址空间——包括全局变量ptr本身,以及ptr指向的那块由malloc分配的堆内存。不过这里用了**写时复制(COW)**机制:默认情况下父子进程共享同一块物理内存页,只有当其中一方试图修改这块内存时,系统才会为子进程复制出独立的物理内存页,之后双方的修改就各自作用在自己的副本上。
2. 父子进程间是否会发生数据竞争?
不会。因为写时复制的存在,当任何一方修改*ptr时,该内存页会被复制,父子进程后续的读写操作都在各自独立的物理内存上进行,不存在同时访问同一块内存的场景,自然不会有数据竞争。
3. 二者的ptr是指向不同内存地址,还是同一地址?
虚拟地址相同,但物理地址不同。fork后子进程完全继承父进程的虚拟地址布局,所以ptr变量的值(也就是它指向的虚拟地址)和父进程一模一样。但当子进程修改*ptr触发写时复制后,子进程的该虚拟地址会映射到新的物理内存页,此时父子的ptr看似指向同一个地址,实际对应的物理内存已经是两块独立的区域了。
4. 使用指针存储变量时调用fork的行为总结
- fork后,指针变量本身会被完整复制到子进程,其存储的虚拟地址值和父进程完全一致
- 指针指向的内存区域默认与父进程共享,只有当修改该区域时才会触发写时复制,生成子进程独有的内存副本
- 父子进程对指针指向内存的修改互不干扰,修改操作各自作用在自己的物理内存上
- 不存在数据竞争风险,写时复制机制已经隔离了双方的修改操作
内容的提问来源于stack exchange,提问作者user21774205
相关产品推荐
相关产品推荐

