会话(session)是一个或者多个进程组的集合。可以具有下图所有的安排,其中,一个会话中有3个进程组。
上图的安排可能由以下形式的shell命令形成的:
proc1 | proc2 &
proc3 | proc4 | proc5
进程调用setsid函数建立一个新会话。
#include
pid_t setsid(void); //若成功则返回进程组ID,出错则返回-1.
1.如果调用此函数的进程不是一个进程组组长,则此函数就会创建一个新会话,结果将发生下面三件事:
a.该进程变成新会话首进程(session leader)。(会话首进程是创建该会话的进程)此时,该进程是新会话中的唯一进程。
b.该进程称为一个新进程组的组长进程,新进程组ID是该调用进程的进程ID。
c.该进程没有控制终端,如果在调用setsid之前该进程有一个控制终端,那么这种联系也会被中断。
2.如果该调用进程已经是一个进程组的组长,则此函数返回出错。为了保证不会发生这种情况,通常先调用fork,然后使其父进程
终止,则子进程则继续。因为子进程继承了父进程的进程组ID,而其进程ID是新分配的,保证了子进程不会是一个进程组的组长。
getsid函数返回会话首进程的进程组ID。
#include
pid_t getsid(pid_t pid); //若成功则返回会话首进程ID,出错则返回-1.
若pid是0,则返回调用进程的会话首进程的进程组ID。
实践:
#include
#include
#include
#include
int main(){
pid_t pid;
if((pid=fork())<0){
perror("fork");
return -1;
}else if(pid == 0){
pid_t sid;
sid = getsid(0);
printf("in child(before setsid) sid=%d\n",sid);
sid = setsid();
printf("in child(after setsid) sid=%d\n",sid);
printf("in child sid=%d,pgrpid=%d,pid=%d\n",sid, getpgrp(),getpid());
exit(0);
}
pid_t sid;
sid = setsid();
printf("in parent sid=%d,pgrpid=%d,pid=%d\n",sid,getpgrp(),getpid());
sid = getsid(0);
printf("in parent sid=%d\n",sid);
sid = getsid(pid);
printf("in parent get child sid=%d\n",sid);
sid = getsid(1);
printf("in parent get init sid=%d\n",sid);
waitpid(pid,NULL,0);
return 0;
}
运行结果:
在父进程中,调用setsid,因为该进程是进程组组长(pid和pgrpid都是7084),所以返回-1。
获取父进程sid是6851。
在父进程中获取子进程sid也是6851。
在父进程中获取init的sid是1。(好像能获取任何进程的sid)
在子进程中获取sid是6851(此时和父进程子在同一个会话中)
在子进程中setsid后,子进程处在新的会话中,新会话的ID是7085,
在子进程中获取sid是7085,进程组ID和进程ID都是7085,说明该子进程是会话中的第一个进程,而且是进程组的组长。