孤儿进程组
孤儿进程组:该进程组中每一个进程的父进程都属于另一个session.
怎样创建孤儿进程组?
fork()后,子进程继承父进程的gid,然后父进程退出,那么子进程变成了孤儿进程,其所在的进程组也变成了孤儿进程组。
特性1:父进程终止后,进程组成为了孤儿进程组。那么新的孤儿进程组中处于停止(stopped)状态的每一个进程都会收到挂断(SIGHUP)信号,接着又收到继续(SIGCONT)信号。
也就是说,进程组成为孤儿进程组后,孤儿进程组中的状态为stopped的进程会被激活。前提是需要对SIGHUP信号自处理,对挂断信号系统默认的动作是终止进程。
特性2:孤儿进程组是后台进程组,且没有控制终端
特性3:孤儿进程组去读控制终端时,read返回出错并将errno设置为EIO。
只有前台作业能接收终端输入,如果后台作业试图读终端,那么这并不是一个错误,但是终端驱动程序将检测到这种情况,并且向后台作业发送一个特定的信号SIGTTIN。该信号通常会暂时停止此后台作业。由于孤儿进程组是后台进程组,如果内核用SIGTTIN信号停止它,那么进程组中的进程就再也不会继续了。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <sys/resource.h> 6 #include <unistd.h> 7 #include <fcntl.h> 8 #include <string.h> 9 #include <syslog.h> 10 #include <signal.h> 11 #include <errno.h> 12 13 static void sig_hup(int signo) 14 { 15 printf("SIGHUP received, pid=%d\n", getpid()); 16 } 17 18 static void pr_ids(char* name) 19 { 20 printf("%s: pid=%d, ppid=%d, pgrp=%d, tcgetpgrp=%d, sid=%d\n", name, getpid(), getppid(), getpgrp(), tcgetpgrp(STDIN_FILENO), getsid(0)); 21 fflush(stdout); 22 } 23 24 int main(void) 25 { 26 char c=0; 27 pid_t pid; 28 29 pr_ids("parent"); 30 31 if ((pid = fork())< 0) 32 { 33 perror("fork error"); 34 exit(1); 35 } 36 else if (pid > 0) 37 { 38 sleep(10); //sleep to let child stop itself 39 printf("parent exit\n"); 40 exit(0); 41 } 42 else 43 { 44 pr_ids("child"); 45 signal(SIGHUP, sig_hup);//establish signal handler 46 kill(getpid(), SIGTSTP);//stop ourself 47 pr_ids("child"); 48 if (read(STDIN_FILENO, &c, 1) != 1) 49 { 50 printf("read error from contorlling TTY, errno=%d\n", errno); 51 exit(0); 52 } 53 printf("c=%d\n",c); 54 } 55 }