(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()); //子进程IDprintf("child Group ID == %d\n",getpgid(0)); // 返回组id//printf("child Group ID == %d\n",getpgrp()); // 返回组idsleep(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为进程组idsleep(13);printf("\n");printf("parent PID == %d\n", getpid()); //父进程IDprintf("parent's parent process PID == %d\n", getppid()); //shell进程IDprintf("parent Group ID == %d\n", getpgid(0)); //父进程组IDsleep(5);setpgid(getpid(),getppid()); //改变父进程的组id为shell进程IDprintf("\n----Group ID of parent is changed to %d\n",getpgid(0));while(1);}return 0;
}
[root@localhost 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