gpt4 book ai didi

c - 在 C 中使用 execve 加载程序时子进程如何终止

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:33:43 27 4
gpt4 key购买 nike

我是 C 的初学者,我正在努力理解 execve C 中的函数调用子进程来加载和运行可执行目标文件。

我们知道 execve只有在出现找不到文件名等错误时才返回调用程序,因此它被调用一次并且永远不会返回。

这是我的问题,如果我们 fork 一个子进程来调用 execve但自从 execve永不返回,如果一切正常,它总是会执行一些东西,这意味着子进程永远不会被终止,那么父进程如何获得这个子进程呢?下面是示例代码

if ((pid = Fork()) == 0) { /* Child runs user job */
if (execve(argv[0], argv, environ) < 0) { -------->line 2
printf("%s: Command not found.\n", argv[0]);
exit(0);
}
}

/* Parent waits for foreground job to terminate */
if (waitpid(pid, &status, 0) < 0) { ------------> but the child process never terminated
printf("waitpid error");
}

所以在第 2 行, execve(argv[0], argv, environ)永远不会返回,所以子进程永远不会终止?

最佳答案

你的程序foo , 将启动一些子进程来运行一些其他程序,bar ,
并且您希望它使用基本的系统调用 forkexecve
让我们调用您的初始 foo过程 p1。 (这代表一些 pid 。)

首先,您将调用fork .
这会创建一个 p1 的子进程,它正在运行 foo 的另一个实例。
调用该子进程 p1.1。

p1.1 正在运行 foo .但是你想运行 bar .所以立即在 p1.1 中,foo来电 execve(path/to/bar ...) .
这替换了 foo 的实例p1.1 与 bar 的实例一起运行.然后你的
子进程 p1.1 正在运行 bar ,如你所愿。

清楚这一点 :-
execve(path/to/bar ...)不启动 bar在一个新的子过程中
p1.1,并让 p1.1 仍在运行 foo 的 fork 后实例.相反,execve(path/to/bar ...)替换foo 的那个实例实例为 bar在过程 p1.1。之后 fork , 但在 execve 之前,
我们有:

p1[foo] -> p1.1[foo]

execve 之后我们有:
p1[foo] -> p1.1[bar]

不是:
p1[foo] -> p1.1[foo] -> p1.1.1[bar]

你可以看到 execve无法向其调用者 p1.1[foo] 返回成功,
因为如果 execve成功,则 p1.1[foo] 不再存在。
当然还有 execve无法将成功返回给 p1[foo],因为 p1[foo] 没有调用它。

since execve never return, it will be always executing something if everything is OK



号码 execve用 p1.1[bar] 替换 p1.1[foo] 并且不返回,因为调用者不再存在。然后 p1.1[bar] 运行直到它终止。

p1.1[bar] 迟早会以其中一种方式终止
任何程序终止:它将运行到正常 exit , 否则会
被信号杀死,或者它可能调用 abort出于自己的意愿。

父进程(p1)如何获得这个子进程(p1.1)?

首先,它不必。一旦 p1[foo] 启动了 p1.1,它就可以,
如果这就是你想要的,那就别管p1.1,继续其他业务
如果有的话,最后是 exit .如果 p1 在 p1.1 之前终止,则 p1.1
变成 orphan process .
init process 立即将一个孤儿进程作为子进程采用。 .所以
如果在此期间没有任何东西终止它,p1.1 将在 init 时被收割。终止,在系统关闭。

但很可能,你不想放弃孤儿,你确实想要 foo了解 child 的退出状态 bar .在这种情况下,
p1[foo] 迟早必须调用 wait/waitpid现在学习 p1.1
结束,然后采取相应的行动。

与此同时,p1[foo] 很可能正在使用一些与 p1.1[bar] 进行通信
inter-process communication 的形式.和/或 p1[foo] 可能
注意 p1.1[bar] 还没有结束时耗时。在这些方式中的一种或其他方式中,p1[foo] 可能会确定
p1.1[bar] 有问题,持续太久,决定 kill p1.1 本身。
当 p1.1 被杀时——不管是谁干的——或根据自己的意愿结束, wait/waitpid将该信息返回给 p1[foo],然后它
可能会自行退出,或继续做其他事情。

在您询问的评论中:

can't we design [execve] like : return 1 if the child process is terminated?



像这样的系统调用当然可以设计,并且已经存在,但它不能
是替代调用进程的非阻塞系统调用,即 execve是。这将是一个阻塞系统调用,它运行调用的子进程
进程并将子进程的退出状态返回给父进程。这样做的人是 system

关于c - 在 C 中使用 execve 加载程序时子进程如何终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53315081/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com