在多核机器Linux操作系统中,进程调度器将一个进程迁移到另一个cpu

在多核机器Linux操作系统中,进程调度器将一个进程迁移到另一个cpu,linux,fork,scheduler,multicore,Linux,Fork,Scheduler,Multicore,在我的程序中,它的rss是65G,当调用fork,sys\u clone->dup\u mm->copy\u page\u range时将花费2秒以上的时间。在这种情况下,当执行fork时,一个cpu将100%sys,同时,一个线程在fork完成之前无法获得cpu时间。机器有16个CPU,另一个CPU处于空闲状态 所以我的问题是一个cpu在fork上很忙,为什么调度程序不将等待这个cpu的进程迁移到另一个空闲cpu上?通常,调度器何时以及如何在CPU之间迁移进程 我搜索这个网站,现有的线程无法回

在我的程序中,它的rss是65G,当调用
fork
sys\u clone->dup\u mm->copy\u page\u range
时将花费2秒以上的时间。在这种情况下,当执行fork时,一个cpu将100%sys,同时,一个线程在fork完成之前无法获得cpu时间。机器有16个CPU,另一个CPU处于空闲状态

所以我的问题是一个cpu在fork上很忙,为什么调度程序不将等待这个cpu的进程迁移到另一个空闲cpu上?通常,调度器何时以及如何在CPU之间迁移进程

我搜索这个网站,现有的线程无法回答我的问题

rss是65G,当调用fork时,sys_clone->dup_mm->copy_page_range将消耗2秒以上的时间

执行
fork
(或
clone
)时,应将现有流程的VMA复制到新流程的VMA中。创建新的
mm
并进行实际复制。没有对
copy\u page\u range
的直接调用,但我认为,可能是内联到
dup\u mm
中的,它有对
copy\u page\u range
的调用

dup_mmap
中有几个锁被锁定,新
mm
和旧
oldmm

356         down_write(&oldmm->mmap_sem);
在使用
mmap_sem
reader/writer信号量后,所有mmap上都有一个循环来复制它们的元信息:

381         for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) 
只有在循环(在您的情况下是长循环)后,
mmap\u sem
才会解锁:

465 out:
468         up_write(&oldmm->mmap_sem);
当rwlock
mmap\u sep
被writer关闭时,任何其他读卡器或写卡器都无法在
oldmm
中使用mmaps

在fork完成之前,一个线程无法获得cpu时间 所以我的问题是一个cpu在fork上很忙,为什么调度程序不将等待这个cpu的进程迁移到另一个空闲cpu上

您确定另一个线程已准备好运行,并且不想使用MMAP执行任何操作,例如:

  • 正在映射新内容或取消映射不需要的内容
  • 增加或缩小其堆(
    brk
  • 不断扩大规模
  • 页错
  • 或者其他很多活动
实际上,等待cpu线程是我的IO线程,它从客户机发送/接收包,在我的观察中,包始终存在,但IO线程无法接收它

您应该检查wait cpu线程的堆栈(甚至还有用于此的SysRq),以及I/O的类型。
mmap
ing文件是I/O的变体,它将被fork阻塞在
mmap\u sem

此外,您还可以通过启用线程视图(
H
键)并在输出中添加“上次使用的CPU”列来检查等待CPU线程的“上次使用的CPU”,例如,在
top
监视实用程序中(
f
滚动到
p
,在较新版本中输入)。我认为您的等待cpu线程可能已经在另一个cpu上,只是不允许(未准备好)运行

如果您仅使用fork来生成
exec
,则可以使用fork:

  • 或者切换到
    vWork
    +
    exec
    (或者只切换到
    posix\u spawn
    )。您的进程(但)直到新进程将执行
    exec
    exit
    ,但执行可能比等待65 GB的MMAP被复制要快
  • 或者不使用多个活动线程和多GB虚拟内存执行多线程进程的fork。您可以创建小型(没有多GB mmaped)助手进程,使用ipc或套接字或管道与之通信,并要求它分叉并执行您想要的任何操作

为什么您认为另一个线程需要cpu?可能它正在某个资源/内存锁上休眠,在fork期间不可用。对不起,我的描述不清楚。实际上,等待cpu线程是我的IO线程,它从客户机发送/接收包,在我的观察中,包始终存在,但IO线程无法接收它。在systemtap的帮助下,我发现IO线程无法获得CPU时间。我可以找到一个cpu有100%的sys(do sys_clone),同时,另一个cpu是空闲的。
sys_clone
可能会在执行dup_mm时阻塞一些内核互斥锁(
pi_lock
mm->mmap_sem
),并且您的I/O线程需要锁定相同的互斥锁/信号量。尝试获取第二个线程的堆栈(内核或用户)。。。(您确定只有
fork
可以为您工作吗?如果fork后面有exec,请尝试vfork+exec=
posix_spawn
。)Raymond,有更新吗?