進(jìn)程優(yōu)先級(jí)的基本概念
在linux系統(tǒng)中,進(jìn)程優(yōu)先級(jí)(priority)決定了進(jìn)程執(zhí)行的順序。優(yōu)先級(jí)較高的進(jìn)程優(yōu)先獲得cpu資源,從而提高了執(zhí)行的優(yōu)先權(quán)。優(yōu)先級(jí)值越低,進(jìn)程的優(yōu)先級(jí)越高,這意味著該進(jìn)程更有可能被cpu優(yōu)先執(zhí)行。合理配置進(jìn)程的優(yōu)先級(jí)對(duì)于提升系統(tǒng)的整體性能至關(guān)重要。
此外,Linux還提供了將進(jìn)程運(yùn)行到指定CPU的功能。通過將不重要的進(jìn)程分配到特定的CPU上,可以更有效地利用CPU資源,避免系統(tǒng)性能下降。
如何查看系統(tǒng)進(jìn)程
在Linux或unix系統(tǒng)中,我們可以使用ps -l命令來查看當(dāng)前運(yùn)行的進(jìn)程。輸出信息中包含了多個(gè)有用的字段,幫助我們理解每個(gè)進(jìn)程的狀態(tài)。以下是一些重要字段:
- UID:表示進(jìn)程的執(zhí)行者身份。
- PID:代表進(jìn)程的標(biāo)識(shí)符。
- PPID:表示該進(jìn)程的父進(jìn)程ID。
- PRI:進(jìn)程的優(yōu)先級(jí)。值越小,優(yōu)先級(jí)越高。
- NI:進(jìn)程的nice值,影響進(jìn)程的優(yōu)先級(jí)。
PRI和NI:優(yōu)先級(jí)與Nice值
PRI(Priority)是進(jìn)程的優(yōu)先級(jí),其值越小,優(yōu)先級(jí)越高,進(jìn)程越有可能先執(zhí)行。NI(Nice)是進(jìn)程的優(yōu)先級(jí)修正值,可以調(diào)整進(jìn)程的優(yōu)先級(jí)。通過修改nice值,用戶可以間接地影響進(jìn)程的PRI值。
具體地,進(jìn)程的新PRI值計(jì)算公式為:
PRI(new) = PRI(old) + nice
當(dāng)nice值為負(fù)時(shí),進(jìn)程的優(yōu)先級(jí)會(huì)變?。▋?yōu)先級(jí)提升);當(dāng)nice值為正時(shí),進(jìn)程的優(yōu)先級(jí)會(huì)變大(優(yōu)先級(jí)降低)。nice值的范圍是-20到19(PRI的值為0~99),越小表示優(yōu)先級(jí)越高,越大表示優(yōu)先級(jí)越低。
查看和調(diào)整進(jìn)程優(yōu)先級(jí)
在Linux中,查看進(jìn)程優(yōu)先級(jí)的常用命令是top。通過top命令,我們不僅能夠查看各個(gè)進(jìn)程的優(yōu)先級(jí),還能實(shí)時(shí)調(diào)整進(jìn)程的nice值:
- 輸入top命令啟動(dòng)進(jìn)程監(jiān)視。
- 按r鍵,選擇需要調(diào)整的進(jìn)程PID。
- 輸入新的nice值來調(diào)整該進(jìn)程的優(yōu)先級(jí)。
除了top命令外,Linux還提供了nice和renice命令來分別調(diào)整進(jìn)程的初始優(yōu)先級(jí)和修改已經(jīng)運(yùn)行中的進(jìn)程的優(yōu)先級(jí)。
補(bǔ)充概念-競爭、獨(dú)立、并行、并發(fā)
- 競爭性:系統(tǒng)進(jìn)程數(shù)量眾多,而CPU資源只有少量,甚至1個(gè),所以進(jìn)程之間是具有競爭屬性的。為了高效完成任務(wù),更合理競爭相關(guān)資源,便具有了優(yōu)先級(jí)。
- 獨(dú)立性:多進(jìn)程運(yùn)行,需要獨(dú)享各種資源,多進(jìn)程運(yùn)行期間互不干擾。
- 并行:多個(gè)進(jìn)程在多個(gè)CPU下分別,同時(shí)進(jìn)行運(yùn)行,這稱之為并行。
- 并發(fā):多個(gè)進(jìn)程在一個(gè)CPU下采用進(jìn)程切換的方式,在一段時(shí)間之內(nèi),讓多個(gè)進(jìn)程都得以推進(jìn),稱之為并發(fā)。
進(jìn)程切換
CPU上下文切換:其實(shí)際含義是任務(wù)切換,或者CPU寄存器切換。當(dāng)多任務(wù)內(nèi)核決定運(yùn)行另外的任務(wù)時(shí),它保存正在運(yùn)行任務(wù)的當(dāng)前狀態(tài),也就是CPU寄存器中的全部內(nèi)容。這些內(nèi)容被保存在任務(wù)自己的堆棧中,入棧工作完成后就把下一個(gè)將要運(yùn)行的任務(wù)的當(dāng)前狀況從該任務(wù)的棧中重新裝入CPU寄存器,并開始下一個(gè)任務(wù)的運(yùn)行,這一過程就是context switch。
時(shí)間片:當(dāng)代計(jì)算機(jī)都是分時(shí)操作系統(tǒng),每個(gè)進(jìn)程都有它合適的時(shí)間片(其實(shí)就是一個(gè)計(jì)數(shù)器)。時(shí)間片到達(dá),進(jìn)程就被操作系統(tǒng)從CPU中剝離下來。
Linux2.6內(nèi)核進(jìn)程O(1)調(diào)度隊(duì)列
上圖是Linux2.6內(nèi)核中進(jìn)程隊(duì)列的數(shù)據(jù)結(jié)構(gòu),之間關(guān)系也已經(jīng)給大家畫出來,方便大家理解。
- 一個(gè)CPU擁有一個(gè)runqueue,如果有多個(gè)CPU就要考慮進(jìn)程個(gè)數(shù)的負(fù)載均衡問題。
- 優(yōu)先級(jí):
- 普通優(yōu)先級(jí):100?139(我們都是普通的優(yōu)先級(jí),想想nice值的取值范圍,可與之對(duì)應(yīng)!)
- 實(shí)時(shí)優(yōu)先級(jí):0?99(不關(guān)心)
活動(dòng)隊(duì)列及其優(yōu)化
在操作系統(tǒng)的進(jìn)程調(diào)度中,活動(dòng)隊(duì)列(Active Queue)用于管理處于運(yùn)行狀態(tài)的進(jìn)程?;顒?dòng)隊(duì)列不僅管理進(jìn)程的排隊(duì)順序,還涉及進(jìn)程的優(yōu)先級(jí)和調(diào)度策略。以下是活動(dòng)隊(duì)列的關(guān)鍵概念及其優(yōu)化過程的整理:
活動(dòng)隊(duì)列的基本概念
- nr_active:表示當(dāng)前活動(dòng)隊(duì)列中處于運(yùn)行狀態(tài)的進(jìn)程總數(shù)。它用于記錄系統(tǒng)中所有正在運(yùn)行的進(jìn)程數(shù)量。
- queue[140]:這是一個(gè)數(shù)組,其中每個(gè)元素對(duì)應(yīng)一個(gè)優(yōu)先級(jí)隊(duì)列。進(jìn)程按照優(yōu)先級(jí)排隊(duì),相同優(yōu)先級(jí)的進(jìn)程使用先進(jìn)先出(FIFO)規(guī)則進(jìn)行調(diào)度。數(shù)組下標(biāo)代表進(jìn)程的優(yōu)先級(jí),因此queue[0]表示優(yōu)先級(jí)最高的進(jìn)程隊(duì)列,queue[139]表示優(yōu)先級(jí)最低的進(jìn)程隊(duì)列。
進(jìn)程調(diào)度的基本過程
操作系統(tǒng)根據(jù)活動(dòng)隊(duì)列進(jìn)行進(jìn)程調(diào)度的過程如下:
- 遍歷隊(duì)列:從queue[0]開始遍歷,查找非空的進(jìn)程隊(duì)列。
- 選擇最高優(yōu)先級(jí)的進(jìn)程隊(duì)列:找到第一個(gè)非空隊(duì)列,該隊(duì)列中的進(jìn)程具有最高的優(yōu)先級(jí)。
- 選中并執(zhí)行進(jìn)程:從該非空隊(duì)列中選擇第一個(gè)進(jìn)程進(jìn)行調(diào)度執(zhí)行。
- 調(diào)度完成:該進(jìn)程開始執(zhí)行,調(diào)度過程結(jié)束。
該過程的時(shí)間復(fù)雜度通常為常數(shù)時(shí)間,因?yàn)殛?duì)列的遍歷通常是有限的,但存在低效的情況。
低效問題及優(yōu)化方案
直接遍歷queue[140]來查找非空隊(duì)列存在效率問題,尤其在系統(tǒng)中進(jìn)程數(shù)量較多時(shí),這種遍歷方式會(huì)變得低效。為了提高查找非空隊(duì)列的效率,可以通過使用位圖(bitmap)進(jìn)行優(yōu)化:
- bitmap[5]:為了提高查找非空隊(duì)列的效率,可以使用位圖來標(biāo)識(shí)每個(gè)進(jìn)程隊(duì)列是否為空。此位圖有140個(gè)位置,表示140個(gè)進(jìn)程隊(duì)列,每個(gè)位置使用5個(gè)字節(jié)(5 * 32位),每一位表示相應(yīng)隊(duì)列的空閑狀態(tài)。
- 優(yōu)化效果:通過位圖的使用,可以在常數(shù)時(shí)間內(nèi)快速定位到第一個(gè)非空隊(duì)列,從而大大提高查找和調(diào)度的效率。
過期隊(duì)列
過期隊(duì)列和活動(dòng)隊(duì)列結(jié)構(gòu)一模一樣。過期隊(duì)列上放置的進(jìn)程,都是時(shí)間片耗盡的進(jìn)程。當(dāng)活動(dòng)隊(duì)列上的進(jìn)程都被處理完畢之后,對(duì)過期隊(duì)列的進(jìn)程進(jìn)行時(shí)間片重新計(jì)算。
過期隊(duì)列與活動(dòng)隊(duì)列的結(jié)構(gòu)
過期隊(duì)列和活動(dòng)隊(duì)列在結(jié)構(gòu)上非常相似,都是由一個(gè)隊(duì)列組成,用于管理不同優(yōu)先級(jí)的進(jìn)程。其基本結(jié)構(gòu)如下:
- 過期隊(duì)列:這是放置已經(jīng)超時(shí)或者不再需要立即執(zhí)行的進(jìn)程隊(duì)列。系統(tǒng)會(huì)根據(jù)進(jìn)程的優(yōu)先級(jí)來調(diào)度這些進(jìn)程,通常只有在特定的條件下,才會(huì)將這些進(jìn)程重新激活。
- 活動(dòng)隊(duì)列:這個(gè)隊(duì)列用于管理當(dāng)前需要執(zhí)行的進(jìn)程。處于活動(dòng)隊(duì)列中的進(jìn)程會(huì)按照優(yōu)先級(jí)順序執(zhí)行,直至完成。
過期隊(duì)列和活動(dòng)隊(duì)列的關(guān)鍵點(diǎn):
當(dāng)活動(dòng)隊(duì)列中的進(jìn)程被處理完畢后,系統(tǒng)會(huì)重新計(jì)算過期隊(duì)列中進(jìn)程的時(shí)間片,并重新將其加入活動(dòng)隊(duì)列,等待重新執(zhí)行。
在操作系統(tǒng)中,active和expired指針用于指向活動(dòng)隊(duì)列和過期隊(duì)列的內(nèi)容。具體作用如下:
- active指針:該指針始終指向活動(dòng)隊(duì)列,管理當(dāng)前需要執(zhí)行的進(jìn)程。當(dāng)隊(duì)列中有進(jìn)程時(shí),active指針指向活動(dòng)隊(duì)列的第一個(gè)進(jìn)程,系統(tǒng)從該進(jìn)程開始調(diào)度。
- expired指針:與active指針類似,expired指針指向過期隊(duì)列。過期隊(duì)列存儲(chǔ)的是已超時(shí)的進(jìn)程,等待重新激活并加入活動(dòng)隊(duì)列進(jìn)行調(diào)度。
盡管active和expired指針指向的是兩個(gè)不同的隊(duì)列,但它們之間的轉(zhuǎn)換并沒有特別復(fù)雜的關(guān)聯(lián)。當(dāng)一個(gè)進(jìn)程的執(zhí)行時(shí)間片結(jié)束后,系統(tǒng)會(huì)將其從活動(dòng)隊(duì)列移到過期隊(duì)列。當(dāng)過期隊(duì)列中的進(jìn)程恢復(fù)執(zhí)行時(shí),它們會(huì)再次被移動(dòng)到活動(dòng)隊(duì)列。