在我的程序中,其rss为65G,当呼叫fork
时,sys_clone->dup_mm->copy_page_range
将消耗超过2秒。在这种情况下,一个cpu在执行fork时会100%sys,同时,一个线程在fork完成之前无法获得cpu时间。机器有16个CPU,其他CPU空闲。
所以我的问题是一个cpu忙于fork,为什么调度程序不会将等待这个cpu的进程迁移到其他空闲cpu?一般来说,调度程序何时以及如何在cpus之间迁移进程?
我搜索这个网站,现有的线程无法回答我的问题。
答案 0 :(得分:2)
rss是65G,当调用fork时,sys_clone-> dup_mm-> copy_page_range将消耗超过2秒
在执行fork
(或clone
)时,应将现有流程的vmas复制到新流程的vmas中。 dup_mm
function (kernel/fork.c)创建新的mm
并进行实际复制。没有直接调用copy_page_range
,但我认为,static function dup_mmap
可能会被内联到dup_mm
,并且会调用copy_page_range
。
在dup_mmap
中,锁定了多个锁,包括新mm
和旧oldmm
:
356 down_write(&oldmm->mmap_sem);
获取mmap_sem
读写器信号量后,所有mmaps都会循环复制其元信息:
381 for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next)
仅在循环之后(在您的情况下很长),mmap_sem
被解锁:
465 out:
468 up_write(&oldmm->mmap_sem);
虽然rwlock mmap_sep
被作者拒绝,但没有任何其他读者或作者可以使用oldmm
中的mmaps做任何事情。
一个线程在fork完成之前无法获得cpu时间 所以我的问题是一个cpu忙于fork,为什么调度程序不会将等待这个cpu的进程迁移到其他空闲cpu?
您确定,其他线程已准备好运行且不想对mmaps执行任何操作,例如:
brk
),实际上,wait-cpu线程是我的IO线程,它从客户端发送/接收包,在我看来,包总是存在,但是IO线程无法接收它。
你应该检查你的wait-cpu线程的堆栈(甚至还有SysRq),以及那种I / O.文件的mmap
是I / O的变体,它将在mmap_sem
上被fork阻止。
您还可以检查wait-cpu线程的“上次使用的CPU”,例如在top
监视实用程序中,通过启用线程视图(H
键)并添加“上次使用的CPU”列来输出(fj
更早; f
滚动到{ {1}},输入更新)。我认为你的wait-cpu线程可能已经在另一个CPU上,只是不允许(未准备好)运行。
如果您只使用fork来制作P
,则对以下内容有用:
exec
+ vfork
(或仅转到exec
)。 vfork
will suspend您的流程(may not suspend your other threads, it is dangerous),直到新流程执行posix_spawn
或exec
,但执行速度可能比等待复制65 GB的mmaps更快。