Shell程序中的fork()和wait()

时间:2014-01-16 21:49:35

标签: c linux shell fork

我是C编程新手,我正在尝试创建一个“shell”,使用fork()创建子进程,execvp发送命令。我的目标是使我的程序能够同时运行进程,并等待。

例如,如果我输入emacs test.sml,我希望我的shell打开带有此文件的emacs,并等待用户结束emacs。 (创建一个新的孩子,然后父母等待孩子完成)

但是,如果我输入emacs test.sml &,那么我希望我的shell打开emacs,然后准备好接受新命令,即使用户保持emacs打开。 (创建一个新子项,然后父项已准备好进行新输入)。

我到目前为止编写的代码就是这样做的,但似乎wait()只适用于第一个孩子。如果我执行以下操作:

  1. - > emacs
    • 父母等待(根据需要)
  2. - > emacs &
    • 父母不等待(根据需要)
  3. - > emacs
    • 父母不等待(不受欢迎)。
  4. 这是我的主要代码。安装程序获取用户输入,但在此处不相关:

    int main(void)
    {
        char inputBuffer[MAX_LINE];
        int background;
        char *args[MAX_LINE/+1];
    
        while(1) {
            background = 0;
    
            int mainpid = getpid();
            printf("My PID is %d\n",mainpid);
            printf(" COMMAND->\n");
            setup(inputBuffer,args,&background);
    
            pid_t pid; //Setting the PID
            pid = fork();
    
            if(pid < 0)
            {
                fprintf(stderr, "Fork Failed");
            }
            //background is 1 if the command ends with &
            if(background == 1)
            {
                if(pid==0)
                {
                    printf("Child should run concurrently with parent\n");
                    int pid = getpid();
                    int ppid = getppid();
                    printf("Child PID %d\n", pid);
                    printf("Child PPID %d\n", ppid);
                    execvp(inputBuffer, args);
                    exit(1);
                }
                else
                {
                    printf("Parent not waiting\n");
                    int pid = getpid();
                    printf("Parent PID %d\n", pid);
                }
            }
            else if(background != 1)
            {
                if(pid==0)
                {
                    printf("Child running and parent waiting\n");
                    int pid = getpid();
                    int ppid = getppid();
                    printf("Child PID %d\n", pid);
                    printf("Child PPID %d\n", ppid);
                    execvp(inputBuffer, args);
                    exit(1);
                }
                else
                {
                    printf("Parent WAIT\n");
                    wait(NULL);
                    printf("Parent done waiting\n");
                    int pid = getpid();
                    printf("Parent PID %d\n", pid);
                }
            }
        }
    }
    

    任何帮助非常感谢

2 个答案:

答案 0 :(得分:3)

如果你在后台运行一个进程,而不是等待,稍后它可能会(将)死掉。此时,您可能正在等待同步启动的另一个进程。

您应该循环调用wait()waitpid(),查找您刚开始的流程的PID,并清理其他僵尸流程:

int status;
int corpse;

while ((corpse = waitpid(-1, &status, 0)) > 0 && corpse != new_pid)
    ...process the death of 'corpse' with exit status 'status'...

循环体中的处理可能与分号一样微不足道;它可能会从后台运行的进程列表中移除尸体(也许可能会带入前台)等等。虽然你可以指定new_pid作为waitpid()的第一个参数,当你不需要这样做时,你会把其他进程当作僵尸。在某些时候,你必须清理僵尸 - 当你等待其他东西完成时更好?您可以改为使用wait()

while ((corpse = wait(&status)) > 0 && corpse != new_pid)

答案 1 :(得分:0)

execvp()可能会失败。如果失败,可能看起来父母没有等待

请尝试更改此

execvp(inputBuffer, args);
exit(1);

if(execvp(inputBuffer, args)<0)
{
    printf("\n execvp failed");
    exit(1);
}

并查看