进程组

进程组

(1)进程组,也称之为作业,BSD与1980年前后向UNIX中增加的一个新特性,代表一个或多个进程的集合。每个进程都属于一个进程组,在waitpid函数和kill函数的参数中都曾经使用到,操作系统设计的进程组的概念,是为了简化对多个进程的管理。

当父进程创建子进程的时候,默认子进程与父进程属于同一个进程组,进程组ID等于进程组第一个进程ID(组长进程)。所以,组长进程标识:其进程组ID等于其进程ID.
组长进程可以创建一个进程组,创建该进程组的进程,然后终止,只要进程组中有一个进程存在,进程组就存在,与组长进程是否终止无关。

(2)kill发送给进程组
使用 kill -n -pgid 可以将信号 n 发送到进程组 pgid 中的所有进程。例如命令 kill -9 -4115 表示杀死进程组 4115 中的所有进程。

进程组操作函数

1. getgrp函数:获取当前进程的进程组

pid_t getpgrp(void);

2. getpgid函数:获取进程的进程组ID

pid_t getpgid(pid_t pid);

分析:

  • 如果pid = 0,那么该函数作用和getpgrp一样

3.  setpgid函数作用:改变进程默认所属的进程组,通常可用来加入一个现有的进程组或新进程组。

int setpgid(pid_t pid, pid_t pgid);

分析:将参数1对应的进程,加入参数2对应的进程组中。

注意:

  • 如改变子进程为新进程组,用fork后,exec前。
  • 权级问题:非root进程只能改变自己创建的子进程,或有权限操作的进程。

ps ajx命令查看系统中的进程,参数a表示不仅列出当前用户的进程,也列出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j列出与作业控制相关的信息。

注意:组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程。

1. 测试代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4  
 5 int main()
 6 {
 7     pid_t pid;
 8     if ((pid = fork()) < 0) 
 9     {
10         perror("fork");
11         exit(1);
12     }
13     else if (pid == 0) 
14     {
15         printf("child PID = %d
", getpid());
16         printf("child Group ID = %d
", getpgid(0)); //返回组id
17         sleep(7);
18         printf("-------Group ID of child  id change to %d
", getpgid(0));
19         exit(0);
20     }
21     else if (pid > 0) 
22     {
23         sleep(1);
24         setpgid(pid, pid); //让子进程自立门户,成为进程组组长,以它的pid为进程组 id 
25  
26         sleep(13);
27         printf("
");
28         printf("parent PID = %d
", getpid());
29         printf("parent's parent PID = %d
", getppid());
30         printf(" parent Group ID = %d
", getpgid(0));
31  
32         sleep(5);
33         setpgid(getpid(), getppid());  //改变父进程组id为父进程的父进程
34         printf("
-------Group ID of parent is change to %d
", getpgid(0));
35  
36         while (1);
37     }
38     return 0;
39 }

输出结果:

进程组的应用

原文地址:https://www.cnblogs.com/sunbines/p/10263513.html