【发布时间】:2015-01-25 12:06:49
【问题描述】:
我想知道 fork() 中写时复制是如何发生的。
假设我们有一个进程 A,它有一个动态 int 数组:
int *array = malloc(1000000*sizeof(int));
数组中的元素被初始化为一些有意义的值。 然后,我们使用 fork() 创建一个子进程,即 B。 B 将迭代数组并进行一些计算:
for(a in array){
a = a+1;
}
- 我知道 B 不会立即复制整个数组,但是子 B 什么时候为数组分配内存?在 fork() 期间?
- 是一次性分配整个数组,还是只为
a = a+1分配一个整数? -
a = a+1;这是怎么发生的? B 是否从 A 读取数据并将新数据写入自己的数组?
我编写了一些代码来探索 COW 的工作原理。我的环境:ubuntu 14.04,gcc4.8.2
#include <stdlib.h>
#include <stdio.h>
#include <sys/sysinfo.h>
void printMemStat(){
struct sysinfo si;
sysinfo(&si);
printf("===\n");
printf("Total: %llu\n", si.totalram);
printf("Free: %llu\n", si.freeram);
}
int main(){
long len = 200000000;
long *array = malloc(len*sizeof(long));
long i = 0;
for(; i<len; i++){
array[i] = i;
}
printMemStat();
if(fork()==0){
/*child*/
printMemStat();
i = 0;
for(; i<len/2; i++){
array[i] = i+1;
}
printMemStat();
i = 0;
for(; i<len; i++){
array[i] = i+1;
}
printMemStat();
}else{
/*parent*/
int times=10;
while(times-- > 0){
sleep(1);
}
}
return 0;
}
在fork()之后,子进程修改了数组中的一半数字,然后修改了整个数组。输出是:
===
Total: 16694571008
Free: 2129162240
===
Total: 16694571008
Free: 2126106624
===
Total: 16694571008
Free: 1325101056
===
Total: 16694571008
Free: 533794816
似乎数组没有作为一个整体分配。如果我将第一个修改阶段稍微更改为:
i = 0;
for(; i<len/2; i++){
array[i*2] = i+1;
}
输出将是:
===
Total: 16694571008
Free: 2129924096
===
Total: 16694571008
Free: 2126868480
===
Total: 16694571008
Free: 526987264
===
Total: 16694571008
Free: 526987264
【问题讨论】:
-
孩子没有“分配”任何东西。子进程从父进程的精确、完整副本开始,然后从那里继续执行。
-
那么,A和B共享数组?
-
@KerrekSB:但它会获得自己独立的进程内存,应该是写时复制。
-
COW 是一个实现细节,它不会影响您的程序。对于 unix.stackexchange.com 或 superuser.com,这个问题可能会更好。
标签: c linux unix fork copy-on-write