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