进程关系:进程会话

1. 会话组成

一个会话可能由一个或者多个进程组构成
在这里插入图片描述
限定条件:

  1. 一个会话最多有(可能没有)一个控制终端(真实终端或者伪终端);
  2. 终端被一个进程组持有,该进程组成为前台进程组,其它的进程组为后台进程组;
  3. 终端键入的信号对递送给前台进程组
  4. 终端断开连接,挂断信号递送给会话首领
    在这里插入图片描述

2. 创建会话

#include <unistd.h>
pid_t setsid(void);

  • 限定条件
    调用进程不可以是process group leader,否则调用失败,返回-1

  • 调用结果

  1. 调用进程会成为一个会话的首领,即 session leader
  2. 调用进程会成为组长进程,即group leader
  3. 调用进程如果本来有控制终端,那么调用进程将丢失该终端
#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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值