设置其他组ID后为什么不叫“读取”?

时间:2018-10-25 22:23:31

标签: c linux unix signals fork

在此程序中,我更改子进程的组ID。

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

int main(void) {
 int status;
 char b[4];
 pid_t pid, ch_pid;

 switch(pid=fork()) {
 case -1:
    perror("Fork failed");
    exit(1);
  case  0:
    printf("\nCHILD: This is child process!\n");
    printf("CHILD: My PID is-- %d\n", getpid());
    printf("CHILD: My parent PID -- %d\n", getppid());
    printf("CHILD: My GID is -- %d\n", getpgid(getpid()));
    printf("CHILD: My SID is -- %d\n", getsid(getpid()));
    int k = setpgid(getpid(),getpid()); /*Modifies group id. Therefore, when user press
             Cn+C, ChPr can't die*/
    printf("BEFORE SETPGRP CHILD: My GID is -- %d\n", getpgid(getpid()));
    printf("BEFORE SETPGRP CHILD: My SID is -- %d\n", getsid(getpid()));
    //read(0,b,4);
    //printf("b: %s\n",b);
    pause();
    exit(0);
  default:
    printf("PARENT: This is parent process!\n");
        printf("PARENT: My PID -- %d\n", getpid());
        printf("PARENT: My child PID %d\n",pid);
    printf("PARENT: My parent PID %d\n",getppid());
    printf("PARENT: My GID %d\n",getpgid(getpid()));
    printf("PARENT: My SID %d\n",getsid(getpid()));
    pause();
    exit(0);
 }
    return 0;
}

但是,当我尝试调用“ read”(带注释的字符串)时,bash终端不读取也不输出。但是,父进程正在读取成功。为什么?父子进程具有相似的会话ID。这意味着它们是由通用tty控制的。我注意到,如果我更改子进程的GID并按Cntrl + C,则父进程只会被打断,子进程将成为一个孤儿。因此,如果我取消注释程序中的“读取”并按Cntrl + C,则会杀死这两个进程。可能是不成功的读取呼叫向bash发送一些信号?谢谢!

2 个答案:

答案 0 :(得分:1)

终端具有前景处理组设置。当外壳程序运行命令时,它将在终端的前台进程组中运行前台作业,但是后台作业将放在其自己的进程组中。只允许前台进程组从终端读取。如果后台进程尝试读取,它将被挂起;当用户将其移至前台时,将终端进程组更改为该组,继续执行该进程,然后将其读取。有stty模式tostop可用于控制后台进程是否可以写入终端,但是没有类似的读取选项,因此始终被禁止。

如果希望更改终端的进程组后能够从终端读取该进程,则需要更改终端的前台进程组。这是通过tcsetpgrp()函数完成的。

tcsetpgrp(0, getpgid(getpid()));

答案 1 :(得分:0)

read(2)仅允许用于终端前台进程组中的进程  (这是与终端驱动程序中的终端相关联的进程组)。其他进程将停止,SIGSTOP驱动程序将信号tty发送给它们。一些控制字符也直接指向终端控制进程组。

有关tty控件的说明,请参见termios(4)tty(4)