3-进程组和组长进程---很好的解释了一个session中怎么出现多个进程组的,是通过setpgid创建进程组的

进程组

一个或多个进程的集合;
可以接受同一终端的各种信号,同一信号发送进程组就等于发送给组中的所有进程;
每个进程组有一个唯一的进程组ID;
进程组的消亡要等到组中所有的进程结束;
kill发送给进程组:kill -9 -进程组号(不要忘记负号)

相关函数   
  #include <unistd.h>

  pid_t getpgrp(void);--老版
  返回:调用进程的进程组ID;
  
  pid_t getpgid(pid_t pid);--新版
  返回:进程pid所在进程组的ID,出错返回-1;

组长进程

每个进程组可以有个组长进程,组长进程的ID就是进程组的ID;
组长进程可以创建进程组以及该组中的进程;
进程组的创建从第一个进程(组长进程)加入开始;
进程组的组号取第一个加入组的进程(组长进程)编号;

相关函数
  #include <unistd.h>
  
  int setpgid(pid_t pid, pid_t pgid);
  返回:成功返回0,出错返回-1;
  功能:将进程加入到指定的进程组中,pid为进程号,pgid为组号;

前台进程组

自动接收终端信号的组成为前台进程组;
在终端通过Ctrl+C等动作产生的信号首先被前台进程组接受;
在shell启动的若干个进程组默认是父进程所在的组为前台进程组;
除非是默认,否则都要通过调度才能成为前台进程组;

相关函数
  #include <unistd.h>

  pid_t tcgetpgrp(int fd);
  返回:若成功返回前台进程组的ID,出错返回-1;
  功能:获得前台进程组ID;

 
  int tcsetpgrp(int fd, pid_t pgrpid);
  返回:成功返回0,出错返回-1;
  功能:使用pgrpid设置前台进程组ID;
  fd必须引用该会话的控制终端,0代表当前正在使用的终端;

示例1:创建一个进程扇,并实现如下图所示的进程组。
在这里插入图片描述

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
 
// 创建一个进程扇,并实现如图所示的进程组分配
 
int main(void)
{
	setpgid(getpid(), getpid());
	pid_t group1 = getpgid(getpid());
	pid_t group2;
 
	int i = 0;
	for(; i < 3; ++i)
	{
		pid_t pid = fork();
		if(pid < 0)
		{
			perror("fork error");
			exit(1);
		}
		else if(pid > 0)
		{
			// parent process
			if(i == 0)
				setpgid(pid, group1);
			if(i == 1)
			{
				setpgid(pid, pid);
				group2 = getpgid(pid);
			}
			if(i == 2)
				setpgid(pid, group2);
		}
		else
		{
			// child process
			if(i == 0)
				setpgid(getpid(), group1);
			if(i == 1)
			{
				setpgid(getpid(), getpid());
				group2 = getpgid(getpid());
			}
			if(i == 2)
				setpgid(getpid(), group2);
			break;
		}
	}
	printf("pid:%d, ppid:%d, pgid:%d\n", getpid(), getppid(), getpgid(getpid()));
 
	for(int i = 0; i < 3; ++i)
		wait(0);
 
	return 0;
}

注意:
1.由于创建的是进程扇,所以每次子进程执行完毕后都需要退出循环;
2.我们需要在父进程与子进程中执行相同的操作,因为我们不知道是父进程先运行还是子进程先运行;

示例2:创建一个进程链,实现如下图所示的进程组。
在这里插入图片描述

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
 
// 创建一个进程链
 
int main(void)
{
	setpgid(getpid(), getpid());//将父进程设置为第一个进程组的组长进程
	pid_t group1 = getpgid(getpid());
 
	int i = 0;
	for(; i < 2; ++i)
	{
		pid_t pid = fork();
		if(pid < 0)
		{
			perror("fork error");
			exit(1);
		}
		else if(pid > 0)
		{
			// parent process
			if(i == 0)
			{
				setpgid(pid, pid);
			}
			if(i == 1)
			{
				setpgid(pid, group1);
			}
			break;
		}
		else
		{
			// child process
			if(i == 0)
				setpgid(getpid(), getpid());
			if(i == 1)
				setpgid(getpid(), group1);
		}
	}
	printf("pid:%d, ppid:%d, pgid:%d\n", getpid(), getppid(), getpgid(getpid()));
	sleep(1);
	return 0;
}

程序执行结果如下所示:
在这里插入图片描述

示例3:创建两个进程组,并将其中一个设置为前台进程组,如下图所示。
在这里插入图片描述

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
 
int main(void)
{
	setpgid(getpid(), getpid());
	pid_t group1 = getpgid(0); // 将当前进程设置为组长进程
	pid_t group2;
 
	int i = 0;
	for(; i < 3; ++i)
	{
		pid_t pid = fork();
		if(pid < 0)
		{
			perror("fork error");
			exit(1);
		}
		else if(pid > 0)
		{
			if(i == 0)
			{
				setpgid(pid, pid);
				group2 = getpgid(pid);
				tcsetpgrp(0, group2); // 将该进程组设置为前台进程组
			}
			if(i == 1)
				setpgid(pid, group2);
			if(i == 2)
				setpgid(pid, group1);
		}
		else
		{
			if(i == 0)
			{
				setpgid(getpid(), getpid());
				group2 = getpgid(getpid());
				tcsetpgrp(0, group2);
			}
			if(i == 1)
				setpgid(getpid(), group2);
			if(i == 2)
				setpgid(getpid(), group1);
			break;
		}
	}
	printf("pid:%d, ppid:%d, pgid:%d, fore_pgid:%d\n", getpid(), getppid(), getpgid(getpid()), tcgetpgrp(0));
 
	for(int i = 0; i < 3; ++i)
		wait(0);
 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值