【问题标题】:Working of exec family functions [duplicate]exec家族功能的工作[重复]
【发布时间】:2013-05-10 13:55:44
【问题描述】:

我正在研究 exec 系列函数。它的手册页说,它用新的进程映像替换当前进程映像。如果它替换二进制,那么返回后,它如何获得调用exec的进程的先前参数?因为替换进程映像意味着替换其所有内存部分。如果我错了或知识较少,请纠正我。

【问题讨论】:

标签: c linux exec systems-programming


【解决方案1】:

真正的工作是由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,然后是forkforkexecve/bin/sh -c ....)。

【讨论】:

  • 我有一些代码,比如我有一个循环 for(index = 0; index
  • 你不会得到它,因为你的进程地址被覆盖了
  • @Radha:你需要阅读高级linux编程这本书,它有一整章解释你forkexecvepipe ...它会比我们有时间解释你做得更好。
  • @Radha:你可以在线阅读advancedlinuxprogramming.com
  • 感谢您指导我:)
【解决方案2】:

分配了一个新的内存块。参数被复制到该块中。只有这样,旧可执行文件内存中的页面才会被释放。请注意,两者之间可能还有其他步骤。例如,新的可执行文件在旧的可执行文件也被释放之前被映射到内存中。

【讨论】:

  • 你的意思是说,在释放之前的内存之后,为新的可执行文件分配了一个全新的内存?那么,在某个时间点,一个进程消耗了这么多内存?这是怎么发生的,意思是根据当前进程的4段内存?
  • 我的意思是覆盖现有内存
  • 为命令行参数等数据分配了少量内存。可执行文件已映射,这意味着它可能不会立即加载。相反,每个页面都可以在稍后访问时加载。旧进程的内存在新进程开始执行之前被丢弃。
【解决方案3】:

Linux fork + exec 用于创建子进程。 fork() 创建新进程,exec 函数将作为 exec() 参数给出的图像/可执行文件加载/覆盖到进程空间并开始执行。

【讨论】:

  • 查看我对 Basile Starynkevitch 的评论。
猜你喜欢
  • 2011-05-11
  • 1970-01-01
  • 2014-02-10
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-18
相关资源
最近更新 更多