C 等待(NULL)函数不工作,并且父进程总是在子进程之前运行

C 等待(NULL)函数不工作,并且父进程总是在子进程之前运行,c,linux,unix,process,C,Linux,Unix,Process,我对以下代码有问题。 它类似于在Unix平台上使用C进行手动shell程序实现。如果用户输入命令,它应该执行并返回相应的结果。 如果用户在末尾输入“&”,则父进程无需等待子进程完成 #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <signal.h> #include <stdlib.h> #include <string.h>

我对以下代码有问题。 它类似于在Unix平台上使用C进行手动shell程序实现。如果用户输入命令,它应该执行并返回相应的结果。 如果用户在末尾输入“
&
”,则父进程无需等待子进程完成

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

#define HISTORY_LIMIT 20
#define BUFFER_LIMIT 100
#define MAX_WORDS 50

int count = 0;
char history[HISTORY_LIMIT][BUFFER_LIMIT];

int tokenize(char *str, char **args, int *bRun)
{
    int i, argc = 0;
    char *token;
    if (count == HISTORY_LIMIT)
    {
        // alignHistory();
    }
    // strcpy(history[count],str);
    count++;
    token = strtok(str, " \t\n");
    for (i = 0; token != NULL; i++)
    {
        args[i] = token;
        token = strtok(NULL, " \t\n");
        argc++;
    }

    for (i = 0; i < argc; i++)
    {
        if (strcmp(args[i], "&") == 0)
        {
            *bRun = 1;
            args[i] = NULL;
        }
    }

    return argc;
} // end of tokenize function

void handleSignal(int sign)
{
    if (sign == SIGINT)
    {
        // getHistory();
    }
}  // end of handlesignal

int main(void)
{
    char *args[MAX_WORDS];
    char buffer[BUFFER_LIMIT];
    pid_t pid;
    int argc;
    int bgRun = 0;
    if (signal(SIGINT, handleSignal) == SIG_ERR)
    {
        printf("can't handle ctrl-c");
        return 0;
    }
    while (1)
    {
        bgRun = 0;
        memset(args, 0, MAX_WORDS);
        printf("osh>");
        fgets(buffer, BUFFER_LIMIT, stdin);
        argc = tokenize(buffer, args, &bgRun);
        if (argc == 0)
            continue;

        if (strcmp(args[0], "exit") == 0)
            break;
        if (strcmp(args[0], "history") == 0)
            getHistory();
        // else if(strcmp(args[0],"hello")==0)printf("Hi There, How are you ?\n");
        else
        {
            pid = fork();

            if (pid == 0)
            {
                execvp(args[0], args);
                return 0;
            }
            else
            {
                if (bgRun == 0)
                    wait(NULL);
            }
        }
    }
}
但是所需的结果应该是这样的(if&用于命令)

所以我使用了
bgRun
int变量,并在命令有1时赋值1 但这不起作用。我认为这是
等待(NULL)
的问题。请从这个恶魔那里救我。

您没有说要等待哪个子进程,所以第三个命令(不应该是后台命令)被认为在第二个命令退出时完成

哎呀


您需要处理
SIGCHLD
并在后台进程终止时获取后台进程,还需要检查退出的进程是否是当前正在运行的“前台”进程,而不是正在完成的后台作业
waitpid()
允许您等待特定流程。

您能澄清一下吗?实际产出和预期产出之间的实质性差异是什么?我可以看到明显的区别,但不清楚为什么一个是正确的输出,而另一个不是。请修改代码的格式-如果没有适当的缩进,很难阅读。我的意图是如果命令中添加了&则父进程不必等待子进程完成,但如果您观察预期与获得的o/p的最后四行..我已输入“whoami&”,并单击enter(因为它是“&”父进程不应该等待子进程,所以它首先被执行,“osh>”在“root”之前被打印),直到现在一切都很好。但问题出现在下一步,我输入了“whoami”,这里父进程应该等待子进程执行,因为我使用了wait(null),但不幸的是父进程没有等待,所以我得到了o/p“osh>”在rootAnd之前,OP可能需要注意它甚至不知道它有过的孩子(我对一个进程做了这件事——是故意的,不是偶然的)。你必须检查
wait()
是否返回了你期望的PID,如果没有,决定怎么做。盲目地忽略返回值是不好的。通常,
wait(NULL)
也很糟糕;您经常想知道孩子终止的原因/方式。对于调试来说,这是至关重要的;您需要捕获PID和状态并报告它们,以便知道发生了什么。@JonathanLeffler如果您能解释我在代码中必须做的更改,那就太好了。请在他的代码中提及任何需要更改的代码@Ben Voigt
osh>whoami
root
osh>whoami &
osh>root
whoami
osh>root
osh>whoami
root
osh>whoami &
osh>root
whoami
root    
osh>