繁体   English   中英

Printf和fork:即使使用wait(NULL)时,顺序也错误

[英]Printf and fork: wrong ordering, even when wait(NULL) is used

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

一些代码:主要和接受输入功能

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> ls &
shw> debug  Makefile  obj  release  rpi-release  src

半预期的:由于父级继续运行而无需等待该过程,因此在ls输出之前会打印shw。 但是之后:

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() ,您知道您正在等待一个特定的孩子,但是您没有告诉您wait它,因此它将只等待第一个完成的孩子。 最终等待的孩子可能是先前发起的异步孩子,该孩子已经完成但状态尚未获得。

因此,这里有一个重要原则: 每个孩子都必须在某个时候获得收成。 如果您wait(2)每个孩子wait(2) ,您将积累僵尸进程:实际上已经死了但仍在OS进程列表中的进程,因为它们的状态尚未恢复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM