gpt4 book ai didi

c - 即使使用 wait(NULL),Printf 和 fork : wrong ordering,

转载 作者:行者123 更新时间:2023-11-30 18:55:04 26 4
gpt4 key购买 nike

所以我正在创建一个非常简单的外壳包装器。主进程使用readline读取一行,然后将其解析为char*[],然后由execvp处理。 Fork 用于确保 execvp 运行后程序继续运行。如果命令以 & 结尾,则母进程不会等待 fork 完成才继续。如果末尾没有&,那么母亲会等待 child 完成。

一些代码:主要及输入接受函数

int main(){
//Welcome message
printf("Welcome to Bourne Shell Wrapper! Enter commands to run them, use ctrl+d to exit\n");
while(1){
//Prefering the complex readline over the easier scanf because of many functions that scanf does not offer.
char* line = readline("shw> ");
if (line == NULL) return 0;
struct Command command = parseInput(line);
if (command.params != NULL){
if (!runCommand(command)) return 1;
}
}

结构命令:

struct Command{
char async;
char** params;
};

运行命令的函数:

int runCommand(struct Command command){
//Fork, let the child run the command and the parent wait for the child to finish before returning
//The child has 0 as childPid, the mother has another positive value. Thats how we seperate them
pid_t childPid = fork();
if (childPid == -1){
printf("Failed to create child\n");
return 0;
} else if (childPid == 0){
if (execvp(command.params[0], command.params) == -1){
fprintf(stderr,"%s: ",strerror(errno));
printCommand(command);
}
return 1;
} else {
if (!command.async){
//This way the mother will wait until all her childeren are done before continuing
wait(NULL);
} else {
}
return 1;
}
}

所以,问题来了。当你不想异步时,这些东西可以工作:

Welcome to Bourne Shell Wrapper! Enter commands to run them, use ctrl+d to exit
shw> ls
debug Makefile obj release rpi-release src
shw>

正如预期的那样:母进程等待子进程返回,然后再次打印 shw> 。然后:

shw> ls &
shw> debug Makefile obj release rpi-release src

半预期:因为父级继续而不等待进程,所以 shw 在 ls 输出之前打印。但随后:

ls
shw> debug Makefile obj release rpi-release src

奇怪!父进程应该等到子进程完成后再重新打印 shw>,但它在子进程之前打印。

我不知道为什么会发生这种情况。有人能指出我正确的方向吗?根据记录,在没有使用 & 的情况下,一切都很完美。

最佳答案

您的评论说:

the mother will wait until all her childeren are done before continuing

但事实并非如此。 wait() 等待单个子进程,以先完成者为准(包括在 wait() 调用之前完成的子进程。)

总结一下:当您执行异步命令时,您不会等待子命令完成;而是会等待子命令完成。当您执行同步命令时,您会等待单个子项完成。总之,您 wait() 等待的子项数量少于您创建的子项数量。

当你调用 wait() 时,你知道你正在等待一个特定的子进程,但你没有告诉 wait ,所以它只会等待哪个 child 先完成。它最终等待的子级很可能是先前启动的异步子级,该子级已经完成但尚未获取其状态。

所以这里有一个重要的原则:每个 child 都必须在某个时刻被收获。如果您不为每个子进程wait(2),您将积累僵尸进程:实际上已经死亡但仍然存在于操作系统进程列表中的进程,因为它们的状态尚未检索。

关于c - 即使使用 wait(NULL),Printf 和 fork : wrong ordering,,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28650159/

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