(1)概念和特性
进程组,也称之为作业。BSD于1980年前后向Unix中增加的一个新特性。代表一个或多个进程的集合。每个进程都属于一个进程组。在waitpid函数和kill函数的参数中都曾使用到。操作系统设计的进程组的概念,是为了简化对多个进程的管理。
当父进程,创建子进程的时候,默认子进程与父进程属于同一进程组。进程组的ID就是该进程组组长的ID,也就是父进程的ID。一个进程只有一个进程组ID,因此一个进程只能有一个进程组。PPID PID PGID 都大于0 。
可以使用kill -SIGKILL -进程组ID来将整个进程组内的进程全部杀死。(注意权限)
只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关。
进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组)。一个进程可以为自己或其它进程设置进程组ID,只要权限够,即root用户的进程可以设置所有进程的进程组ID。
(2)进程组操作函数
getpgrp函数:获取当前进程的进程组ID
pid_t getpgrp(void); 成功:返回调用者的进程组ID;失败:-1,设置errno
getpgid函数:获取指定进程的进程组ID(注意权限)
pid_t getpgid(pid_t pid); 成功:返回进程组ID;失败:-1,设置errno
如果pid = 0,那么该函数作用和getpgrp一样,获取当前进程的进程组ID。
setpgid函数
改变进程默认所属的进程组。通常可用来加入一个现有的进程组或创建一个新进程组。
int setpgid(pid_t pid, pid_t pgid); 成功:0;失败:-1,设置errno
将参1对应的进程,加入参2对应的进程组中(可以不存在)。
注意:如改变子进程为新的组,应fork后,exec前;权限问题,非root进程只能改变自己创建的子进程,或有权限操作的进程。
//修改子进程的进程组ID
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0) {
perror("fork");
exit(1);
} else if (pid == 0) {
printf("child PID == %d\n",getpid()); //子进程ID
printf("child Group ID == %d\n",getpgid(0)); // 返回组id
//printf("child Group ID == %d\n",getpgrp()); // 返回组id
sleep(7);
printf("----Group ID of child is changed to %d\n",getpgid(0));
exit(0);
} else if (pid > 0) {
sleep(1);
setpgid(pid,pid); //让子进程自立门户,成为进程组组长,以它的pid为进程组id
sleep(13);
printf("\n");
printf("parent PID == %d\n", getpid()); //父进程ID
printf("parent's parent process PID == %d\n", getppid()); //shell进程ID
printf("parent Group ID == %d\n", getpgid(0)); //父进程组ID
sleep(5);
setpgid(getpid(),getppid()); //改变父进程的组id为shell进程ID
printf("\n----Group ID of parent is changed to %d\n",getpgid(0));
while(1);
}
return 0;
}
[[email protected] 01_session_daemon_test]# ./setpgid
child PID == 19987
child Group ID == 19986
----Group ID of child is changed to 19987
parent PID == 19986
parent's parent process PID == 12137
parent Group ID == 19986
----Group ID of parent is changed to 12137