目錄
??前言??
??進(jìn)程的概念
??描述進(jìn)程-PCB
???查看進(jìn)程
?? 查看正在運行的程序
??殺死進(jìn)程
??通過系統(tǒng)調(diào)用獲取進(jìn)程標(biāo)識符
??通過系統(tǒng)調(diào)用創(chuàng)建進(jìn)程
?? 進(jìn)程的特點
??進(jìn)程的狀態(tài)
?? kill 信號
?? 僵尸進(jìn)程?
?? 孤兒進(jìn)程
?? 運行狀態(tài)
?? 阻塞狀態(tài)
?? 掛起狀態(tài)
??進(jìn)程的切換
??進(jìn)程的優(yōu)先級
?? 概念
?? 原則
?? 查看方式
?? PRI 和 NI
?? 調(diào)整方式
?? 進(jìn)程的地址空間 (虛擬地址)
?? 虛擬地址的好處
?? Linux2.6 內(nèi)核進(jìn)程調(diào)度隊列?編輯
?? 活動隊列
??? 過期隊列
??active指針和expired指針
??總結(jié)
??前言??
? ? ? ? 歡迎觀看本期【Linux雜貨鋪】,本期內(nèi)容,將講解操作系統(tǒng)中重要的概念——進(jìn)程。本篇文章將講解操作系統(tǒng)關(guān)于進(jìn)程的通用知識,以及在Linux中如何組織管理進(jìn)程,以及運行進(jìn)程。
? ? ? ? 如果你還不是很了解操作系統(tǒng)的概念,可以收看上期關(guān)于操作系統(tǒng)的知識:
【Linux雜貨鋪】操作系統(tǒng)-CSDN博客
? ? ? ? 這里簡單概括一下操作系統(tǒng)的的前置知識,即什么管理,簡單概括就是先描述,在組織。舉個例子,操作系統(tǒng)將一個個硬件描述為一個結(jié)構(gòu)體struct,將結(jié)構(gòu)體組織稱不同數(shù)據(jù)結(jié)構(gòu),例如鏈表,通過對鏈表的增刪查改來管理硬件。
? ? ? ? 這里就先介紹了操作系統(tǒng)重管理的概念。
??進(jìn)程的概念
? ? ? ? 除法任何一個事件時,系統(tǒng)都會將它定義為一個進(jìn)程,并給予這個進(jìn)程一個ID,稱為PID,同時根據(jù)觸發(fā)這個進(jìn)程的用戶與相關(guān)屬性關(guān)系,給予這個PID一組有效的權(quán)限設(shè)置。
? ? ? ? 執(zhí)行一個程序或者命令,就是觸發(fā)一個事件,而獲取一個PID。
? ? ? ? 簡單來說就是一個正在運行的程序。
??描述進(jìn)程-PCB
? ? ? ? 進(jìn)程的信息會被放在一個叫進(jìn)程控制塊的數(shù)據(jù)結(jié)構(gòu)中,可以理解為進(jìn)程的屬性。在Linux系統(tǒng)中PCB是:task_struct。
? ? ? ? task_stuct就是Linux內(nèi)核中的一個數(shù)據(jù)結(jié)構(gòu),它會被裝載到內(nèi)存里并且包含進(jìn)程的信息。
task_ struct 內(nèi)容分類? ● 標(biāo)示符: 描述本進(jìn)程的唯一標(biāo)示符,用來區(qū)別其他進(jìn)程。? ● 狀態(tài): 任務(wù)狀態(tài),退出代碼,退出信號等。? ● 優(yōu)先級: 相對于其他進(jìn)程的優(yōu)先級。? ● 程序計數(shù)器: 程序中即將被執(zhí)行的下一條指令的地址。? ● 內(nèi)存指針: 包括程序代碼和進(jìn)程相關(guān)數(shù)據(jù)的指針,還有和其他進(jìn)程共享的內(nèi)存塊的指針? ● 上下文數(shù)據(jù): 進(jìn)程執(zhí)行時處理器的寄存器中的數(shù)據(jù) [ 休學(xué)例子,要加圖 CPU ,寄存器 ] 。? ● I/ O 狀態(tài)信息 : 包括顯示的 I/O 請求 , 分配給進(jìn)程的 I / O 設(shè)備和被進(jìn)程使用的文件列表。? ● 記賬信息: 可能包括處理器時間總和,使用的時鐘數(shù)總和,時間限制,記賬號等。? ● 其他信息
? ? ? ? 進(jìn)程 = 內(nèi)核結(jié)構(gòu)體PCB + 程序的代碼和數(shù)據(jù)。
? ? ? ? 每個進(jìn)程都有一個唯一標(biāo)識符,叫pid。
???查看進(jìn)程
? ? ? ? 進(jìn)程信息可以通過 /proc 系統(tǒng)文件查看。如獲得PID為1的進(jìn)程信息,需要查看/proc/1這個文件。
? ? ? ? 大多數(shù)進(jìn)程信息同樣可以使用top和ps這些用戶級工具來獲取。
?? 查看正在運行的程序
ps -ajx
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
while(1){
sleep(1);
}
return 0;
}
??殺死進(jìn)程
kill -9 pid
? ? ? ? kill 先簡單理解為向進(jìn)程發(fā)了個信號,-9表示殺死進(jìn)程,在進(jìn)程的狀態(tài)會進(jìn)行講解。
??通過系統(tǒng)調(diào)用獲取進(jìn)程標(biāo)識符
進(jìn)程id = pid
父進(jìn)程id? = ppid
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
//獲得子進(jìn)程
printf("pid: %d\n", getpid());
//獲得父進(jìn)程
printf("ppid: %d\n", getppid());
return 0;
}
? ? ? ? 我們通過父進(jìn)程來創(chuàng)建子進(jìn)程,子進(jìn)程繼承父進(jìn)程的代碼和數(shù)據(jù),會有自己的PCB。
??通過系統(tǒng)調(diào)用創(chuàng)建進(jìn)程
? ? ? ? fork函數(shù),fork函數(shù)會有兩個返回值,父進(jìn)程一個,子進(jìn)程一個。這里可以這樣理解,進(jìn)入fork函數(shù)后,已經(jīng)有了兩個進(jìn)程,父進(jìn)程和子進(jìn)程,父子進(jìn)程會進(jìn)行代碼共享,即有兩個return。
? ? ? ? 父進(jìn)程會得到子進(jìn)程的pid,子進(jìn)程的返回值為0。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
printf("hello proc : %d!, ret: %d\n", getpid(), ret);
sleep(1);
return 0;
}
? ? ? ? fork之后通常要用 if 分流。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
if(ret < 0){
perror("fork");
return 1;
}
else if(ret == 0){ //child
printf("I am child : %d!, ret: %d\n", getpid(), ret);
}else{ //father
printf("I am father : %d!, ret: %d\n", getpid(), ret);
}
sleep(1);
return 0;
}
?? 進(jìn)程的特點
? ? ? ? 1. 競爭性:系統(tǒng)進(jìn)程數(shù)目眾多,而CPU資源只有少量,甚至1個,所以進(jìn)程之間具有競爭屬性,為了高效完成任務(wù),更合理的競爭相關(guān)資源,便具有了優(yōu)先級。
? ? ? ? 2. 獨立性:多進(jìn)程運行,需要獨享各種資源,多進(jìn)程運行期間互不干擾。
? ? ? ? 3. 并行: 多個進(jìn)程在多個CPU下分別,同時進(jìn)行運行,這稱之為并行。
? ? ? ? 4. 并發(fā): 多個進(jìn)程在1個CPU下采用進(jìn)程切換的方式,在一段時間內(nèi),讓多個進(jìn)程得以推進(jìn),稱之為并發(fā)。
??進(jìn)程的狀態(tài)
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
R運行狀態(tài)(running): 并不意味著進(jìn)程一定在運行中,它表明進(jìn)程要么是在運行中要么在運行隊列
里。
S睡眠狀態(tài)(sleeping): 意味著進(jìn)程在等待事件完成(這里的睡眠有時候也叫做可中斷睡眠
(interruptible sleep))。
D磁盤休眠狀態(tài)(Disk sleep)有時候也叫不可中斷睡眠狀態(tài)(uninterruptible sleep),在這個狀態(tài)的
進(jìn)程通常會等待IO的結(jié)束。
T停止?fàn)顟B(tài)(stopped): 可以通過發(fā)送 SIGSTOP 信號給進(jìn)程來停止(T)進(jìn)程。這個被暫停的進(jìn)程可
以通過發(fā)送 SIGCONT 信號讓進(jìn)程繼續(xù)運行。
X死亡狀態(tài)(dead):這個狀態(tài)只是一個返回狀態(tài),你不會在任務(wù)列表里看到這個狀態(tài)。
僵死狀態(tài)(Zombies)是一個比較特殊的狀態(tài)。當(dāng)進(jìn)程退出并且父進(jìn)程(使用wait()系統(tǒng)調(diào)用,后面講)
沒有讀取到子進(jìn)程退出的返回代碼時就會產(chǎn)生僵死(尸)進(jìn)程
R : 進(jìn)程運行狀態(tài)
S:(淺)休眠狀態(tài),進(jìn)程處于等待狀態(tài),等待資源就緒,可中斷休眠。
D:(深)休眠狀態(tài),不可被殺,深度睡眠,不可中斷睡眠。
? 1. 等待進(jìn)程自己醒來。
? 2. 斷電重啟。
T:暫停狀態(tài)
? ? ? ? kill -19 pid 改為暫停狀態(tài),即將進(jìn)程暫停。
? ? ? ? kill -18 pid? 繼續(xù)運行進(jìn)程。
t : 調(diào)試暫停,debug調(diào)試,遇到斷點就暫停。
?? kill 信號
? ? ? ? kill 向指定進(jìn)程發(fā)送信號。kill -l 查看信號
?? 僵尸進(jìn)程?
? ? ? ? z狀態(tài),即進(jìn)程已經(jīng)運行完畢,但需要維持自己的退出信息,在自己的task_struct記錄自己的退出信息,未來讓父進(jìn)程讀取,如果父進(jìn)程沒有讀取,僵尸進(jìn)程會一直存在。
? ? ? ? 僵尸進(jìn)程不可以被殺死。如果僵尸進(jìn)程一直沒有被父進(jìn)程讀取,就會造成內(nèi)存泄漏。
? ? ? ? x狀態(tài)就就是,讀取了z,由os釋放進(jìn)程。
?? 孤兒進(jìn)程
? ? ? ? 父進(jìn)程先退出,子進(jìn)程就被稱為“孤兒進(jìn)程”。孤兒進(jìn)程被1號進(jìn)程領(lǐng)養(yǎng),由os進(jìn)行回收。
? ? ? ? 孤兒進(jìn)程可以被殺死。
?? 運行狀態(tài)
????????R運行狀態(tài):并不意味著程序一定在運行中,表明程序要么在運行中,要么在運行隊列中。
? ? ? ? 分時操作系統(tǒng),即每個進(jìn)程都有一個時間片,在規(guī)定時間片內(nèi)執(zhí)行進(jìn)程,如果進(jìn)程沒有執(zhí)行完畢,則會再次進(jìn)入運行隊列等待。
?? 阻塞狀態(tài)
? ? ? ? S休眠狀態(tài):意味著進(jìn)程正在等待事件完成。
? ? ? ? D磁盤休眠狀態(tài):有時候也叫不可中斷休眠狀態(tài),在這個狀態(tài)的進(jìn)程通常會等待IO結(jié)束。
?? 掛起狀態(tài)
????????內(nèi)存資源不足,且進(jìn)程處于阻塞狀態(tài)時,進(jìn)程就會被喚出到swap分區(qū)中。過多的掛起,會導(dǎo)致效率問題
??進(jìn)程的切換
? ? ? ? 基于時間片等原因,進(jìn)程可能會切換到其他狀態(tài),那么CPU是如何知道進(jìn)程執(zhí)行到哪了呢,接著上一次執(zhí)行繼續(xù)執(zhí)行呢?
? ? ? ? CPU的寄存器會保存著進(jìn)程的臨時數(shù)據(jù)。CPU內(nèi)部所有寄存器中的臨時數(shù)據(jù),就叫做進(jìn)程的上下文。
??進(jìn)程的優(yōu)先級
?? 概念
? ? ? ? 本質(zhì)是指定一個進(jìn)程獲得某種資源的先后順序,在task_struct中是一個數(shù)字int,優(yōu)先級數(shù)字越小,優(yōu)先級越高。
? ? ? ? 為什么要有優(yōu)先級呢?因為進(jìn)程訪問的資源是有限的。
?? 原則
? ? ? ? 分時操作系統(tǒng),基于時間片調(diào)度輪轉(zhuǎn),要保證基本的公平。如果進(jìn)程因為長時間不被調(diào)度,就會造成饑餓問題。
?? 查看方式
ps -l
?? PRI 和 NI
? ? ? ? PRI就是進(jìn)程的優(yōu)先級,其值越小,進(jìn)程的優(yōu)先級就越高。
? ? ? ? NI就是nice值,即進(jìn)程可被執(zhí)行的優(yōu)先級的修證數(shù)據(jù)。
? ? ? ? 進(jìn)程優(yōu)先級 = PRI + NI。
? ? ? ? nice值的取值范圍是[-20 , 19] 一共40個級別。
? ? ? ? RPI優(yōu)先級默認(rèn)是從801開始的,取值是[60 , 99]。
?? 調(diào)整方式
? ? ? ? 用top命令更改已存在的進(jìn)程的nice
● top
● 輸入“r” -> 輸入PID -> 輸入nice值
?? 進(jìn)程的地址空間 (虛擬地址)
? ? ? ? 我們在C/C++語言中看到的地址都是虛擬地址。物理地址,用戶是看不到的,由os統(tǒng)一管理。os負(fù)責(zé)將虛擬地址轉(zhuǎn)換為物理地址。
? ? ? ? 地址空間本質(zhì)上是一個結(jié)構(gòu)體,內(nèi)部是很多屬性,表示每個區(qū)間的范圍??梢院唵卫斫?,每個進(jìn)程都有一個地址空間和頁表,頁表負(fù)責(zé)將地址空間上的虛擬地址轉(zhuǎn)為物理地址。
? ? ? ? 父進(jìn)程創(chuàng)建子進(jìn)程后,子進(jìn)程的頁表與父進(jìn)程的頁表是一樣的,即相同的虛擬地址映像到相同的物理地址。但是如果一個進(jìn)程想要修改,則物理地址就會發(fā)生改變,即虛擬地址對應(yīng)不同的物理地址。這就是寫實拷貝。
?? 虛擬地址的好處
1. 將無序變?yōu)橛行?,以統(tǒng)一的視角看待物理內(nèi)存以及運行各個區(qū)域。
2. 進(jìn)程管理模塊和內(nèi)存管理模塊進(jìn)行解耦
3. 有效的攔截非法請求。
?? Linux2.6 內(nèi)核進(jìn)程調(diào)度隊列
? ? ? ? 一個CPU擁有一個requeue(運行隊列)。
? ? ? ? 普通優(yōu)先級:100-139?
? ? ? ? 實時優(yōu)先級:0 - 99 (不關(guān)心)
?
?? 活動隊列
? ? ? ? ?時間片還沒有結(jié)束的所有進(jìn)程都會按照優(yōu)先級放在該隊列。
nr_active: 總共有多少個運行狀態(tài)的進(jìn)程queue[140]: 一個元素就是一個進(jìn)程隊列,相同優(yōu)先級的進(jìn)程按照 FIFO 規(guī)則進(jìn)行排隊調(diào)度 , 所以,數(shù)組下標(biāo)就是優(yōu)先級!從該結(jié)構(gòu)中,選擇一個最合適的進(jìn)程,過程是怎么的呢?1. 從 0 下表開始遍歷 queue[140]2. 找到第一個非空隊列,該隊列必定為優(yōu)先級最高的隊列3. 拿到選中隊列的第一個進(jìn)程,開始運行,調(diào)度完成!4. 遍歷 queue[140] 時間復(fù)雜度是常數(shù)!但還是太低效了!bitmap[5]: 一共 140 個優(yōu)先級,一共 140 個進(jìn)程隊列,為了提高查找非空隊列的效率,就可以用 5*32 個比特位表示隊列是否為空,這樣,便可以大大提高查找效率
? ? ? ? 上圖,我們展示活動隊列,過期隊列也是同理。
??? 過期隊列
? ? ? ? 過期隊列和活動隊列一模一樣,過期隊列上放置的集成,都是時間片耗盡,但是還沒有結(jié)束的進(jìn)程。當(dāng)活動隊列上的進(jìn)程都處理完畢后,對過期隊列進(jìn)程時間片重計算。
??active指針和expired指針
? ? ? ??active指針永遠(yuǎn)指向活動隊列。
????????expired指針永遠(yuǎn)指向過期隊列。
????????可是活動隊列上的進(jìn)程會越來越少,過期隊列上的進(jìn)程會越來越多,因為進(jìn)程時間片到期時一直都存在的。
??總結(jié)
? ? ? ? 以上,就是本期【Linux雜貨鋪】進(jìn)程基本概念的所有內(nèi)容了,講解了什么事進(jìn)程,進(jìn)程的狀態(tài)有哪些,包括僵尸進(jìn)程,孤兒進(jìn)程,講解了進(jìn)程的優(yōu)先級,也粗略的講解了進(jìn)程的地址空間,也就是平常說的虛擬地址,以及Linux中臨時拷貝是什么,在Linux中是如何調(diào)度進(jìn)程的。
? ? ? ? 如果感覺本期內(nèi)容對你有幫助,歡迎點贊,收藏,關(guān)注Thanks?(?ω?)?文章來源:http://www.zghlxwxcb.cn/news/detail-841574.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-841574.html
到了這里,關(guān)于【Linux雜貨鋪】進(jìn)程的基本概念的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!