二十七、Linux 進程與信號---進程組和組長進程


27.1 進程組

27.1.1 進程組介紹

  • 進程組為一個或多個進程的集合
  • 進程組可以接受同一終端的各種信號,同一個信號發送進程組等於發送給組中的所有進程
  • 每個進程組有唯一的進程組 ID
  • 進程組的消亡要等到組中所有的進程結束
  • 進程組的消亡:kill 發送信號給進程組
    • kill -9  -進程組號

27.1.2 進程組 ID 獲取--- getpgrp 和 getpgid

(1)getpgrp --- 獲取調用進程的進程組ID

1 #include <unistd.h>
2 pid_t getpgrp(void);
  • 函數說明
    • getpgrp()用來取得目前進程所屬的組識別碼。此函數相當於調用 getpgid(0);
  • 返回值
    • 返回目前進程所屬的組識別碼。

(2)getpgid --- 獲取 pid 所在進程組的 ID  

1 #include <unistd.h>
2 pid_t getpgid( pid_t pid);
  • 函數說明
    • getpgid()用來取得參數 pid 指定進程所屬的組識別碼。如果參數 pid 為0,則會取得目前進程的組識別碼。
  • 返回值
    • 執行成功則返回組識別碼,如果有錯誤則返回 -1 ,錯誤原因存於 errno 中。
  • 錯誤代碼
    • ESRCH 找不到符合參數 pid 指定的進程。
  • getpgid(getpid()) 獲取指定進程的進程組
  • getpgid(0) 獲取當前進程的進程組

27.2 組長進程

27.2.1 概念

  • 每個進程組可以有個組長進程,組長進程的ID就是進程組的ID
  • 組長進程可以創建進程組以及該組中的進程
  • 進程組的創建從第一個進程(組長進程)加入開始
  • 進程組的組號取第一個加入組的進程(組長進程)編號

27.2.2 設置進程組 ID--- setpgid(創建進程組或將指定進程加入到指定的進程組中)

1 #include <unistd.h>
2 int setpgid(pid_t pid,pid_t pgid);
  • 函數說明
    • setpgid() 將參數 pid 指定進程所屬的組 ID 設為參數 pgid 指定的組 ID。如果參數 pid 為 0 ,則會用來設置目前進程的組識別碼,如果參數 pgid 為0,則會以目前進程的進程 ID 來取代。
  • 函數功能:將進程加入到指定的進程組中, pid 為進程號, pgid 為組號
  • 返回值
    • 執行成功則返回組 ID,如果有錯誤則返回-1,錯誤原因存於 errno 中。
  • 錯誤代碼
    • EINVAL 參數 pgid 小於0。
    • EPERM 進程權限不足,無法完成調用。
    • ESRCH 找不到符合參數 pid 指定的進程。

27.3 例子

27.3.1 構建進程扇組

  構建一個進程扇,要求每兩個進程為一個進程組,如下所示

  

  

 1 #include <unistd.h>
 2 #include <fcntl.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <sys/wait.h>
 6 
 7 int main(void)
 8 {
 9 
10     //創建進程組,組長進程為父進程
11     setpgid(getpid(), getpid());
12 
13     /* 組1 */
14     // 或 pid_t group1 = getpgid(0);
15     pid_t group1 = getpgid(getpid());
16     pid_t group2;
17 
18     int i = 0;
19     pid_t pid;
20 
21     for(; i < 3; i++) {
22         pid = fork();
23         if(pid < 0) {
24             perror("fork error`");
25             exit(1);
26         } else if(pid > 0) {//父進程
27             //父進程中執行和子進程相同的操作
28             if(i == 0) {
29                 //要注意fork 在父進程中返回的是子進程的 pid
30                 setpgid(pid, group1);
31             }
32 
33             //第二個子進程作為組長進程,要創建進程組
34             if(i == 1) {
35                 setpgid(pid, pid);
36                 group2 = getpgid(pid);
37             }
38 
39             if(i == 2) {
40                 //第三個子進程加入到 group2
41                 setpgid(pid, group2);
42             }
43         } else {//子進程
44             //將第一個子進程加入到 group1
45             if(i == 0) {
46                 setpgid(getpid(), group1);
47             }
48 
49             //第二個子進程作為組長進程,要創建進程組
50             if(i == 1){
51                 setpgid(getpid(), getpid());
52                 group2 = getpgid(getpid());
53             }
54 
55             if(i == 2) {
56                 setpgid(getpid(), group2);
57             }
58 
59             //因為是進程扇,每一個子進程要退出循環
60             //父進程繼續循環 fork
61             break;
62         }
63     }
64 
65     printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid(0));
66 
67     //防止僵屍進程產生
68     for(i = 0; i < 3; i++) {
69         wait(0);
70     }
71 
72     exit(0);
73 }

  編譯運行:

  

