setsid()函数说明
[root@iZn6p6j5eiblyzZ cyh]# man setsid
NAME
setsid - run a program in a new session
SYNOPSIS
setsid program [arg...]
DESCRIPTION
setsid runs a program in a new session.
说明:当进程是会话的进程组长进程时setsid()调用失败并返回(-1)。setsid()调用成功后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和进程组脱离。由于会话对控制终端的独占性,进程同时与控制终端脱离。
- 进程组介绍:每一个进程除了有一个进程ID之外,还属于一个进程组,进程组通常是一个或多个进程的集合。这些进程通常是与一个作业相关的。
[root@iZn6p6j5eiblyzZ cyh]# ps -o pid,pgid,sid,command|cat
PID PGID SID COMMAND
5681 5681 5617 su
5682 5682 5617 bash
5778 5778 5617 ps -o pid,pgid,sid,command
5779 5778 5617 cat
[root@iZn6p6j5eiblyzZ cyh]#
PGID标识着一个进程组,因为PID和PGID相等,所以ps 进程是进程组组长进程,cat 进程属于这一进程组下的进程。
实现与其父进程进程组和会话组脱离
-
失败例子
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
int main(int argc, char *argv[])
{
pid_t pid;
fprintf(stdout, "PID:%d, PGID:%d, SID:%d\n", getpid(), getpgrp(), getsid(0));
if(setsid() < 0)
{
fprintf(stderr, "setsid error:%s\n", strerror(errno));
}
while(1);
return 0;
}
[cyh@iZn6p6j5eiblyzZ ~]$
[cyh@iZn6p6j5eiblyzZ ~]$ ./llinux
PID:5980, PGID:5980, SID:5935
setsid error:Operation not permitted
上例中创建进程组失败,失败原因是当前进程是一个组长进程,而该函数是不允许组长进程调用的。
当进程是会话的进程组长进程时setsid()调用失败并返回(-1)。
正确例子
#include <unistd.h>
#include <stdio.h>
int main()
{
if(fork > 0)
{
while(1);
}
else
{
setsid();
while(1)
}
}
[cyh@iZn6p6j5eiblyzZ ~]$ ps -fu cyh
UID PID PPID C STIME TTY TIME CMD
cyh 3855 469 0 9月21 tty1 00:00:00 -bash
cyh 5934 5932 0 22:13 ? 00:00:00 sshd: cyh@pts/0
cyh 5935 5934 0 22:13 pts/0 00:00:00 -bash
cyh 5960 5935 0 22:14 pts/0 00:00:00 ps -fu cyh
[cyh@iZn6p6j5eiblyzZ ~]$ ./t_setsid &
[1] 5961
[cyh@iZn6p6j5eiblyzZ ~]$ ./t_setsid &
[2] 5962
[cyh@iZn6p6j5eiblyzZ ~]$ ps -o pid,pgid,sid,command
PID PGID SID COMMAND
5935 5935 5935 -bash
5961 5961 5935 ./t_setsid
5962 5962 5935 ./t_setsid
5964 5964 5935 ps -o pid,pgid,sid,command
[cyh@iZn6p6j5eiblyzZ ~]$
上面的例子使用setsid()函数成功创建了一个新的会话和一个新的进程组。以及新的进程组长, PGID : 5961和5962 。