设置进程组可防止子进程启动

时间:2018-09-15 20:20:26

标签: c terminal process fork exec

因此,我试图创建一个基本的终端,而我的问题是:如果我使用以下代码执行大多数“常规”终端命令(例如lscat等),没有问题。它设置了流程组并完美运行。但是,当我尝试执行诸如vim .之类的命令时,该过程似乎立即停止。如果我取消对setpgrp()的调用,该命令将按预期工作(并与控制终端的pgid执行)。

这是我的代码:

pid_t normal_cmd(char **argv, int bg) {
    int pid = fork(), status;
    if(pid < 0)
            unix_error("Could not fork child process");
    else if(!pid) { //child (this is the problematic area)
            setpgrp();
            status = execvp(argv[0], argv);
            if(status < 0)
                    unix_error("Could not exec child process");
    }
    else { //parent
            if(!bg) {
                    addjob(jobs, pid, FG);
                    pause(); //waitpid() is in SIGCHLD handler
                    struct job_t *cj = getjobpid(jobs, pid);
                    if(cj && cj->state != ST)
                            deletejob(jobs, pid);
            }
            else
                    addjob(jobs, pid, BG);
    }
    return pid;
}

您知道为什么更改进程组会导致vim在此处失败吗?

1 个答案:

答案 0 :(得分:1)

vim将尝试从控制终端读取数据,并且由于其进程组不是前台进程组,因此它将收到SIGTTIN信号,该信号将挂起它。 ls和其他“正常”命令不会被挂起,因为它们不会从标准输入(在本例中为终端)中读取。

setpgrp()调用的作用是创建一个以调用进程作为其领导者的新进程组-并且新进程组不是终端上的前台进程组,除非您使用 tc进行创建 setpgrp()或ioctl(TIOCSPGRP)。

您可以阅读有关作业控制here的更多信息。尤其是this,它解释了为什么后台程序试图从tty中读取时收到SIGTTIN,而试图向tty中写入却没有SIGTTOU的原因。