Memory management 实践叉子的例子';我们在行动中抄写

Memory management 实践叉子的例子';我们在行动中抄写,memory-management,fork,clone,shared-memory,copy-on-write,Memory Management,Fork,Clone,Shared Memory,Copy On Write,在Linux中,系统调用fork据说使用了写时复制(COW)机制,从而避免了在实际不需要时复制内存 然而,我从来没有看到过奶牛活动的确切证据。我想这样我就建立了我自己的 为此,我运行了一个程序来计算一个矩阵的平方,该矩阵包含40000行和列,每个条目都是一个双精度(8字节)。该程序分为8个进程以进行平方运算。实际值是随机填充的。初始矩阵和结果都使用系统调用mmap作为rw和shareable进行分配 我希望能看到COW使用top跟踪内存使用情况。我看到的是下面的景色。这充其量只是一个“自相矛盾”

在Linux中,系统调用
fork
据说使用了写时复制(COW)机制,从而避免了在实际不需要时复制内存

然而,我从来没有看到过奶牛活动的确切证据。我想这样我就建立了我自己的

为此,我运行了一个程序来计算一个矩阵的平方,该矩阵包含
40000
行和列,每个条目都是一个双精度(8字节)。该程序分为8个进程以进行平方运算。实际值是随机填充的。初始矩阵和结果都使用系统调用
mmap
作为rw和shareable进行分配

我希望能看到COW使用
top
跟踪内存使用情况。我看到的是下面的景色。这充其量只是一个“自相矛盾”的例子:fork不可能在调用时实际克隆和复制初始矩阵的内存,因为系统没有95GiB的RAM,而只有16GiB

(顺便说一句,这表明在top的任何内存列中添加不同进程的值没有多大意义。我没有意识到这一点,这恐怕部分解释了我无法清楚地看到写时复制是如何发生的)

这似乎不是一个令人信服的证据来证明奶牛的行为。从教育的角度来看,这是一个薄弱的例子,因为所有进程“显示”11.9GiB的使用。这不是一个令人信服、清晰的例子。相反,你需要按照“忽略这一点,忽略其他价值,然后想象……你得到了我们想要的”。最好是一些工具,显示每个进程正在使用的独立物理内存的实际部分

这里独立的意思是:如果你加上你看到的每个进程的内存使用量,你就会得到整个程序实际使用的总物理内存

作为
top
这方面的错误工具,我们可以用什么来代替呢

编辑:例如,这些工具会有帮助吗?如果是这样,如何使用它们来获取这些信息?valgrind,smem,/proc/pid/smap

编辑2:进一步挖掘正如所暗示的,到目前为止我发现的最好的机会是通过
smap
(或者可能是
pmap
)作为

(echo“Parent:;pid=266694;cat/proc/$pid/smaps|grep-A9”/dev/zero“echo”;对于ch-in
cat/proc/$pid/task/$pid/children
;do-echo-e“\n###child:$ch”cat/proc/$ch/smaps | grep-A9”/dev/zero”完成)>out

其中父进程的id为266694。这部分输出在这里可能有用,如下所示

Parent: 7fa5d9963000-7fa8d486b000 rw-s 00000000 00:01 18271562 /dev/zero (deleted)  
Size:           12500000 kB  
KernelPageSize:      4 kB  
MMUPageSize:           4 kB  
Rss:               35512 kB  
Pss:               35512 kB  
Shared_Clean:          0 kB  
Shared_Dirty:          0 kB 
Private_Clean:         0 kB  
Private_Dirty:     35512 kB
-- 7fa8d486b000-7fabcf773000 rw-s 00000000 00:01 18271561  /dev/zero (deleted)  
Size:           12500000 kB  
KernelPageSize:        4 kB  
MMUPageSize:           4 kB  
Rss:            12500000 kB  
Pss:             1562500 kB  
Shared_Clean:          0 kB  
Shared_Dirty:   12500000 kB 
Private_Clean:         0 kB  
Private_Dirty:         0 kB
    

\### Child: 266706 7fa5d9963000-7fa8d486b000 rw-s 00000000 00:01 18271562                   /dev/zero (deleted)  
Size:           12500000 kB  
KernelPageSize:        4 kB  
MMUPageSize:           4 kB 
Rss:               35872 kB  
Pss:               35872 kB  
Shared_Clean:          0 kB  
Shared_Dirty:          0 kB  
Private_Clean:         0 kB  
Private_Dirty:     35872 kB  
-- 7fa8d486b000-7fabcf773000 rw-s 00000000 00:01 18271561                   /dev/zero (deleted)  
Size:           12500000 kB  
KernelPageSize:        4 kB  
MMUPageSize:           4 kB  
Rss:            12500000 kB  
Pss:             1562500 kB  
Shared_Clean:          0 kB  
Shared_Dirty:   12500000 kB 
Private_Clean:         0 kB  
Private_Dirty:         0 kB
其余的孩子表现出大致相同的价值观。我还不知道如何正确地解释这一点


然而,我担心我最初的问题更多的是关于(*nix)内存管理和可用于检查它的工具-
top
ps
在这里显然是无用的()。我知道这是一个完全不同的主题,但eps>0。也许我会更改标题或完全删除问题…

如果您使用
MAP\u SHARED
映射内存,则该内存在fork上共享(而不是复制)。只有当你用
MAP\u PRIVATE
映射时,内存才会被复制到fork上(用COW),我知道这个“理论”。我正在寻找一种方法来展示这一点,事实上,这就是正在发生的事情。如果我必须教授这个主题,我怎么做才能让学生们不必相信我的话呢?你的
top
快照似乎非常清楚地表明了这一点——共享矩阵使用的11.9GB由所有进程共享。所使用的总内存仅稍高一点——孩子们需要复制几个堆栈页,可能还有一个全局页,就这样。啊,在意识到我所提到的
top
:不同进程的内存值不能被添加后,我计算了这么多!然而,从教育的角度来看,这是一个薄弱的例子,因为所有进程“显示”11.9GiB的使用。这不是一个令人信服、清晰的例子。相反,你需要沿着“忽略这一点,忽略其他价值,然后想象……你得到了我们想要的”。最好是一些工具,显示每个进程正在使用的物理内存的实际部分。您可以用一些独特的数据填充进程内存的某些页面,进行多次搜索,然后搜索
/dev/mem
,并且(希望)只找到一个包含这些内容的物理页面。也许
mlock()。