目錄
1.進程優(yōu)先級
1.1 基本概念
1.2 查看系統(tǒng)進程
1.3 修改進程優(yōu)先級的命令
2.進程間切換
2.1 相關(guān)概念
2.2 Linux2.6內(nèi)核進程調(diào)度隊列(了解即可)
3.命令行參數(shù)
1.進程優(yōu)先級
1.1 基本概念
- cpu資源分配的先后順序,就是指進程的優(yōu)先權(quán)(priority)。
- 優(yōu)先權(quán)高的進程有優(yōu)先執(zhí)行權(quán)利。配置進程優(yōu)先權(quán)對多任務(wù)環(huán)境的linux很有用,可以改善系統(tǒng)性能。
- 還可以把進程運行到指定的CPU上,這樣一來,把不重要的進程安排到某個CPU,可以大大改善系統(tǒng)整體性能。?
我們知道進程在內(nèi)存中是需要排隊的,比如運行隊列,等待隊列。那排隊是干什么的:就是在確認優(yōu)先級,來確定得到某種資源的先后順序。為什么要確認優(yōu)先級,本質(zhì)就是資源不足。那么操作系統(tǒng)是怎么做到呢?我們下面講解:
優(yōu)先級其實就是PCB中的一個 int 字段,數(shù)值越小,優(yōu)先級越大,跟我們的考試排名一樣。Linux進程的優(yōu)先級數(shù)值范圍:60~99。Linux中默認進程的優(yōu)先級都是80。
1.2 查看系統(tǒng)進程
我們先編寫一段代碼
在linux或者unix系統(tǒng)中,用ps -la 命令則會類似輸出以下幾個內(nèi)容:
我們很容易注意到其中的幾個重要信息,有下:
- UID : 代表執(zhí)行者的身份
- PID : 代表這個進程的代號
- PPID :代表這個進程是由哪個進程發(fā)展衍生而來的,亦即父進程的代號
- PRI :代表這個進程可被執(zhí)行的優(yōu)先級,其值越小越早被執(zhí)行
- NI :代表這個進程的nice值
PRI and NI:
PRI也還是比較好理解的,即進程的優(yōu)先級,或者通俗點說就是程序被CPU執(zhí)行的先后順序,此值越小進程的優(yōu)先級別越高
那NI就是我們所要說的nice值了,其表示進程可被執(zhí)行的優(yōu)先級的修正數(shù)值
PRI值越小越快被執(zhí)行,那么加入nice值后,將會使得PRI變?yōu)?span style="color:#38d8f0;">:PRI(new)=PRI(old)+nice。pri(old)?,都是從80開始的!
這樣,當(dāng)nice值為負值的時候,那么該程序?qū)?yōu)先級值將變小,即其優(yōu)先級會變高,則其越快被執(zhí)行所以,調(diào)整進程優(yōu)先級,在Linux下,就是調(diào)整進程nice值
nice其取值范圍是-20至19,一共40個級別。nice調(diào)整最小是:-20,超過部分統(tǒng)一當(dāng)成-20。nice調(diào)整最大是:19,超過部分統(tǒng)一當(dāng)成19。
PRI vs NI:
- 需要強調(diào)一點的是,進程的nice值不是進程的優(yōu)先級,他們不是一個概念,但是進程nice值會影響到進程的優(yōu)先級變化??梢岳斫鈔ice值是進程優(yōu)先級的修正修正數(shù)據(jù)
1.3 修改進程優(yōu)先級的命令
用top命令更改已存在進程的nice:
- top
- 進入top后按“r”–>輸入進程PID–>輸入nice值
我們輸入進程號講 nice 改為19
普通用戶是沒有辦法將優(yōu)先級調(diào)大,讓PRI減小的。需要使用su換成root,或使用sudo命令。?
2.進程間切換
2.1 相關(guān)概念
- 競爭性: 系統(tǒng)進程數(shù)目眾多,而CPU資源只有少量,甚至1個,所以進程之間是具有競爭屬性的。為了高效完成任務(wù),更合理競爭相關(guān)資源,便具有了優(yōu)先級。
- 獨立性: 多進程運行,需要獨享各種資源,多進程運行期間互不干擾。
- 并行: 多個進程在多個CPU下分別,同時進行運行,這稱之為并行。
- 并發(fā): 多個進程在一個CPU下采用進程切換的方式,在一段時間之內(nèi),讓多個進程都得以推進,稱之為并發(fā)。
因為要并發(fā),所以必定要考慮進程間切換。
每一個進程不是占有CPU就一直運行,每隔一段時間,會自動被操作系統(tǒng)從cpu上剝離下來。Linux內(nèi)核是支持進程之間進行cpu資源搶占的!是基于時間片的輪轉(zhuǎn)式搶占式內(nèi)核。
為什么我們函數(shù)內(nèi)定義的棧臨時變量,會返回給外部,我們的程序/進程,它怎么知道我們當(dāng)前運行到哪里里?如何做到函數(shù)間跳轉(zhuǎn)? 因為cpu內(nèi)存在大量寄存器,比如eip是程序計數(shù)器或者叫pc,會自動執(zhí)行我們要執(zhí)行的下一行代碼。我們的進程在運行的時候,是會使用這些寄存器的,我們的進程,會產(chǎn)生各種數(shù)據(jù),在寄存器中臨時保存。
如果我們有多個進程呢?各個進程在CPU寄存器中形成的臨時數(shù)據(jù),都應(yīng)該是不一樣的!而cpu內(nèi)寄存器只有一套,我們?nèi)绾巫龅阶屆總€進程使用cpu時能從上次時間片執(zhí)行到的位置繼續(xù)執(zhí)行?我們可以先簡單的理解為時間片結(jié)束后,cpu寄存器中的數(shù)據(jù)會先保存到進程PCB中,然后下次執(zhí)行時先讀取PCB中存儲的寄存器的數(shù)據(jù),然后繼續(xù)執(zhí)行,本質(zhì)就是將CPU寄存器的內(nèi)容,保存到內(nèi)存中!
2.2 Linux2.6內(nèi)核進程調(diào)度隊列(了解即可)
上圖是Linux2.6內(nèi)核中進程隊列的數(shù)據(jù)結(jié)構(gòu),之間關(guān)系也已經(jīng)給大家畫出來,方便大家理解
一個CPU擁有一個runqueue
- 如果有多個CPU就要考慮進程個數(shù)的負載均衡問題
優(yōu)先級
- 普通優(yōu)先級:100~139(我們都是普通的優(yōu)先級,想想nice值的取值范圍,可與之對應(yīng)?。?/li>
- 實時優(yōu)先級:0~99(我們這里不關(guān)心)
活動隊列
- 時間片還沒有結(jié)束的所有進程都按照優(yōu)先級放在該隊列
- nr_active: 總共有多少個運行狀態(tài)的進程
- queue[140]: 一個元素就是一個進程隊列,相同優(yōu)先級的進程按照FIFO規(guī)則進行排隊調(diào)度,所以,數(shù)組下標就是優(yōu)先級!
- 從該結(jié)構(gòu)中,選擇一個最合適的進程,過程是怎么的呢?
1. 從0下表開始遍歷queue[140]
2. 找到第一個非空隊列,該隊列必定為優(yōu)先級最高的隊列
3. 拿到選中隊列的第一個進程,開始運行,調(diào)度完成!
4. 遍歷queue[140]時間復(fù)雜度是常數(shù)!但還是太低效了!
- bitmap[5]:一共140個優(yōu)先級,一共140個進程隊列,為了提高查找非空隊列的效率,就可以用 5*32 個比特位表示隊列是否為空,即位段,這樣,便可以大大提高查找效率!
過期隊列
- 過期隊列和活動隊列結(jié)構(gòu)一模一樣
- 過期隊列上放置的進程,都是時間片耗盡的進程,或者是剛到運行對列中的進程。
- 當(dāng)活動隊列上的進程都被處理完畢之后,對過期隊列的進程進行時間片重新計算
active指針和expired指針
- active指針永遠指向活動隊列
- expired指針永遠指向過期隊列
- 可是活動隊列上的進程會越來越少,過期隊列上的進程會越來越多,因為進程時間片到期時一直都存在的。
- 沒關(guān)系,在合適的時候,只要能夠交換active指針和expired指針的內(nèi)容,就相當(dāng)于有具有了一批新的活動進程!
總結(jié)
在系統(tǒng)當(dāng)中查找一個最合適調(diào)度的進程的時間復(fù)雜度是一個常數(shù),不隨著進程增多而導(dǎo)致時間成本增加,我們稱之為進程調(diào)度O(1)算法
3.命令行參數(shù)
?命令行參數(shù)是什么?
我們看下面一段代碼看下面一段代碼
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 0;
for(;i<argc;i++)
{
printf("%d: %s\n",i, argv[i]);
}
printf("hello world\n");
return 0;
}
運行輸出:?
可以發(fā)現(xiàn)main函數(shù)是可以傳參的,shell 會自動講命令行輸入的一大串字符,按空格分割成小的字串,第一參數(shù)argc存命令行字串個數(shù),第二個參數(shù)argc是一個指針數(shù)組存字串內(nèi)容。
命令行參數(shù),可以支持各種指令級別的命令行選項的設(shè)置!這樣就可以理解之前學(xué)的指令,選項是什么關(guān)系了。
我們來模擬實現(xiàn)一個計算器
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if(argc != 4)
{
printf("Use error\nUsage: %s op[-add|sub|mul|div] d1 d2\n",argv[0]);
return 1;
}
// 你的程序一定有4個命令行參數(shù),第一個是程序名
int x = atoi(argv[2]);
int y = atoi(argv[3]);
if(strcmp(argv[1],"-add")==0)
{
int result = x+y;
printf("%d+%d=%d\n",x,y,result);
}
else if(strcmp(argv[1],"-sub")==0)
{
int result = x-y;
printf("%d-%d=%d\n",x,y,result);
}
else if(strcmp(argv[1],"-mul")==0)
{
int result = x*y;
printf("%d*%d=%d\n",x,y,result);
}
else if(strcmp(argv[1],"-div")==0)
{
if(0==y)
{
printf("%d/%d=error! div zero\n",x,y);
}
else
{
int result = x/y;
printf("%d/%d=%d\n",x,y,result);
}
}
else
{
printf("Use error,you should use the right command line\nUsage: %s op[-add|sub|mul|div] d1 d2\n",argv[0]);
}
return 0;
}
?運行結(jié)果:
對于為什么系統(tǒng)命令不用加 ./指定位置?,而我們寫的程序就需要寫 ./?,這就涉及到環(huán)境變量了,下一篇文章我們講解環(huán)境變量。文章來源:http://www.zghlxwxcb.cn/news/detail-754331.html
本篇結(jié)束!文章來源地址http://www.zghlxwxcb.cn/news/detail-754331.html
到了這里,關(guān)于Linux:進程優(yōu)先級與命令行參數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!