27.3.2 構建進程鏈組

  

 1 #include <unistd.h>
 2 #include <fcntl.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <sys/wait.h>
 6 
 7 int main()
 8 {
 9     //創建進程組1,父進程為組長進程
10     setpgid(getpid(), getpid());
11     pid_t group1 = getpgid(getpid());
12 
13     pid_t pid;
14     int i = 0;
15     for(;i < 2; i++) {
16         pid = fork();
17         if(pid < 0) {
18             perror("fork error");
19             exit(1);
20         } else if(pid > 0) {
21             if(i == 0) {
22                 //創建進程組2,第一個子進程作為組長進程
23                 setpgid(pid, pid);
24             }
25 
26             if(i == 1) {
27                 //將第二個子進程加入到 group1中
28                 setpgid(pid, group1);
29             }
30 
31             // 在進程鏈中,父進程操作完退出循環
32             break;
33         } else if(pid == 0) {
34             
35             if(i == 0) {
36                 //創建進程組2,第一個子進程作為組長進程
37                 setpgid(getpid(), getpid());
38             }
39 
40             if(i == 1) {
41                 //將第二個子進程加入到 group1中
42                 setpgid(getpid(), group1);
43             }
44         }
45     }
46 
47     printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid(0));
48 
49     //防止僵屍進程產生
50     for(i = 0; i < 2; i++) {
51         wait(0);
52     }
53 
54     return 0;
55 }

  編譯運行:

  

27.3.3 進程組刪除

 1 #include <unistd.h>
 2 #include <fcntl.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <sys/wait.h>
 6 
 7 int main(void)
 8 {
 9     //創建進程組,父進程作為組長進程
10     setpgid(getpid(), getpid());
11 
12     pid_t pid = fork();
13     if(pid < 0){
14         perror("fork error");
15         exit(1);
16     } else if(pid > 0) {
17         //將子進程加入到父進程所在的組
18         setpgid(pid, getpgid(getpid()));
19     } else {
20         //將子進程加入到父進程所在的組
21         setpgid(getpid(), getpgid(getppid()));
22     }
23 
24     printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid(0));
25 
26     pause();//進程暫停,等待信號
27 
28     return 0;
29 }

  編譯運行:

(1)殺掉進程組

  

  

(2)殺掉父進程

  

  

  殺掉父進程后,子進程依然存在,只不過變成了孤兒進程,並被2323進程所領養

(3)殺掉子進程

   

  

  子進程變為了僵屍進程,子進程被殺死,但是父進程並沒有回收子進程。

  殺掉父進程:

  

  僵屍進程被回收

27.3.4 子進程不加入父進程組中

 1 #include <unistd.h>
 2 #include <fcntl.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <sys/wait.h>
 6 
 7 int main(void)
 8 {
 9     //創建進程組,父進程作為組長進程
10     setpgid(getpid(), getpid());
11 
12     pid_t pid = fork();
13     if(pid < 0){
14         perror("fork error");
15         exit(1);
16     } else if(pid > 0) {
17         //將子進程加入到父進程所在的組
18         setpgid(pid, getpgid(getpid()));
19     } else {
20         //將子進程加入到父進程所在的組
21         //setpgid(getpid(), getpgid(getppid()));
22     }
23 
24     printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid(0));
25 
26     pause();//進程暫停,等待信號
27 
28     return 0;
29 }

  編譯運行:

  

  

  沒有將子進程加入到組中,依然將子進程加入到父進程組了。

  注意:從 shell 上啟動一個父進程,然后從父進程上創建若干個子進程,默認情況下都加入到父進程所在的組中,組號就是父進程的 PID,組長就為父進程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM