1

有没有办法在分叉之前将只读变量加载到内存中并将它们保留在那里而不用完 virt 内存 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 进程是否真的为每个孩子复制了整个数据结构集?

4

2 回答 2

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 的总使用量。请注意,在程序开始时分配时,它从 2866552 增加到 2917888 $data,然后随着分叉完成从那里保持相当稳定。

我怀疑您所看到的top是它使用特定于 IPC 的“共享内存”(即,已明确请求并分配为“共享”的内存块)和当前可用于多个进程的页面在写时复制的基础上不符合该定义。

于 2013-03-18T15:29:39.563 回答
0

fork 上的perl 文档说“文件描述符(有时是这些描述符上的锁)是共享的,而其他所有内容都是复制的。”

于 2013-03-18T14:31:30.287 回答