【问题标题】:Perl fork() shared memoryPerl fork() 共享内存
【发布时间】:2013-03-06 21:25:45
【问题描述】:

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

【问题讨论】:

  • 您使用了错误的测试。您需要使用能够真正区分共享页面和非共享页面的东西。该工具可能是特定于操作系统的;在 Linux 上,我们使用 Linux::Smaps

标签: perl fork


【解决方案1】:

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

【讨论】:

  • 您错过了文档中的下一句:“在大多数支持 fork() 的系统上,都非常注意使其非常高效(例如,在数据页上使用写时复制技术) ,使其成为过去几十年多任务处理的主要范例。”
【解决方案2】:

这取决于操作系统,或者您没有看到您认为您看到的内容。我将您的测试脚本修改为:

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

【讨论】:

  • 好的,你是对的。我已经使用 free 运行了几个测试来证明数据确实是共享的。什么顶级节目仍然让我感到困惑。 :-(
猜你喜欢
  • 2010-12-30
  • 2021-12-04
  • 2011-02-10
  • 2011-07-31
  • 2012-04-26
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多