?? 前言
在學(xué)完進(jìn)程狀態(tài)之后,本章我們將來學(xué)習(xí)一下環(huán)境變量,還有進(jìn)程優(yōu)先級(jí)等??????……
本文實(shí)驗(yàn)系統(tǒng):CentOS 7.6
~
1. 進(jìn)程優(yōu)先級(jí)
1.1 什么是優(yōu)先級(jí):
- 優(yōu)先級(jí)是權(quán)限嗎?
在之前我們講解過什么是權(quán)限:?? 傳送門
我們這里講的優(yōu)先級(jí)并不是權(quán)限,那么優(yōu)先級(jí)到底是什么呢?
- 如果我們說權(quán)限是能不能的問題的話
- 那么優(yōu)先級(jí)就是 — 能!但只不過是先還是后的問題
- 優(yōu)先級(jí)是進(jìn)程獲取資源的先后順序
- 為什么會(huì)存在優(yōu)先級(jí)?
- 排隊(duì)的本質(zhì)叫做確認(rèn)優(yōu)先級(jí)
- 那么排隊(duì)的最根本原因是 — 資源不夠!
系統(tǒng)里面永遠(yuǎn)都是,進(jìn)程占大多數(shù),而資源是少數(shù)!所以,進(jìn)程競(jìng)爭(zhēng)資源是常態(tài)!一定需要確認(rèn)先后!
Linux下的優(yōu)先級(jí)的相關(guān)概念和操作(怎么辦):
- Linux優(yōu)先級(jí)的構(gòu)成:
- priority + nice
我們可以根據(jù)自己的需求將進(jìn)程的優(yōu)先級(jí)進(jìn)行修改:
- 要更改進(jìn)程優(yōu)先級(jí),需要更改不是
pri
,而是NI
- nice:進(jìn)程優(yōu)先級(jí)的修正數(shù)據(jù)!
數(shù)字越小,代表優(yōu)先級(jí)越高,數(shù)字越大,代表優(yōu)先級(jí)越低。
1.2 如何修改優(yōu)先級(jí):
我們可以通過代碼的方式來對(duì)優(yōu)先級(jí)進(jìn)行修改,但是我們只講通過修改nice
的方式來對(duì)進(jìn)程優(yōu)先級(jí)進(jìn)行修改。
注意:
- 雖然我們可以對(duì)Linux進(jìn)程的優(yōu)先級(jí)進(jìn)行修改
- 但是Linux不允許進(jìn)程無節(jié)制的設(shè)置優(yōu)先級(jí)
不建議隨便改Liunx系統(tǒng)中的優(yōu)先級(jí),因?yàn)槲覀儾⒉欢{(diào)度器的調(diào)度算法,隨便的更改優(yōu)先級(jí)就是變相的插隊(duì),可能讓我們自己寫的進(jìn)程優(yōu)先得到了某種資源,但是可能會(huì)打破調(diào)度系統(tǒng)的平衡。
每次設(shè)置優(yōu)先級(jí),這個(gè)old優(yōu)先級(jí)都會(huì)被恢復(fù)成為80。
- 修改方式:
- top + r:改優(yōu)先級(jí)。
一個(gè)進(jìn)程的優(yōu)先級(jí)不能被輕易修改,會(huì)打破調(diào)度器平衡,如果非得設(shè)置就必須具備超級(jí)用戶的權(quán)限。
nice值的修改并不是無節(jié)制的,是有一定取值范圍的:
- nice [-20, 19]
- prio [60,99]
如果nice修改的值超出了指定的修改范圍,那么就會(huì)取其上、下限。
當(dāng)我們?cè)O(shè)置完該進(jìn)程的pri為60之后,再次對(duì)該進(jìn)程的nice進(jìn)行修改,此時(shí)pri會(huì)再次恢復(fù)到80??!
- prio = prio_old + nice
2. 進(jìn)程的其他概念
2.1 競(jìng)爭(zhēng)性與獨(dú)立性:
競(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í)。
進(jìn)程在使用資源的時(shí)候是不允許別的進(jìn)程來使用的。競(jìng)爭(zhēng)方式一:排隊(duì)。
當(dāng)一個(gè)進(jìn)程在使用資源的時(shí)候,是不允許別的進(jìn)程也來使用該資源的基本上所有的外設(shè)和CPU都是這樣子的。
獨(dú)立性: 多進(jìn)程運(yùn)行,需要獨(dú)享各種資源,多進(jìn)程運(yùn)行期間互不干擾,進(jìn)程運(yùn)行是有獨(dú)立性的。
進(jìn)程運(yùn)行具有獨(dú)立性,不會(huì)因?yàn)橐粋€(gè)進(jìn)程掛掉或者異常,而導(dǎo)致其他進(jìn)程出現(xiàn)問題!
使用STL將對(duì)象放到各種容器中,就像在Linux系統(tǒng)當(dāng)中將PCB放來放去是一個(gè)道理。
2.2 并行與并發(fā):
并行: 多個(gè)進(jìn)程在多個(gè)CPU
下分別,同時(shí)進(jìn)行運(yùn)行,這稱之為并行。
我的電腦是單CPU的,但是我的電腦中有各種進(jìn)程都可以在跑,這是什么原因?
此時(shí)我們不得不清楚一個(gè)概念:
多個(gè)進(jìn)程都在你的系統(tǒng)中運(yùn)行 != 多個(gè)進(jìn)程都在你的系統(tǒng)中同時(shí)運(yùn)行
- 不要以為進(jìn)程一旦占有CPU, 就會(huì)一直執(zhí)行到結(jié)束,才會(huì)釋放CPU資源!
-
我們遇到的大部分操作系統(tǒng)都是分時(shí)的!
操作系統(tǒng)會(huì)給每一個(gè)進(jìn)程,在一次調(diào)度周期中,賦予一個(gè)時(shí)間片的概念! - 在一個(gè)時(shí)間段內(nèi),多個(gè)進(jìn)程都會(huì)通過切換交叉的方式,讓多個(gè)進(jìn)程代碼,在一段時(shí)間內(nèi)都得到推進(jìn)
- 例如一個(gè)進(jìn)程只能在CPU上執(zhí)行10ms就要從CPU上扒下來,讓其他的進(jìn)程來執(zhí)行
- 這種現(xiàn)象,我們叫做并發(fā)!
這就是跑死循環(huán)不卡死的原因,可能會(huì)卡一點(diǎn),因?yàn)榇嬖谶M(jìn)程的切換。
操作系統(tǒng)中的一個(gè)軟件叫調(diào)度器幫我們做的將進(jìn)程放在CPU再扒下來,賦予執(zhí)行的時(shí)長(zhǎng),為什么是這么長(zhǎng)時(shí)間等等…
并發(fā): 多個(gè)進(jìn)程在一個(gè)CPU
下采用進(jìn)程切換的方式,在一段時(shí)間之內(nèi),讓多個(gè)進(jìn)程都得以推進(jìn),稱之為并發(fā)。
如果存在多個(gè)CPU的情況,在任何一個(gè)時(shí)刻,都有可能有兩個(gè)進(jìn)程在同時(shí)被運(yùn)行(就是在CPU上運(yùn)行)
2.3 進(jìn)程間優(yōu)先級(jí)的體現(xiàn):
操作系統(tǒng),就是簡(jiǎn)單的根據(jù)隊(duì)列來進(jìn)行先后調(diào)度的嗎??有沒有可能突然來了一個(gè)優(yōu)先級(jí)更高的進(jìn)程??
當(dāng)代計(jì)算機(jī)都具有的一種機(jī)制:搶占式內(nèi)核!
正在運(yùn)行的低優(yōu)先級(jí)進(jìn)程,但如果來個(gè)優(yōu)先級(jí)更高的進(jìn)程,我們的調(diào)度器會(huì)直接把進(jìn)程從
CPU
上剝離,放上優(yōu)先級(jí)更高的進(jìn)程,進(jìn)程搶占。
進(jìn)程搶占:
有可能進(jìn)程正在跑,突然來了個(gè)優(yōu)先級(jí)更高的進(jìn)程,操作系統(tǒng)直接就把這個(gè)進(jìn)程扒下來了,讓優(yōu)先級(jí)更高的進(jìn)程來跑。
2.4 O(1) 調(diào)度算法:
這里我們就簡(jiǎn)單介紹一下:
- 允許不同優(yōu)先級(jí)的進(jìn)程存在
- 相同優(yōu)先級(jí)的進(jìn)程,是可能存在多個(gè)的!
而我們之前學(xué)習(xí)過數(shù)據(jù)結(jié)構(gòu),我們知道隊(duì)列是先進(jìn)先出的,是不允許隨意插入的,那么優(yōu)先級(jí)如何體現(xiàn)出來呢?
操作系統(tǒng)采用的是哈希的數(shù)據(jù)結(jié)構(gòu),哈希復(fù)習(xí):傳送門
根據(jù)不同的優(yōu)先級(jí),將特定的進(jìn)程放入不同的隊(duì)列中!
同時(shí)操作系統(tǒng)還做了另外的結(jié)構(gòu)優(yōu)化,因?yàn)榇嬖诖罅坎煌瑑?yōu)先級(jí)的進(jìn)程,如果遍歷哈希表的話就是線性探測(cè),這里則是運(yùn)用位圖來判斷所需進(jìn)程在不在,位圖復(fù)習(xí):傳送門
操作系統(tǒng)會(huì)把活躍的進(jìn)程放在一起,舊的進(jìn)程放在一起,最后再交換指向兩個(gè)哈希表的指針,就將兩個(gè)哈希表交換了。
- swap(active, old) ;
2.4 進(jìn)程上下文:
CPU
一定具有把數(shù)據(jù)暫時(shí)保存起來的能力。CPU
內(nèi)的寄存器更多是用來保存一些臨時(shí)數(shù)據(jù)。CPU
內(nèi)的寄存器是:可以臨時(shí)的存儲(chǔ)數(shù)據(jù),非常少,但是非常重要。
int func()
{
int a = 10 + 20;
return a;
}
int main()
{
int ret = func();
return 0;
}
把a(bǔ)的值放到了寄存器eax里面,用寄存器的方式來充當(dāng)返回值,把寄存器里面的值mv到ret變量里,也就是把數(shù)據(jù)從CPU放到了內(nèi)存里面。
- 當(dāng)進(jìn)程再被執(zhí)行的過程中,一定會(huì)存在大量的臨時(shí)數(shù)據(jù),會(huì)暫存在CPU內(nèi)的寄存器中!
我們把進(jìn)程在運(yùn)行中產(chǎn)生的各種寄存器數(shù)據(jù),我們叫做進(jìn)程的硬件上下文數(shù)據(jù)。
- 當(dāng)進(jìn)程被剝離:需要保存上下文數(shù)據(jù)
- 當(dāng)進(jìn)程恢復(fù)的時(shí)候:需要將曾經(jīng)保存的上下文數(shù)據(jù)恢復(fù)到寄存器中
上下文在哪里保存呢?—— task struct
3. 環(huán)境變量
3.1 環(huán)境變量的概念:
環(huán)境變量(environment variables)一般是指在操作系統(tǒng)中用來指定操作系統(tǒng)運(yùn)行環(huán)境的一些參數(shù)。
環(huán)境變量的用途:
如:我們?cè)诰帉?code>C / C++代碼的時(shí)候,在鏈接的時(shí)候,從來不知道我們的所鏈接的動(dòng)態(tài)靜態(tài)庫(kù)在哪里,但是照樣可以鏈接成功,生成可執(zhí)行程序,原因就是有相關(guān)環(huán)境變量幫助編譯器進(jìn)行查找。環(huán)境變量通常具有某些特殊用途,還有在系統(tǒng)當(dāng)中通常具有全局特性。
我們之前學(xué)習(xí)的各種指令,工具,和可執(zhí)行文件:
- 都是可執(zhí)行程序,我們可以將自己寫的可執(zhí)行程序叫指令,系統(tǒng)的指令叫命令程序二進(jìn)制文件
- 其實(shí)大家都可以既叫做指令,又叫做工具, 又叫做可執(zhí)行程序,都可以
- 其實(shí)是一碼事…
3.2 查看環(huán)境變量:
Linux
查看環(huán)境變量的方法:
- 而我們自己寫的可執(zhí)行程序?yàn)槭裁匆獛下窂讲拍軋?zhí)行,而系統(tǒng)中的命令則是不需要帶路徑??
- 系統(tǒng)中是存在相關(guān)的環(huán)境變量,保存了程序的搜索路徑的!
- 系統(tǒng)中搜索可執(zhí)行程序的環(huán)境變量叫做PATH!
解釋:
環(huán)境變量
PATH
里面有多種變量,中間用冒號(hào):
分割開,其中我們?cè)趫?zhí)行某個(gè)程序時(shí):例如在執(zhí)行Is時(shí), 當(dāng)識(shí)別到有Is輸入時(shí), 會(huì)在上面的路徑中一個(gè)一個(gè)的搜索,只要在特定路徑下找到了Is,就會(huì)執(zhí)行特定路徑下的Is,執(zhí)行完就停止搜索不再往后走了,換言之PATH就提供了可執(zhí)行程序搜索的路徑。Is或者是很多指令在PATH里面是可以被找到的。
那我們自己寫的程序,生成的可執(zhí)行程序之后,我們也想不通過帶路徑的方式像指令一樣執(zhí)行它,我們有兩種方式:
3.3 修改環(huán)境變量:
直接mytest當(dāng)做指令用,直接將可執(zhí)行程序執(zhí)行起來,不帶路徑:
方法一:直接將可執(zhí)行程序拷貝到系統(tǒng)當(dāng)中
一開始不做任何處理:
不建議自己安裝,更不建議將自己的指令拷貝到Linux系統(tǒng)的目錄下,因?yàn)闀?huì)污染Linux
系統(tǒng)的命令池。
第二種:將mytest的所處路徑也添加到環(huán)境變量里
命令行變量分兩種:
- 普通變量
- 環(huán)境變重(全局)
定義變量可不僅僅只能在C/C++中,Linux命令行或者系統(tǒng)中也是可以直接定義變量的。
但是定義的是普通變量,通過查看環(huán)境變量的方式查看不了。
export導(dǎo)出環(huán)境變量,就可以在系統(tǒng)中可以查看的環(huán)境變量。
所以我們就可以通過export
將環(huán)境變量中的PATH
給改了,就可以實(shí)現(xiàn)不用路徑直接執(zhí)行可執(zhí)行程序了。
但是不能通過上述方式,因?yàn)檫@樣改的話就將全部的PATH給改了,那么其他的指令也就用不成了。
不過我們也不用過于擔(dān)心,我們?cè)诿钚猩显O(shè)置的環(huán)境變量具有臨時(shí)性的,將終端關(guān)掉重啟就恢復(fù)了。
環(huán)境變量本身就在內(nèi)存中存著呢,并不是以文件的方式存在的,改了也不影響,下次登錄的時(shí)候會(huì)重新讀取系統(tǒng)的配置文件,重新生成環(huán)境變量,如果想讓配置的環(huán)境變量永久有效的話,是需要更改配置文件的。
- 登錄程序會(huì)自動(dòng)執(zhí)行Linux上的程序,幫我們?cè)赽ash的上下文當(dāng)中導(dǎo)出一些變量,這些變量是從文件中來的。
- 可以理解成,就相當(dāng)于在啟動(dòng)的時(shí)候讀取配置文件,跟我們寫程序一樣,將數(shù)據(jù)讀到內(nèi)存里,然后在內(nèi)存里env就能查看到對(duì)應(yīng)的環(huán)境變量了。
系統(tǒng)中相關(guān)配置文件一般在:
正確修改環(huán)境變量:
備注:
環(huán)境變量輕易不要修改,非要改最好是新增,不要做覆蓋。
which
是通過環(huán)境變量來查找可執(zhí)行程序的路徑。
3.4 和環(huán)境變量相關(guān)的命令:
- echo: 顯示某個(gè)環(huán)境變量值
- export: 設(shè)置一個(gè)新的環(huán)境變量
- env: 顯示所有環(huán)境變量
- unset: 清除環(huán)境變量
- set: 顯示本地定義的shell變量和環(huán)境變量
前幾個(gè)我們已經(jīng)講的差不多了,我們來介紹后幾個(gè):
- unset:
- set:
aa叫局部變量查不到,可以通過export直接倒成環(huán)境變量,此時(shí)再查就能查到了。
查看本地變量:
set的環(huán)境變量和本地變量都能查到。
3.5 環(huán)境變量的獲?。?/h3>
3.5 - 1 main函數(shù)可以帶參數(shù)嗎?可以帶多少?
我們先來看main函數(shù)帶兩個(gè)參數(shù):
#include <stdio.h>
int main(int argc, char* argv[])
{
int i = 0;
for(i = 0; i < argc; i++)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
return 0;
}
將命令行傳遞給命令行參數(shù):
-
char* argv[]
是個(gè)指針數(shù)組,而int argc
則是指針數(shù)組中元素的個(gè)數(shù)。 - 可執(zhí)行程序和選項(xiàng)都是字符串,最后都以指針數(shù)組的方案存在了指針數(shù)組中。
- 指針數(shù)組中存的是字符串的起始地址
- 最后以
NULL
結(jié)尾
我們給main
函數(shù)傳遞的argc,char* argv[]
是命令行參數(shù),傳遞的是:命令行中輸入的程序名和選項(xiàng)!!
具體是哪個(gè)字符串的起始地址呢?
這樣就傳遞命令行參數(shù)了。
3.5 - 2 傳遞參數(shù)的意義是什么
命令行計(jì)算器:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
if(argc != 4)
{
printf("Usage: %s [-a|-s|-m|-d] one_data two_data\n", argv[0]);
return 0;
}
int x = atoi(argv[2]);
int y = atoi(argv[3]);
if(strcmp("-a", argv[1]) == 0)
{
printf("%d+%d=%d\n",x, y, x + y);
}
else if(strcmp("-s", argv[1]) == 0)
{
printf("%d-%d=%d\n",x, y, x - y);
}
else if(strcmp("-m", argv[1]) == 0)
{
printf("%d*%d=%d\n",x, y, x * y);
}
else if(strcmp("-d", argv[1]) == 0 && y != 0)
{
printf("%d/%d=%d\n",x, y, x / y);
}
else
{
printf("Usage: %s [-a|-s|-m|-d] one_data two_data\n", argv[0]);
}
return 0;
}
運(yùn)行結(jié)果:
意義:
- 同一個(gè)程序,通過傳遞不同的參數(shù),讓同一個(gè)程序有不同的執(zhí)行邏輯,執(zhí)行結(jié)果。
- Linux系統(tǒng)中,會(huì)根據(jù)不通的選項(xiàng),讓不同的命令,可以有不同的表現(xiàn)!指令中那么多選項(xiàng)的由來和起作用的方式!!
-
ls -a -l -i
不同的選項(xiàng)代表的含義不一樣。
那么命令行參數(shù)是怎么傳遞給main函數(shù)的呢??
- 進(jìn)程控制講
3.6 進(jìn)程獲取環(huán)境變量的方法:
方法一:main函數(shù)的第三個(gè)參數(shù)
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
void func(void)
{
printf("hehe\n");
}
int main(int argc, char* argv[], char* env[])
{
//func(1, 1);
int i = 0;
for(i = 0; env[i]; i++)
{
printf("env[%d]: %s\n", i, env[i]);
}
return 0;
}
打印出來的就是各種環(huán)境變量了:
-
char* env[]
也是個(gè)指針數(shù)組 - 數(shù)組里的每個(gè)元素都是指向一個(gè)字符串
- 每個(gè)字符串就是一個(gè)環(huán)境變量
- 最后以
NULL
結(jié)尾
一個(gè)進(jìn)程是會(huì)被傳入環(huán)境變量參數(shù)的,每個(gè)進(jìn)程都是的??!
我們自己的程序跑起來變成進(jìn)程,這個(gè)進(jìn)程就被調(diào)用方傳入了環(huán)境變量了。
如果一個(gè)C語(yǔ)言函數(shù)在聲明中沒有帶參數(shù),但是我們強(qiáng)制給其帶參的話并不報(bào)錯(cuò)。
而且強(qiáng)行傳的參數(shù),依舊壓棧,依舊形成臨時(shí)變量,只不過后面沒有使用罷了。
給函數(shù)定義的時(shí)候形參帶上void的話,強(qiáng)制傳參才會(huì)報(bào)錯(cuò)。
進(jìn)程想獲得環(huán)境變量的第一種方法,那就是main
函數(shù)的第三個(gè)參數(shù),傳進(jìn)來的值就是一個(gè)指針數(shù)組,就可以通過指針數(shù)組的方案來遍歷。
方法二:通過C語(yǔ)言內(nèi)部維護(hù)的environ
int main()
{
extern char** environ;
for (int i = 0; environ[i]; i++)
{
printf("%d: %s\n", i, environ[i]);
}
return 0;
}
方法三:用接口getenv()
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* val = getenv("PATH");
printf("%s\n", val);
return 0;
}
3.7 我為什么要獲取環(huán)境變量:
以后有用途,萬一有用途~
我們寫一個(gè)只能自己運(yùn)行的程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
//讓程序只能自己執(zhí)行
char* id = getenv("USER");
//忽略大小寫
if(strcasecmp(id, "Zh_Ser") != 0)
{
printf("權(quán)限拒絕!\n");
return 0;
}
printf("成功執(zhí)行...\n");
char *val = getenv("PATH");
printf("%s\n", val);
return 0;
}
就算是root用戶也不能執(zhí)行!文章來源:http://www.zghlxwxcb.cn/news/detail-449838.html
環(huán)境變量是誰(shuí)給我的呢??目前談不清,但是我們可以觀察到!文章來源地址http://www.zghlxwxcb.cn/news/detail-449838.html
到了這里,關(guān)于【Linux】進(jìn)程優(yōu)先級(jí) + 環(huán)境變量的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!