28.1 介绍
28.1.1 概念
- 自动接受终端信号的组称为前台进程组
- 在终端通过 ctrl + c 等动作产生的信号首先被前台进程组接受
- 在 shell 启动的若干个进程组默认是父进程所在的组为前台进程组
- 除非是默认,否则都要通过调度才能成为前台进程组
28.1.1 函数 tcgetpgrp 和 tcsetpgrp
(1)tcgetpgrp 函数---获得前台进程组ID
#include <unistd.h>
int tcgetpgrp(int fd);
- 函数功能:获得前台进程组 ID
- 返回值:若成功返回前台进程组ID,出错返回 -1
(2)tcsetpgrp 函数---设置前台进程组ID
#include <unistd.h>
int tcsetpgrp(int fd, pid_t pgrpid);
- 函数功能:使用 pgrpid 设置前台进程组ID,fd 必须引用该会话的控制终端,0 代表当前正在使用的终端
- 返回值:成功返回 0,出错返回 -1
28.2 例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h> int main(void)
{
pid_t group1,group2; //创建进程组1,父进程作为组长进程
setpgid(getpid(), getpid());
group1 = getpgid(getpid()); pid_t pid;
int i = ;
for(; i < ; i++) {
pid = fork();
if(pid < ) {
perror("fork error");
exit();
} else if(pid > ) {
if(i == ) {
setpgid(pid, pid);
group2 = getpgid(pid);
} if(i == ) {
setpgid(pid, group2);
} if(i == ) {
setpgid(pid, group1);
}
} else { if(i == ) {
setpgid(getpid(), getpid());
group2 = getpgid(getpid());
} if(i == ) {
setpgid(getpid(), group2);
} if(i == ) {
setpgid(getpid(), group1);
} break;
}
} printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid());
pause(); exit();
}
编译执行
查询下进程:
按下 ctrl-c 停止运行的进程
然后再查看进程:
8956 和 8959 为默认进程组 group1,执行完 ctrl +c 后关闭,但是 group2 没有关闭,可以发现进程组默认是父进程那一组
进行设置 group2 为前台进程组
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h> int main(void)
{
pid_t group1,group2; //创建进程组1,父进程作为组长进程
setpgid(getpid(), getpid());
group1 = getpgid(getpid()); pid_t pid;
int i = ;
for(; i < ; i++) {
pid = fork();
if(pid < ) {
perror("fork error");
exit();
} else if(pid > ) {
if(i == ) {
setpgid(pid, pid);
group2 = getpgid(pid);
} if(i == ) {
setpgid(pid, group2); //将 group2 设置为前台进程组
tcsetpgrp(, group2);
} if(i == ) {
setpgid(pid, group1);
}
} else { if(i == ) {
setpgid(getpid(), getpid());
group2 = getpgid(getpid());
} if(i == ) {
setpgid(getpid(), group2); tcsetpgrp(, group2);
} if(i == ) {
setpgid(getpid(), group1);
} break;
}
} printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid());
pause(); exit();
}