设置进程组阻止子进程启动

Setting process group prevents child process from starting

所以我正在尝试创建一个基本终端,我的问题是:如果我使用以下代码执行大多数 "normal" 终端命令(例如 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 在这里失败吗?

vim 会尝试从控制终端读取,因为它的进程组不是前台进程组,所以它会收到一个 SIGTTIN 信号来暂停它。 ls 和其他 "normal" 命令不会被挂起,因为它们不从标准输入(在本例中是终端)读取。

setpgrp() 调用的作用是创建一个以调用进程为首的新进程组——并且新进程组不是终端上的前台进程组,直到您使用 tcsetpgrp() 或 ioctl(TIOCSPGRP).

您可以阅读有关作业控制的更多信息 here. Especially this,这解释了为什么后台程序在尝试从 tty 读取时会收到 SIGTTIN,但在尝试写入时不会收到 SIGTTOU .