是否有一种方法可以在不使用fork()
的情况下,仅使用execvp()
来启动子进程?
是否有一种方法可以在不使用fork()
的情况下,仅使用execvp()
来启动子进程?
posix_spawn
可能正在使用一个更新的fork-with-options原语(无论它叫什么),而不是原始的fork(2),但它仍然是一个库例程,它包装了一个fork操作和一个exec操作。它的算法没有改变。 - zwolfork
函数制作了一个调用进程的精确副本,并实际上返回两次,一次给父进程,一次给子进程。 execvp
函数(以及 exec
家族中的其他函数)在同一个进程中执行一个新的进程镜像,覆盖现有的进程镜像。execvp
而无需先调用 fork
。 如果这样做,那只意味着当前运行的程序消失,并被给定的程序替换。 然而,fork
是创建新进程的方法。posix_spawn 是不直接调用 fork
时创建子进程的唯一符合 posix 标准的方法。我说“不直接”是因为历史上 posix_spawn
本身会调用 fork
或 vfork
。然而,在 GNU/Linux 中已经不再是这样了。与直接使用 fork
相比,posix_spawn
本身可能更有效率,并且在代码试图运行不同可执行文件时也可能更符合概念。
如果您不担心可移植性,可以放弃 posix,直接与目标内核进行耦合。在 Linux 上,创建子进程的系统调用是 clone。在本回答编写时,手册页提供了三种变体的文档,包括相对较新的 clone3
。
我认为您可以从手册页中借鉴例子,并向 childFunc
添加一个 execvp
调用。不过我还没有尝试过!
posix_spawn
本身可能比fork
更有效率。原因是fork()
在glibc中存在问题,而且glibc的维护者们已经花费了十五年的时间努力让fork()
从POSIX异步信号安全函数列表中移除。 - Andrew Henle正如用户zwol已经解释的那样,execve()
不会派生一个新进程。相反,它会替换当前进程的地址空间和CPU状态,
从可执行文件名加载新的地址空间,并从main()
开始执行,参数列表为argv
,环境变量列表为envp
。
它保留pid和打开的文件。
int execve(const char *filename,char *const argv [],char *const envp[]);
filename
:可执行文件的名称
argv
:命令行参数
envp
:环境变量设置(例如,$PATH
,$HOME
等)
posix_spawn。但它忽略了execvp()的失败——可能是因为实现这个功能被认为太复杂了。
execvp
会用另一个可执行文件替换掉您的进程,所以它并不是子进程。为什么会抵制fork
呢? - Khouri Giordano