Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Linux上更快地分叉大型进程?_Linux_Process_Debian_Exec_Fork - Fatal编程技术网

在Linux上更快地分叉大型进程?

在Linux上更快地分叉大型进程?,linux,process,debian,exec,fork,Linux,Process,Debian,Exec,Fork,在现代Linux上,从大型进程中获得与fork-execve组合相同效果的最快、最好的方法是什么 我的问题是,流程分叉大约有500字节大,一个简单的基准测试只能从流程中获得大约50个分叉/秒(从最小规模的流程中获得约1600个分叉/秒),这对于预期的应用程序来说太慢了 一些谷歌搜索被认为是为了解决这个问题而发明的。。。但也有一些警告。现代Linux似乎已经获得了相关的clone和posix_spawn调用;这些可能有帮助吗?vWork的现代替代品是什么 我在i7上使用64位的Debian Len

在现代Linux上,从大型进程中获得与
fork
-
execve
组合相同效果的最快、最好的方法是什么

我的问题是,流程分叉大约有500字节大,一个简单的基准测试只能从流程中获得大约50个分叉/秒(从最小规模的流程中获得约1600个分叉/秒),这对于预期的应用程序来说太慢了

一些谷歌搜索被认为是为了解决这个问题而发明的。。。但也有一些警告。现代Linux似乎已经获得了相关的
clone
posix_spawn
调用;这些可能有帮助吗?
vWork
的现代替代品是什么


我在i7上使用64位的Debian Lenny(如果posix_spawn有帮助的话,这个项目可能会压缩)。

你真的测量过分叉需要多少时间吗?引用

Linux从来没有这个问题;因为Linux在内部使用写时复制语义,所以Linux只在页面更改时复制页面(实际上,仍然有一些表需要复制;在大多数情况下,它们的开销并不显著)

所以叉子的数量并不能真正显示开销有多大。您应该测量fork所消耗的时间,并且(这是一个通用的建议)只测量您实际执行的fork所消耗的时间,而不是通过基准测试最高性能

但是,如果您真的发现分叉一个大进程是一个缓慢的过程,那么您可能会产生一个小的辅助进程,将主进程导入到它的输入,并从中接收到执行命令。小进程将
fork
exec
这些命令

posix_spawn() 据我所知,该功能是通过桌面系统上的
fork
/
exec
实现的。然而,在嵌入式系统中(特别是在没有板载的系统中),进程是通过系统调用生成的,该调用的接口是
posix_spawn
或类似的函数。引述:

  • 对于实时环境,交换通常太慢

  • 动态地址转换并非在POSIX可能有用的任何地方都可用

  • 当POSIX必须在没有地址转换或其他MMU服务的情况下运行时,进程太有用了,不能简单地选择退出POSIX

因此,POSIX需要进程创建和文件执行原语,这些原语可以在没有地址转换或其他MMU服务的情况下高效地实现


如果您的目标是最大限度地减少时间消耗,那么我认为您不会从桌面上的此功能中受益。

如果您提前知道子进程的数量,那么在启动时预分叉应用程序,然后通过管道分发execv信息可能是合理的。或者,如果您的程序中存在某种“停顿”,那么可以提前完成一两个子流程,以便在以后快速恢复。这两个选项都不能直接解决问题,但如果任何一种方法都适合你的应用程序,它可能会让你回避问题。

结果:我将按照这里的其他答案所建议的早期生成的助手子流程进行操作,但后来我发现,我们重新使用了巨大的页面支持来提高fork性能


我自己也尝试过让我的所有应用程序的malloc分配巨大的页面,现在不管进程大小如何,我都能得到大约2400个fork/s(在我感兴趣的范围内)。惊人。

在Linux上,您可以使用带有
posix\u spawn\u USEVFORK
标志的
posix\u spawn(2)
,以避免从大型进程分叉时复制页表的开销

benchmarking the various spawns over 1000 runs at 100M RSS
                            user     system      total        real
fspawn (fork/exec):     0.100000  15.460000  40.570000 ( 41.366389)
pspawn (posix_spawn):   0.010000   0.010000   0.540000 (  0.970577)
有关
posix_spawn(2)
及其优点和一些示例的详细摘要,请参阅

要利用
vWork(2)
,请确保在
#包括
#之前
#定义"GNU"源
,然后只需
posix_spawnattr_设置标志(&attr,posix_spawnaw_usevWork)

我可以确认这在Debian Lenny上是有效的,并且在从一个大型流程分叉时提供了巨大的速度

benchmarking the various spawns over 1000 runs at 100M RSS
                            user     system      total        real
fspawn (fork/exec):     0.100000  15.460000  40.570000 ( 41.366389)
pspawn (posix_spawn):   0.010000   0.010000   0.540000 (  0.970577)

我看到了这篇博文:

摘录:

系统调用clone()起到了解救作用。我们使用clone()创建一个 具有以下功能的子进程:

  • 子级运行在与父级相同的内存空间中。这意味着当子进程被复制时,不会复制内存结构 创建。因此,对任何非堆栈变量的任何更改 由子进程创建的对象在父进程中可见。这类似于 线程,因此与fork()完全不同,而且 危险——我们不希望孩子把父母搞得一团糟
  • 子项从一个entry函数开始,该函数在创建子项之后立即被调用。这类似于线程,与fork()不同
  • 子对象有一个单独的堆栈空间,类似于threads和fork(),但与vfork()完全不同
  • 最重要的是:这个类似线程的子进程可以调用exec()
简而言之,通过以下方式调用clone,我们创建了一个 子进程,非常类似于线程,但仍然可以调用 exec():

但是,我认为它可能仍然受到setuid问题的影响:

“setuid和vfork”

现在是最糟糕的时候了。线程和vWork允许您进入 两个进程同时共享内存空间和 同时运行。现在,如果 父级调用setuid(或任何其他影响函数的特权)?你 最终,两个具有不同权限级别的进程在同一个数据库中运行 共享地址空间。这是一件坏事

例如,考虑一个最初运行的多线程服务器守护进程 作为root用户,它使用posix_spawn(用vWork天真地实现)来