【進程】進程組

一、進程組

1. 進程組

(1)進程組,也稱之為作業,BSD與1980年前后向UNIX中增加的一個新特性,代表一個或多個進程的集合。每個進程都屬于一個進程組,在waitpid函數和kill函數的參數中都曾經使用到,操作系統設計的進程組的概念,是為了簡化對多個進程的管理。

當父進程創建子進程的時候,默認子進程與父進程屬于同一個進程組,進程組ID等于進程組第一個進程ID(組長進程)。所以,組長進程標識:其進程組ID等于其進程ID.

組長進程可以創建一個進程組,創建該進程組的進程,然后終止,只要進程組中有一個進程存在,進程組就存在,與組長進程是否終止無關。

(2)kill發送給進程組

使用?kill -n -pgid?可以將信號 n 發送到進程組 pgid 中的所有進程。例如命令?kill -9 -4115?表示殺死進程組 4115 中的所有進程。


2. getpgid、getpgrp函數原型:

pid_t getpgrp(void);
pid_t getpgid(pid_t pid);

分析:

  • 函數1:獲取當前進程的進程組ID
  • 函數2:如果pid = 0,那么該函數作用和getpgrp一樣。

?

3. setpgid函數函數原型:改變進程默認所屬的進程組,通常可用來加入一個現有的進程組或新進程組。

int setpgid(pid_t pid, pid_t pgid);

分析:將參數1對應的進程,加入參數2對應的進程組中。

注意:

  • 如改變子進程為新進程組,用fork后,exec前。
  • 權級問題:非root進程只能改變自己創建的子進程,或有權限操作的進程。

4. 測試代碼:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main()
{pid_t pid;if ((pid = fork()) < 0) {perror("fork");exit(1);}else if (pid == 0) //子進程{printf("child PID = %d\n", getpid());printf("child Group ID = %d\n", getpgid(0)); //返回組idsleep(7);printf("-------Group ID of child  id change 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());printf("parent's parent PID = %d\n", getppid());printf(" parent Group ID = %d\n", getpgid(0));sleep(5);setpgid(getpid(), getppid());  //改變父進程組id為父進程的父進程printf("\n-------Group ID of parent is change to %d\n", getpgid(0));while (1);}return 0;
}

輸出結果:

?

二、進程組的應用

1. 實驗一:

題目:利用進程扇完成一個小實驗。該進程扇有 1 個父進程和 3 個子進程,我們希望達到圖 1 中的效果,即將進程 0 (父進程)和進程 1 設置成一組,假設為組 1,將進程 2 和 進程 3 設置成另一個組,假設為組 2. 另外,我們希望進程 0 和進程 2 分別是這兩個組的組長。? ?
?

1. 測試代碼:

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>int main() 
{int pid, i;int group1, group2;// 設置父進程(進程 0)為組長 setpgid(getpid(), getpid());group1 = getpgid(getpid());for (i = 1; i <= 3; ++i) {pid = fork();if (pid == 0)   child{if (i == 1) {// 如果 group1 根本不存在,就會出問題。// 比如進程 0 已經運行結束。setpgid(getpid(), group1);}else if (i == 2) {setpgid(getpid(), getpid());group2 = getpgid(getpid());}else if (i == 3) {// 試想如果進程 2 還沒運行,進程 3 先運行了,// 這時候 group2 還未進行設置,這里就會有問題。// 或者進程 2 已經結束,那進程 3 的設置也會失敗setpgid(getpid(), group2);}break;}else if (pid < 0) {perror("fork");return -1;}}printf("進程 %d, pid: %d -> ppid: %d, pgid: [%d], (%s)\n", i % 4, getpid(), getppid(), getpgid(getpid()), strerror(errno));while (1) sleep(1);return 0;
}

輸出結果:?

