1. 进程组
- 概念
进程组是一个或多个进程的集合。
- kill发送给进程组
使用 kill -n -pgid
可以将信号 n 发送到进程组 pgid 中的所有进程。例如命令 kill -9 -4115
表示杀死进程组 4115 中的所有进程。
2. 进程组的创建与设置
pid_t getpgrp(void);
返回:调用进程的进程组ID.
返回:调用进程的进程组ID.
pid_t getpgid(pid_t pid);
返回:进程pid所在进程组的ID,出错返回-1;
setpgid(pid, pid)
进程调用setpid可以加入一个现有的进程组或者创建一个新进程组。
3. 程序清单
题目:利用进程扇完成一个小实验。该进程扇有 1 个父进程和 3 个子进程,我们希望达到图 1 中的效果,即将进程 0 (父进程)和进程 1 设置成一组,假设为组 1,将进程 2 和 进程 3 设置成另一个组,假设为组 2. 另外,我们希望进程 0 和进程 2 分别是这两个组的组长。
3.1 错误代码:
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
int pid, i;
int group1, group2;
// 设置父进程(进程 0)为组长
setpgid(getpid(), getpid());
group1 = getpgid(getpid());
for (i = 1; i <= 3; ++i) {
pid = fork();
if (pid == 0) {
// child
if (i == 1) {
// 如果 group1 根本不存在,就会出问题。
// 比如进程 0 已经运行结束。
setpgid(getpid(), group1);
}
else if (i == 2) {
setpgid(getpid(), getpid());
group2 = getpgid(getpid());
}
else if (i == 3) {
// 试想如果进程 2 还没运行,进程 3 先运行了,
// 这时候 group2 还未进行设置,这里就会有问题。
// 或者进程 2 已经结束,那进程 3 的设置也会失败
setpgid(getpid(), group2);
}
break;
}
else if (pid < 0) {
perror("fork");
return -1;
}
}
printf("%d, pid: %d -> ppid: %d, pgid: [%d]\n", i%4, getpid(), getppid(), getpgid(getpid()));
while(1)
sleep(3);
return 0;
}
输出结果:
扫描二维码关注公众号,回复:
3680632 查看本文章
![](/qrcode.jpg)
3.2 正确代码:
#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 中的效果,即将进程 0 (父进程)和进程 2 设置成一组,假设为组 1,将进程 1 和 进程 3 设置成另一个组,假设为组 2. 另外,我们希望进程 0 和进程 1 分别是这两个组的组长。
3.3 测试代码
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
int pid, i;
int group1, group2;
setpgid(getpid(), getpid());
group1 = getpgid(getpid());
for (i = 0; i < 3; ++i) {
pid = fork();
if (pid > 0) {
// father
if (i == 0) {
setpgid(pid, pid);
group2 = getpgid(pid);
}
else if (i == 1) {
setpgid(pid, group1);
}
else if (i == 2) {
setpgid(pid, group2);
}
break;
}
else if (pid == 0) {
// child
if (i == 0) {
setpgid(getpid(), getpid());
group2 = getpgid(getpid());
}
else if (i == 1) {
setpgid(getpid(), group1);
}
else if (i == 2) {
setpgid(getpid(), group2);
}
}
else if (pid < 0) {
perror("fork");
return -1;
}
}
printf("进程 %d, pid: %d -> ppid: %d, pgid: [%d]\n", i, getpid(), getppid(), getpgid(getpid()));
while(1) sleep(1);
return 0;
}
输出结果: