一、進(jìn)程優(yōu)先級(jí)
1、基本概念
cpu 資源分配的先后順序,就是指進(jìn)程的優(yōu)先權(quán)(priority) .優(yōu)先權(quán)高的進(jìn)程有優(yōu)先執(zhí)行權(quán)利。配置進(jìn)程優(yōu)先權(quán)對(duì)多任務(wù)環(huán)境的 Linux 很有用,可以改善系統(tǒng)性能。 還可以把進(jìn)程運(yùn)行到指定的 CPU 上,這樣一來,把不重要的進(jìn)程安排到某個(gè) CPU,可以大大改善系統(tǒng)整體性能。
2、查看以及修改系統(tǒng)進(jìn)程的優(yōu)先級(jí)
在 Linux 或者 unix 系統(tǒng)中,用ps –al命令則會(huì)類似輸出以下幾個(gè)內(nèi)容, 其中:
UID : 代表執(zhí)行者的身份
PID : 代表這個(gè)進(jìn)程的代號(hào)
PPID :代表這個(gè)進(jìn)程是由哪個(gè)進(jìn)程發(fā)展衍生而來的,亦即父進(jìn)程的代號(hào)
PRI :代表這個(gè)進(jìn)程可被執(zhí)行的優(yōu)先級(jí),其值越小越早被執(zhí)行
NI :代表這個(gè)進(jìn)程的 nice 值,其表示進(jìn)程可被執(zhí)行的優(yōu)先級(jí)的修正數(shù)值。
我們看到我們現(xiàn)在有兩個(gè)進(jìn)程 bash ps 它們的進(jìn)程優(yōu)先級(jí)都是 80,如果我們要修改它們的優(yōu)先級(jí)就要用到 NI 的 nice 值了。
?
P?R?I?(?n?e?w?)?=?P?R?I?(?o?l?d?)?+?n?i?c?e?PRI(new)=PRI(old)+nicePRI(new)=PRI(old)+nice
?
從這個(gè)公式中我們知道 新的 PRI = 老的 PRI + nice 值,但是這個(gè)老的 PRI 的值是指 PRI 最初的默認(rèn)值,例如上面的bash ps 是 80,那么這個(gè) PRI 以后不論怎么改老的 PRI 都是 80,當(dāng)然大多數(shù)進(jìn)程默認(rèn)的 PRI 都是 80。
此外 nice 是有范圍的!其取值范圍是 - 20 至 19,一共 40 個(gè)級(jí)別。
于是下面我們?nèi)L試去更改processC進(jìn)程的優(yōu)先級(jí)。
注意:將進(jìn)程優(yōu)先級(jí)調(diào)高(即將 nice 值設(shè)置為負(fù)數(shù))需要 root 用戶進(jìn)行操作!
修改進(jìn)程優(yōu)先級(jí)的 Linux 指令
top命令
進(jìn)入top后按 "r" -> 輸入進(jìn)程 PID -> 輸入 nice 值
按下 “r”
輸入 -20
再次[查看進(jìn)程]的相關(guān)信息:
我們發(fā)現(xiàn)進(jìn)程的優(yōu)先級(jí)確實(shí)改變了,但是我們能改變進(jìn)程優(yōu)先級(jí)有限[ ? 20 , 19 ] [-20,19][?20,19],因?yàn)檎{(diào)度器不允許我們將一個(gè)進(jìn)程設(shè)置的優(yōu)先級(jí)太高,進(jìn)而導(dǎo)致其他進(jìn)程難以被調(diào)度。
3、一些其他的關(guān)于進(jìn)程優(yōu)先級(jí)的指令和函數(shù)調(diào)用
nice指令,nice 命令的功能是用于調(diào)整進(jìn)程的優(yōu)先級(jí),合理分配系統(tǒng)資源。-n 參數(shù)是 nice 值的優(yōu)先級(jí)別,
以 nice 值為 -5 的方式執(zhí)行指定程序
查看進(jìn)程優(yōu)先級(jí)
renice命令可以修改正在運(yùn)行的進(jìn)程的調(diào)度優(yōu)先級(jí)。
renice更改一個(gè)或多個(gè)進(jìn)程的調(diào)度優(yōu)先級(jí)。第一個(gè)參數(shù)是要使用的優(yōu)先級(jí)值,另一個(gè)參數(shù)被表示為進(jìn)程標(biāo)識(shí)信息。
?
renice?[-n]?priority?[-gpu]?identifier
?
-g, 后面加組的 pgid, 改變一個(gè)組的進(jìn)程優(yōu)先級(jí)
-u, 后面加 user name 或 uid,改變一個(gè)用戶所擁有的進(jìn)程優(yōu)先級(jí)。
-p, 后面加 pid ,改變一個(gè)進(jìn)程的進(jìn)程優(yōu)先級(jí)。
使用renice命令
函數(shù)調(diào)用
在 Linux 中關(guān)于改變進(jìn)程優(yōu)先級(jí)函數(shù)調(diào)用主要有兩個(gè):getpriority() 與setpriority()。
4、與進(jìn)程優(yōu)先級(jí)有關(guān)的一些進(jìn)程性質(zhì)
競(jìng)爭(zhēng)性: 系統(tǒng)進(jìn)程數(shù)目眾多,而 CPU 資源只有少量,甚至 1 個(gè),所以進(jìn)程之間是具有競(jìng)爭(zhēng)屬性的。為了高效完成任務(wù),更合理競(jìng)爭(zhēng)相關(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ā)
二、環(huán)境變量
1、基本概念
環(huán)境變量 (environment variables) 一般是指在操作系統(tǒng)中用來指定操作系統(tǒng)運(yùn)行環(huán)境的一些參數(shù),環(huán)境變量通常具有某些特殊用途,在系統(tǒng)當(dāng)中通常具有全局特性。
如:我們?cè)诰帉?C/C++ 代碼的時(shí)候,在鏈接的時(shí)候,從來不知道我們的所鏈接的動(dòng)態(tài)[靜態(tài)庫]在哪里,但是照樣可以鏈接成功,生成可執(zhí)行程序,原因就是有相關(guān)環(huán)境變量幫助編譯器進(jìn)行查找。
2、和環(huán)境變量相關(guān)的命令
1.env: 顯示所有環(huán)境變量
2.echo: 顯示的變量值 (需要帶上 $ 符號(hào))
3.export: 設(shè)置一個(gè)新的環(huán)境變量,或者將本地[變量提升]成環(huán)境變量。
4.unset: 清除環(huán)境變量
5.set: 顯示本地定義的 shell 變量和環(huán)境變量
3、Linux 中的常見環(huán)境變量介紹
PATH : 指定命令的搜索路徑
例如我們使用的 Linux 中 ls pwd命令,其實(shí)就是一個(gè)個(gè) C 語言寫的一個(gè)個(gè)小程序,為什么我們運(yùn)行自己寫的程序就要用./ + 自己的程序名 ,而我們運(yùn)行l(wèi)s pwd 從來不加./,這就和環(huán)境變量 PATH 有關(guān)了!
我們查看環(huán)境變量可以使用echo $環(huán)境變量命令:
默認(rèn)情況下我們使用的 Linux 指令會(huì)去 PATH 路徑下尋找源程序,由于ls指令的路徑位置就在 PATH 的環(huán)境變量中所以我們可以不用加./
我們現(xiàn)在嘗試將我們的路徑添加到 PATH 環(huán)境變量里面,來讓我們的程序也不需要加./,這時(shí)我們就需要使用一個(gè)新的指令了:export
export令可以將本地變量提升成環(huán)境變量,于是我們將我們的路徑添加到 PATH 中就可以這樣寫:
?
export?PATH=$PATH:你要添加的路徑
?
當(dāng)然我們使用export命令是暫時(shí)將本地變量提升為環(huán)境變量,當(dāng)我們退出云服務(wù)器或關(guān)機(jī)重啟都會(huì)消除export暫時(shí)提升的環(huán)境變量,想要真正的修改我們要修改相應(yīng)的配置文件。
當(dāng)然我們還可以將我們寫的程序拷貝到 Linux 的 PATH 默認(rèn)路徑下,這樣我們也不用使用./了,在 Linux 中,把可執(zhí)行程序,拷貝到系統(tǒng)默認(rèn)路徑下,讓我們可以直接訪問的方式,相當(dāng)于 Linux 下軟件的安裝!
HOME : 指定用戶的主工作目錄 (即用戶登陸到 Linux 系統(tǒng)中時(shí), 默認(rèn)的目錄)
由于 HOME 環(huán)境變量的存在,我們使用相同的命令cd ~卻得到了不同的結(jié)果。
SHELL : 當(dāng)前 Shell, 它的值通常是 / bin/bash。
4、環(huán)境變量的組織方式以及在 C 代碼中如何獲取環(huán)境變量
在 Shell 內(nèi)部,環(huán)境變量其實(shí)是以環(huán)境變量表的方式進(jìn)行維護(hù)的!
此外環(huán)境變量還具有全局性,我們知道我們?cè)?bash 下運(yùn)行的程序其父進(jìn)程都是 bash, 那么 bash 就可以將自己的環(huán)境變量傳遞給子進(jìn)程,并在子進(jìn)程中發(fā)揮作用!
我們來看一段代碼來驗(yàn)證環(huán)境變量具有全局性。
1. C 庫函數(shù)getenv()獲得單個(gè)環(huán)境變量
在看驗(yàn)證代碼之前我們先了解一個(gè)函數(shù)getenv() getenv()是一個(gè) C 庫函數(shù), 它可以獲取一個(gè)環(huán)境變量的內(nèi)容
函數(shù)原型:
函數(shù)的參數(shù)是環(huán)境變量的名稱,返回值是一個(gè)char*字符串記錄了環(huán)境變量里面的內(nèi)容, 如果調(diào)用失敗會(huì)返回 NULL 指針。
實(shí)例代碼
?
#include???? #include ??? int?main() { ????char*?env?=??getenv("USER");//USER是環(huán)境變量 ????if(env?==?NULL) ????{ ????????perror("getenv?fail:"); ????} ????printf("%s ",env); ????return?0; }
?
代碼輸出結(jié)果
我們?cè)诖a里面多出來的USER變量就是來自 Shell 傳遞給我們的test1c進(jìn)程的環(huán)境變量!
2. main()函數(shù)參數(shù)獲得環(huán)境變量
此外我們我們還可以用main函數(shù)的參數(shù)來獲得所有環(huán)境變量的地址,通過地址我們也能遍歷所有環(huán)境變量
函數(shù)原型
?
int?main(int?argc,?char?*argv[],?char?*envp[]);
?
在這里我們先不談?wù)摵瘮?shù)的參數(shù) argc *argv[], 我們來談?wù)摰谌齻€(gè)參數(shù)!其中*envp[]是一個(gè)字符數(shù)組指針,指向的是一個(gè)指針數(shù)組,數(shù)組名代表首元素的地址,首元素是一個(gè)字符指針,*envp[]剛好又是指向首元素的指針,故其實(shí)*envp[]其實(shí)是一個(gè)二級(jí)指針!
明白了這些,我們來看下面一段代碼:
?
#includeint?main(int?argc,?int?*argv[],?int?*envp[]) { ????for(int?i?=0;?envp[i]?!=?NULL?;?++i) ????{ ???????//打印所有環(huán)境變量,相當(dāng)于 env 命令! ????????printf("envp[%d]-->%s ",?i,?envp[i]); ????} ????return?0; }
?
可以看到我們確實(shí)打印出了所有的環(huán)境變量,而且這個(gè)環(huán)境變量來自于其父進(jìn)程 bash。
3. C 語言全局變量environ獲得環(huán)境變量
變量詳情:
environ變量是一個(gè)二級(jí)指針與main()函數(shù)參數(shù)的char *envp[]類似。遍歷所有環(huán)境變量也可以這樣寫:
?
#include???????? #include ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????int?main() { ????extern?char**?environ; ????for(int?i?=0;?environ[i]?!=?NULL;?++i) ????{ ????????printf("environ[%d]-->%s ",?i,?environ[i]); ????} ????return?0; }
?
5、不同用戶的環(huán)境變量是怎么形成的
通過上面的講解我們知道了環(huán)境變量的概念與作用,環(huán)境變量中的每一個(gè),都有自己的用途: 有的是進(jìn)行路徑查找的,有的時(shí)進(jìn)行身份認(rèn)證的,有的時(shí)進(jìn)行動(dòng)態(tài)庫查找的,有的是用來進(jìn)行確認(rèn)當(dāng)前路徑等等每一個(gè)環(huán)境變量都有自己的特定應(yīng)用場(chǎng)景。
我們也知道為什么,對(duì)于不同的用戶其環(huán)境變量也并不相同,例如我們上面的 root 用戶的環(huán)境變量與 pan 的環(huán)境變量有的一樣有的不一樣,那么 Linux 是怎樣形成不同的環(huán)境變量的呢?
這里先給出結(jié)論:環(huán)境變量本質(zhì)就是一個(gè)內(nèi)存級(jí)的一張表,這張表由用戶在登陸會(huì)統(tǒng)的時(shí)候,給特定用戶形成屬于自己的環(huán)境變量表。
在我們的家目錄下有兩個(gè)文件叫 .bashrc .bash_profile 在根目錄下有一個(gè)bashrc的文件
打開這些文件看看!
6、main() 函數(shù)的命令行參數(shù)
在前面我們談?wù)撝形覀冋f到過main()函數(shù)的參數(shù)問題,我們還有兩個(gè)參數(shù)沒有談?wù)搃nt argc char *argv[]?,F(xiàn)在我們來討論它們!
由于 C 語言中無法傳遞整個(gè)數(shù)組,所以在函數(shù)中想要獲得數(shù)組元素的個(gè)數(shù)必須在傳參時(shí)就要提前傳遞好,于是其中int argc 就是char *argv[]數(shù)組指針指向的數(shù)組的有效元素個(gè)數(shù),不包含 NULL。
這個(gè)char *argv[]是一個(gè)數(shù)組指針,其指向的數(shù)組里面存放的都是char *的指針,這些char *的指針指向的內(nèi)容需要我們使用命令行的方式進(jìn)行設(shè)置。
我們先看下面一段代碼:
?
#include???? int?main(int?argc,?int?*argv[]) { ?????printf("argc?=?%d ",argc); ?????for(int?i?=?0;?argv[i]?!=?NULL;?++i) ????{ ????????printf("argv[%d]-->%s ",?i,?argv[i]); ????} ????return?0; }
?
運(yùn)行結(jié)果:
我們 Linux 中l(wèi)s命令有許多參數(shù)如-a -l -d -n,ls本質(zhì)上就是 C 語言寫的一個(gè)程序,它為什么能根據(jù)不同的參數(shù)執(zhí)行不同的功能就是因?yàn)槭褂昧?mian() 函數(shù)的命令行參數(shù)!
審核編輯:湯梓紅
評(píng)論
查看更多