Perl fork()共享内存

szqfcxe2  于 8个月前  发布在  Perl
关注(0)|答案(2)|浏览(68)

有没有办法在分叉之前将只读变量加载到内存中,并将它们保存在那里,而不会占用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

可以肯定的是,几乎所有的内存都在各个子进程中。
是我遗漏了什么,还是fork一个perl进程真的复制了每个子进程的整个数据结构集?

1sbrub3j

1sbrub3j1#

这可能与操作系统有关,也可能你看到的不是你认为看到的。我修改了你的测试脚本:

#!/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特定意义上的“共享内存”(即,已显式请求并分配为“共享”的内存块),并且当前可用于多个进程的页面在写时复制的基础上不符合该定义。

0qx6xfy6

0qx6xfy62#

perl docs on fork说“文件描述符(有时是这些描述符上的锁)是共享的,而其他所有内容都是复制的。”
实际上这意味着进程的所有(代码和)数据都被复制到fork上,但是进程地址空间中的文件描述符基本上是对共享内核结构的引用。因此父进程和子进程可以访问同一个文件。

相关问题