Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Printf和fork:错误的排序,即使使用了wait(NULL)_C_Linux_Bash - Fatal编程技术网

C Printf和fork:错误的排序,即使使用了wait(NULL)

C Printf和fork:错误的排序,即使使用了wait(NULL),c,linux,bash,C,Linux,Bash,所以我创建了一个非常简单的shell包装器。主进程使用readline读取一行,然后将其解析为char*[],然后由execvp处理。Fork用于确保程序在execvp运行后继续运行。如果命令以&结束,则母进程在继续之前不会等待fork完成。如果最后没有&则母亲等待孩子完成 一些代码: 主要功能和输入接受功能 int main(){ //Welcome message printf("Welcome to Bourne Shell Wrapper! Enter commands

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

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

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;
    }
}
所以,问题出在这里。当您不想进行异步时,这些功能可以正常工作:

欢迎使用Bourne Shell包装器!输入运行命令,使用ctrl+d退出
shw>ls
调试Makefile obj release rpi release src
shw>
正如预期的那样:在再次打印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
,所以它只会等待哪个孩子先完成。它最终等待的子对象很可能是先前启动的异步子对象,该子对象已完成,但其状态尚未恢复

所以这里有一个重要的原则:每个孩子都必须在某个时候收获。如果不为每个子进程
等待(2)
,则会累积僵尸进程:实际上已死亡但仍在操作系统进程列表中活动的进程,因为尚未检索它们的状态