我正在研究 exec 系列函数。它的手册页说,它用新的进程映像替换了当前的进程映像。如果它替换二进制文件,那么在返回后,它如何获取调用exec的进程的先前参数?因为替换进程映像意味着替换其所有内存部分。如果我错了或知识较少,请纠正我。
3 回答
真正的工作是由execve(2)系统调用完成的。所有其他功能(如execvp
...)都在调用execve
.
这execve
是一个相当复杂的系统调用。成功时不返回。但是进程状态(包括地址空间)已经[几乎]完全重写了。
所以基本上,地址空间正在变得新鲜。它包含来自二进制可执行文件的段。
程序参数、环境等...已被复制(在堆栈段的底部)到新的地址空间中。因此它们是有限的(ARG_MAX
通常为 128Kbytes - 但您可以通过重新编译内核来提高它)。
地址空间的更改实际上大多是惰性完成的(使用write on write);实际上,分页无效,并且后续访问会出现页面错误,内核通过提供新页面等来服务...
在 Linux 上,我建议查看/proc/
(有关更多信息,请参阅proc(5))。特别是,try cat /proc/self/maps
which 将向您显示运行该cat
.
当然execve
通常在fork(2)之后使用,也可能与dup2(2)和/或pipe(2)以及一些等待系统调用如waitpid(2)或wait4(2)一起使用,也许处理SIGCHLD
信号 -see signal(7 ) & sigaction(2)。请阅读例如高级 linux 编程(您可以在线阅读)。
您也可以考虑使用popen(3)或system(3)(他们要求pipe
,popen
然后fork
& execve
of /bin/sh
-c
....)。
分配了一个新的内存块。参数被复制到该块中。只有这样,旧可执行文件内存中的页面才会被释放。请注意,两者之间可能还有其他步骤。例如,新的可执行文件在旧的可执行文件也被释放之前被映射到内存中。
Linux fork + exec 用于创建子进程。fork() 创建新进程,exec 函数将作为 exec() 参数给出的图像/可执行文件加载/覆盖到进程空间并开始执行。