1. 会话组成
一个会话可能由一个或者多个进程组构成
限定条件:
- 一个会话最多有(可能没有)一个控制终端(真实终端或者伪终端);
- 终端被一个进程组持有,该进程组成为前台进程组,其它的进程组为后台进程组;
- 终端键入的信号对递送给前台进程组
- 终端断开连接,挂断信号递送给会话首领
2. 创建会话
#include <unistd.h>
pid_t setsid(void);
-
限定条件
调用进程不可以是process group leader,否则调用失败,返回-1 -
调用结果
- 调用进程会成为一个会话的首领,即 session leader
- 调用进程会成为组长进程,即group leader
- 调用进程如果本来有控制终端,那么调用进程将丢失该终端
#include <iostream>
using namespace std;
extern "C"
{
#include <unistd.h>
}
int main(void)
{
int res = 0;
pid_t pid = fork();
if(-1 == pid)
{
cout << "fork failed" << endl;
res = -1;
goto End;
}
if(pid == 0)
{
/*child*/
cout << "Child: pid = " << getpid()
<< " group = " << getpgrp()
<< " session = " << getsid(0) << endl;
/**/
res = setsid();
if(res == -1)
{
cout << "setsid failed" << endl;
goto End;
}
else
{
cout << "new session: pid = " << getpid()
<< " group = " << getpgrp()
<< " session = " << getsid(0) << endl;
execlp("leader","new session",NULL);
}
}
else
{
while(1)
{
/*father*/
sleep(5);
cout << "Father: pid = " << getpid()
<< " group = " << getpgrp()
<< " session = " << getsid(0) << endl;
}
}
End:
return res;
}
输出结果:
Child: pid = 17901 group = 17900 session = 17438
new session: pid = 17901 group = 17901 session = 17901
Father: pid = 17900 group = 17900 session = 17438
子进程创建新的会话前,其父进程是组长进程,并且子进程和父进程都属于会话 17438
子进程创建新的会话后,子进程成为组长进程,同时成为会话首领
(这时候使用ps命令会发现,新的会话没有控制终端)
3. 获取/设置 前台进程组
g++ main.cpp -o main
执行 ./main
首先:
Shell 执行main时,main进程成为组长进程,并且是前台进程组长进程
其次:
main执行时,fork出一个子进程,子进程从组中分离出去,单独成为一个组(后台进程组)
最后:
父进程异步的把控制终端丢给子进程,最终子进程成为前台进程组,父进程组成为后台进程组
现象:
这个时候使用CTRL + C ,发现子进程被杀死(Zombie),父进程正常运行
/*main.cpp*/
#include <iostream>
extern "C"
{
#include <unistd.h>
#include <stdio.h>
}
using namespace std;
int main(void)
{
pid_t child = fork();
cout << "origin process" << endl;
if(-1 == child)
{
cout << "fork failed" << endl;
return -1;
}
if(0 == child)
{
/*child*/
cout << "P1:child pid = " << getpid()
<< " group pid = " << getpgrp()
<< " front_gpid = " << tcgetpgrp(STDIN_FILENO);
/*seperate group*/
if( -1 == setpgid(0,0))
{
cout << "setgpid failed for child" << endl;
return -1;
}
int cnt = 2;
int pid = getpid();
int pgrp = getpgrp();
while(1)
{
sleep(1);
char arr[1024];
sprintf(arr,"P%d:child pid = %d,group pid = %d,front_group = %d",cnt++,pid,pgrp,tcgetpgrp(STDIN_FILENO));
cout << arr << endl;
}
}
else
{
/*father process*/
cout << "father pid = " << getpid()
<< " group pid = " << getpgrp()
<< " front_gpid = " << tcgetpgrp(STDIN_FILENO) << endl;
/*set child as front*/
if(-1 == tcsetpgrp(STDIN_FILENO,child))
{
cout << "set child as front failed" << endl;
}
while(1)
{
sleep(1);
}
}
return 0;
}