进程组和组长进程

进程组

  • 一个或多个进程的集合;
  • 可以接受同一终端的各种信号,同一信号发送进程组就等于发送给组中的所有进程;
  • 每个进程组有一个唯一的进程组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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值