1. 术语
resident set size (RSS)
2. 文件系统
/proc/self/statm
3. 相关命令
3.1. top
3.1.1. Fields
TIME+1 | TIME |
---|---|
5432:01 means “5432 minutes and 1 second” |
90,32 means “90 hours and 32 minutes” |
25:15.20 means “25 minutes, 15 seconds and 20% of 1 second” |
25:15 means “25 minutes and 15 seconds” |
3.2. ps
3.2.1. 输出说明
TIME
: the cumulated CPU time in [DD-]hh:mm:ss format (time=TIME)
Field | value & means |
---|---|
TIME |
1-18:09:38 means “1 day, 18 hours, 9 minutes and 38 seconds” |
4. 相关系统调用
4.1. fork
子进程是父进程的副本,获取了父进程的数据空间、堆和栈的副本,但是他们共享正文段。
写时复制(Copy-On-Write,COW):不复制父进程的完全副本,只有在父或子进程尝试修改这些区域时,则为修改区域的那块内存制作一个副本,通常是虚拟内存的一页。
博主注: 如果父进程尝试修改共享的内存页,内核会为父进程同样制作副本,而把原本的内存页留给子进程使用,这会导致即使在父进程中,原本的内存页的物理地址也会发生改变,从而使得 RDMA 等机制发生错误(要求物理地址保持不变),所以此时需要使用 madise
设置 MADV_DONTFORK
标志。
在 Linux 中,写时复制(Copy-On-Write, COW)机制主要通过页表和内存管理单元(MMU)来实现。以下是 COW 在 Linux 中的具体实现步骤:
页表标记:当进程调用 fork() 创建子进程时,父进程和子进程的页表会标记共享的内存页为只读。这意味着这些页在初始状态下是共享的,且无法被写入。
页错误处理:如果父进程或子进程尝试写入这些只读页,会触发页错误(page fault)。操作系统内核会捕获这个页错误,并执行 COW 机制。
内存页复制:在页错误发生时,操作系统会分配一个新的物理内存页,并将原始页的内容复制到这个新页中。然后,页表会更新,以指向新的可写内存页。
页表更新:操作系统更新进程的页表,使得写入操作可以在新的内存页上进行,而不会影响其他进程共享的原始页。
引用计数:操作系统维护每个内存页的引用计数,以跟踪有多少进程共享该页。当引用计数减少到零时,内存页可以被释放。
4.2. mmap
TODO
4.3. madvise
madvise
是一个系统调用,用于向内核提供关于内存使用的建议。
1 |
|
4.3.1. 选项 advice:
4.3.1.1. MADV_DONTFORK
MADV_DONTFORK
阻止 fork()
后的子进程看见这些范围的内存页。
这意味该内存不会被复制,即在 fork()
调用时,指定的内存区域不会被子进程继承,避免写时复制导致的页物理地址发生变化。在 fork() 之后,如果父进程对共享内存页进行写操作,写时复制(COW)机制会将这些页复制到新的物理位置。这会导致 RDMA 操作使用的内存地址不一致,从而引发数据错误。
拓展: RDMA 中,ibv_fork_init
和 RDMAV_HUGEPAGES_SAFE
会调用 madvise()
来为 IB 卡的 DMA 内存页设置 MADV_DONTFORK
,以避免数据损坏。
5. 参考
what-does-virtual-memory-size-in-top-mean
[2]: https://blog.csdn.net/weixin_42319496/article/details/125940896
[3]: https://docs.nvidia.com/networking/display/rdmaawareprogrammingv17/ibv_fork_init