process group - 进程组
session - 会话
controlling terminal - 控制终端
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/resource.h>
int
main()
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
/*
* Clear file creation mask.
*/
umask(0);
/*
* Get maximum number of file descriptors.
*/
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
exit(1);
/* [1] */
sleep(5);
/*
* Become a session leader to lose controlling TTY.
*/
if ((pid = fork()) < 0)
exit(1);
else if (pid != 0) /* parent */
exit(0);
/* [2] */
sleep(5);
setsid();
/* [3] */
sleep(5);
/*
* Ensure future opens won't allocate controlling TTYs.
*/
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
exit(1);
if ((pid = fork()) < 0)
exit(1);
else if (pid != 0) /* parent */
exit(0);
/* [4] */
sleep(5);
/*
* Change the current working directory to the root so
* we won't prevent file systems from being unmounted.
*/
if (chdir("/") < 0)
exit(1);
/*
* Close all open file descriptors.
*/
if (rl.rlim_max == RLIM_INFINITY)
rl.rlim_max = 1024;
for (i = 0; i < rl.rlim_max; i++)
close(i);
/*
* Attach file descriptors 0, 1, and 2 to /dev/null.
*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
/*
* Initialize the log file.
*/
openlog(NULL, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
syslog(LOG_ERR, "unexpected file descriptors %d %d %d",
fd0, fd1, fd2);
exit(1);
}
return 0;
}
/*
[1] 父进程:新建进程组(并且是进程组组长),与bash处于同一回话(bash为session leader)
$ ps -u hwx -o pid,ppid,pgid,sid,comm
PID PPID PGID SID COMMAND
1038 1037 1038 1038 bash
1425 1038 1425 1038 a.out
[2] 第一个子进程,新建回话之前:与父进程处于同一进程组(但不是进程组组长),与bash处于同一回话
$ ps -u hwx -o pid,ppid,pgid,sid,comm
PID PPID PGID SID COMMAND
1038 1037 1038 1038 bash
1427 1 1425 1038 a.out
[3] 第一个子进程,新建回话之后:新建回话(成为session leader),新建进程组(进程组组长)
$ ps -u hwx -o pid,ppid,pgid,sid,comm
PID PPID PGID SID COMMAND
1038 1037 1038 1038 bash
1427 1 1427 1427 a.out
[4] 第二个子进程:既不是进程组组长,也不是session leader
$ ps -u hwx -o pid,ppid,pgid,sid,comm
PID PPID PGID SID COMMAND
1038 1037 1038 1038 bash
1432 1 1427 1427 a.out
*/
说明:
1、
pgid(process group ID) == pid of process group leader
sid(session ID) == pid of session leader
2、只有 非 group leader 才能创建 session(见 setsid())
3、如果一个进程能新建 session, 那么新建 session 的同时, 必定新建 process group, 并且使这个进程成为 session leader 和 process group leader
4、能获得控制终端(controlling terminal)的必定是 session leader, 因此,如果一个进程不是 session leader, 则这个进程不可能获得控制终端