Cor*_*lks 6 c linux exec vfork
该
vfork()函数具有相同的效果fork(2),除非在成功调用[...]exec(3)函数族之一之前,如果进程调用任何其他函数,则行为未定义.
这表明exec*()之后调用任何函数vfork()是可以接受的.但是,稍后在手册页中明确说明:
特别是,程序员不能依赖父母保持阻止,直到孩子打电话
execve(2)[...].
execve(2)在手册页中重复使用,它的用法表明它是唯一exec可以接受的类型函数vfork().
那么为什么execve被挑选出来,我可以安全地调用其他exec类型的函数(比如execlp)?
你必须打电话execve.无法保证任何其他exec-family函数不会执行之后不安全的操作vfork.例如:
execl可以为参数列表分配内存.它必须是异步信号安全的,这意味着它不太可能使用malloc,但即使它没有,也没有办法在底层execve发生之后释放分配的内存(存在于父代的内存空间中),所以除非它设法在堆栈上构建参数列表,否则它(最多)会泄漏父节点中的内存.
execvp需要访问环境以执行路径搜索,还需要构造要传递到的连接路径名execve.后者可能需要分配,而前者可能会做各种不安全的vfork事情(注意:execvp甚至不是异步信号安全的).
等等
真的,你应该根本不使用vfork.几乎不可能安全使用它.特别是在使用信号处理程序的任何程序中都不安全,因为除非你阻塞所有信号,否则信号处理程序可以在子程序中共享父项的内存时运行(在这种情况下,子项将在exec之后继承一个完全阻塞的信号掩码,几乎肯定不是你想要的).
如果您正在寻找更有效的替代品fork,请使用posix_spawn.
在 Linux 上,所有exec*函数实际上都是系统调用之上的包装库函数execve。因此,通过调用,execlp您实际上也在调用execve。