測試代碼:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>int main(void)
{setpgid(getpid(), getpid());pid_t group1 = getpgid(getpid());pid_t group2;int i = 0;for(; i < 3; ++i){pid_t pid = fork();if(pid < 0){perror("fork error");exit(1);}else if(pid > 0){// parent processif(i == 0)setpgid(pid, group1);if(i == 1){setpgid(pid, pid);group2 = getpgid(pid);}if(i == 2)setpgid(pid, group2);}else{// child processif(i == 0)setpgid(getpid(), group1);if(i == 1){setpgid(getpid(), getpid());group2 = getpgid(getpid());}if(i == 2)setpgid(getpid(), group2);break;}}printf("pid:%d, ppid:%d, pgid:%d\n", getpid(), getppid(), getpgid(getpid()));for(int i = 0; i < 3; ++i)wait(0);return 0;
}

輸出結果:

2. 實驗二:

題目:利用進程扇完成一個小實驗。該進程扇有 1 個父進程和 3 個子進程,我們希望達到圖 1 中的效果,即將進程 0 (父進程)和進程 1 設置成一組,假設為組 1,將進程 2 和 進程 3 設置成另一個組,假設為組 2. 另外,我們希望進程 0 和進程 2 分別是這兩個組的組長。

測試代碼:

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>int main() 
{int pid, i;int group1, group2;setpgid(getpid(), getpid());group1 = getpgid(getpid());for (i = 0; i < 3; ++i) {pid = fork();if (pid > 0) //父進程{if (i == 0) {setpgid(pid, pid);group2 = getpgid(pid);}   else if (i == 1) {setpgid(pid, group1);}   else if (i == 2){setpgid(pid, group2);}   break;}   else if (pid == 0)  //子進程{if (i == 0) {setpgid(getpid(), getpid());group2 = getpgid(getpid());}   else if (i == 1) {setpgid(getpid(), group1);}   else if (i == 2) {setpgid(getpid(), group2);}   }   else if (pid < 0) {perror("fork");return -1; }   }printf("進程 %d, pid: %d -> ppid: %d, pgid: [%d]\n", i, getpid(), getppid(), getpgid(getpid()));while(1) sleep(1);return 0;
}

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/385484.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/385484.shtml
英文地址,請注明出處:http://en.pswp.cn/news/385484.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

函數wait、waitpid、孤兒進程、僵尸進程

一、函數wait、waitpid 一個進程在終止時會關閉所有文件描述符&#xff0c;釋放在用戶空間釋放的內存&#xff0c;但它的PCB還保留著&#xff0c;內核在其中保存一些信息&#xff1a;如果是正常終止時則保存著退出狀態&#xff0c;如果是異常終止則保存著導致該進程終止的信號是…

MySQL中的字符集與字符序

這篇文章詳細介紹一下MySQL中的字符集和字符序相關的問題&#xff0c;里里外外地了解一下字符集和字符序的方方面面&#xff0c;同時重點說明一下開發中需要注意的問題。 文章基于MySQL 8.0&#xff0c;也會涉及到5.7版本。主要參考MySQL手冊&#xff1a;https://dev.mysql.com…

MySQL中的JSON

從5.7.8開始&#xff0c;MySQL開始支持JSON類型&#xff0c;用于存儲JSON數據。 JSON類型的加入模糊了關系型數據庫與NoSQL之間的界限&#xff0c;給日常開發也帶來了很大的便利。 這篇文章主要介紹一下MySQL中JSON類型的使用&#xff0c;主要參考MySQL手冊&#xff1a;https…

【C++ Primer | 15】虛函數表剖析(一)

一、虛函數 1. 概念 多態指當不同的對象收到相同的消息時&#xff0c;產生不同的動作 編譯時多態&#xff08;靜態綁定&#xff09;&#xff0c;函數重載&#xff0c;運算符重載&#xff0c;模板。運行時多態&#xff08;動態綁定&#xff09;&#xff0c;虛函數機制。為了實現…

【Leetcode | 02】二叉樹、線性表目錄

二叉樹序號題號1 94. 二叉樹的中序遍歷 295. 不同的二叉搜索樹 II396. 不同的二叉搜索樹4 98. 驗證二叉搜索樹 5100. 相同的樹6101. 對稱二叉樹7102. 二叉樹的層次遍歷8103. 二叉樹的鋸齒形層次遍歷9104. 二叉樹的最大深度10105. 從前序與中序遍歷序列構造二叉樹11106. 從中序與…

Leetcode 118. 楊輝三角

給定一個非負整數 numRows&#xff0c;生成楊輝三角的前 numRows 行。 在楊輝三角中&#xff0c;每個數是它左上方和右上方的數的和。 示例: 輸入: 5 輸出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1] ] class Solution { public:vector<vector<int>> generate(…

管道符、重定向與環境變量

輸入輸出重定向 輸入重定向&#xff1a;將文件內容導入到命令中&#xff1b;輸出重定向&#xff1a;將命令執行后顯示到屏幕上的內容導入到文件中&#xff0c;不在屏幕中顯示。共分為&#xff1a;標準輸入重定向&#xff08;文件描述符為0&#xff09;、標準覆蓋輸出&#xff0…

【C++ Primer | 0 】字符串函數實現

1. memcpy函數原型&#xff1a; void* memcpy(void* dst, const void* src, size_t size); void* memmove(void* dst, const void* src, size_t size); 分析&#xff1a; source和destin所指的內存區域可能重疊&#xff0c;但是如果source和destin所指的內存區域重疊,那么這個…

編寫Shell腳本(批處理,一次執行多條命令)

Bash終端的優勢&#xff1a;1.上下鍵重復執行命令&#xff1b;2.tab鍵自動補齊&#xff1b;3.提供有用的環境變量&#xff1b;4.批處理。 shell腳本文件建議以.sh為后綴。 其實vim創建文本文件時&#xff0c;對名字無要求&#xff0c;但最好規定格式。 echo $SHELL&#xff08…

判斷用戶的參數(條件測試語句)

說明$?: $&#xff1f;為上一次命令的執行返回值&#xff0c;若上一次命令正常執行&#xff0c;則返回0&#xff1b;若執行出錯&#xff0c;則返回一個非0的隨機數。比如創建一個已經存在的目錄&#xff0c;則返回一個非0數。 另外&#xff0c;測試語句成立返回0&#xff0c…

流程控制語句(bash)

1.if控制語句 if then fi if then else fi if then elif then elif then else fi if 條件表達式 then 命令序列&#xff08;滿足條件才執行&#xff09; #注意&#xff0c;如果if與then&#xff08;elif與then&#xff09;寫在同一行&#xff0c;要用;隔開&#xff…

用戶身份與文件的權限(普通權限、特殊權限、隱藏權限和文件控制列表ACL)

用戶身份 root用戶是存在于所有類UNIX操作系統中的超級用戶&#xff0c;它擁有最高的系統所有權。root用戶的用戶身份號碼UID為0&#xff0c;UID相當于用戶的身份證號碼一樣&#xff0c;具有唯一性。管理員用戶&#xff08;超級用戶&#xff09;UID為0&#xff1b;系統用戶UID為…

存儲結構與磁盤劃分

文件系統層次化標準&#xff08;FHS&#xff0c;file system hierarchy standard&#xff09; 在windows操作系統中&#xff0c;要找到一個文件需要先進入該文件所在的磁盤分區&#xff08;如C:\等 C:\ZSX\zsx.txt&#xff09;&#xff0c;然后在進入該分區下的一個具…

Linux中常用文件的含義

在Linux中配置了服務文件后&#xff0c;需要重啟該服務&#xff0c;配置信息才會生效。 /etc/passwd 保存了系統中所有用戶的信息&#xff0c;一旦用戶的登陸終端設置為/sbin/nologin&#xff0c;則不再允許登錄到系統 /etc/shadow與/etc/passwd均為用戶信息文件 /…

64. 最小路徑和

給定一個包含非負整數的 m x n 網格&#xff0c;請找出一條從左上角到右下角的路徑&#xff0c;使得路徑上的數字總和為最小。 說明&#xff1a;每次只能向下或者向右移動一步。 示例: 輸入: [[1,3,1],[1,5,1],[4,2,1] ] 輸出: 7 解釋: 因為路徑 1→3→1→1→1 的總和最小。…

Linux本地yum源配置以及使用yum源安裝各種應用程序

將軟件包傳送到Linux中后&#xff0c;掛載&#xff0c;然后配置yum軟件倉庫&#xff0c;最后就可以使用yum來安裝相應的應用程序了。假設掛載目錄為/tmp/ruanjianbao&#xff0c;則下面說明配置本地yum倉庫的過程&#xff1a; &#xff08;1&#xff09;cd /etc/yum.repos.d/…

gcc與g++編譯器

首先在Linux(RHEL7.0)上安裝gcc&#xff1a;yum install gcc gcc-c -y 其中gcc-c是為了能夠編譯c源代碼&#xff0c;即g。 gcc為Linux C/C下重要的編譯環境&#xff0c;是GUN項目中符合ANSIC標準的編譯系統&#xff0c; gcc可以編譯C、C、Objective-C、Java、Fortran、Pascal…