有没有办法在分叉之前将只读变量加载到内存中并将它们保留在那里而不使用virt memory x x的子项?
似乎普遍认为只读内存默认是共享的,并且在写入时被复制。我进行了测试,发现这是不真实的:
#!/usr/bin/perl
my $data;
$$data = 'a'x 1_000_000; #keep it in a ref just in case that matters
foreach (0..10){
last unless my $pid = fork();
}
<STDIN>;
虽然这个过程坐在STDIN上,但我会检查顶部:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
15982 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15983 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15984 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15985 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15986 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15987 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15988 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15989 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15990 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15991 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
15992 wdev 20 0 121m 2540 188 S 0.0 0.1 0:00.00 foo.t
果然,几乎所有的记忆都在个别的儿童过程中。
我是否缺少某些东西,或者是否真的要为每个孩子复制perl进程的整个数据结构集?
答案 0 :(得分:3)
这是依赖于操作系统的,或者您没有看到您认为自己所看到的内容。我将您的测试脚本修改为:
#!/usr/bin/env perl
print `free`;
my $data = [ ('a') x 1000000 ];
for (1 .. 10) {
print `free`;
last unless fork;
}
sleep 10;
使用./forktest | grep Mem
运行它,我得到输出,如:
Mem: 3979908 2866552 1113356 0 667388 1258560
Mem: 3979908 2917888 1062020 0 667388 1258560
Mem: 3979908 2918284 1061624 0 667388 1258560
Mem: 3979908 2918532 1061376 0 667388 1258560
Mem: 3979908 2918936 1060972 0 667388 1258560
Mem: 3979908 2919404 1060504 0 667388 1258560
Mem: 3979908 2919900 1060008 0 667388 1258560
Mem: 3979908 2919900 1060008 0 667388 1258560
Mem: 3979908 2920148 1059760 0 667388 1258560
Mem: 3979908 2920148 1059760 0 667388 1258560
Mem: 3979908 2920496 1059412 0 667388 1258560
其中第二列数字(总体第三列)是系统RAM的总使用量。请注意,在程序开始时分配$data
时,它会从2866552增加到2917888,然后在叉子完成时保持相当稳定。
我怀疑你在top
中看到的是它在IPC特定的意义上使用“共享内存”(即已明确请求并分配为“共享”的内存块)和当前可在写入时写入多个进程的页面不符合该定义。
答案 1 :(得分:0)
perl docs on fork说“文件描述符(有时锁定那些描述符)是共享的,而其他一切都被复制了。”