前言
在了解進程狀態之后,本章我們將來學習一下進程優先級,還有環境變量等。。
目錄
- 1.進程優先級
- 1.1 為什么要有優先級?
- 2.進程的其他概念
- 2.1 競爭性與獨立性
- 2.2 并行與并發
- 2.3 進程間優先級的體現:
- 2.3.1 O(1) 調度算法:
- 2.4 進程上下文:
- 3 .環境變量
- 3.1 環境變量的概念:
- 3.2 常用的環境變量:
- 3.3 環境變量指令:
- 3.4 linux修改環境變量的方法:
- 3.5 通過代碼如何獲取環境變量:
- 3.5. 1 **環境變量的組織方式**
- 3.5. 2 方法一:main函數的第三個參數
- 3.5. 3 方法二:通過C語言第三方變量environ獲取
- 3.5. 4 方法三:通過系統調用獲取或設置環境變量
- 3.6 環境變量通常是具有全局屬性的
1.進程優先級
1.1 為什么要有優先級?
因為CPU是有限的,進程太多,需要通過某種方式競爭資源!Linux系統中進程占大多數,而資源是少數! 所以,進程競爭資源是常態!一定需要確認先后順序
- cpu資源分配的先后順序,就是指進程的優先權(priority)。
- 優先權高的進程有優先執行權利。配置進程優先權對多任務環境的linux很有用,可以改善系統性能。
- 還可以把進程運行到指定的CPU上,這樣一來,把不重要的進程安排到某個CPU,可以大大改善系統整體性能
- 什么是優先級?
就是確認是誰應該先獲得某種資源,誰后獲得
在Linux系統中,一般一個服務,是專屬專機。優先級是操作系統是最清楚的(在創建進程task_struct時),你自己改的,并一定按照這個操作來的。(一般不需要調整的)
計算機為了保證每個進程能夠,盡可能平均的使用進程,所以nice的調整范圍只有40個。(-20~ 19)
- Linux優先級的構成
- priority(PRI) + nice
PRI(new)=PRI(old)+nice - 需要強調一點的是,進程的nice值不是進程的優先級,他們不是一個概念,但是進程nice值會影響到進 程的優先級變化。
- 可以理解nice值是進程優先級的修正修正數據
注意:
-
雖然我們可以對Linux進程的優先級進行修改
-
但是Linux不允許進程無節制的設置優先級
-
用top命令更改已存在進程的nice
輸入top
進入top后按“r”–>輸入進程PID–>輸入nice值
-
nice值的修改并不是無節制的,是有一定取值范圍的;nice [-20, 19] prio [60,99]
-
當我們設置完該進程的pri為60之后,再次對該進程的nice進行修改,此時pri會再次恢復到80!!
prio = prio_old + nice
2.進程的其他概念
2.1 競爭性與獨立性
競爭性: 系統進程數目眾多,而CPU資源只有少量,甚至1個,所以進程之間是具有競爭屬性的。為了高效完成任務,更合理競爭相關資源,便具有了優先級。
當一個進程在使用資源的時候,是不允許別的進程也來使用該資源的基本上所有的外設和CPU都是這樣子的。
獨立性: 多進程運行,需要獨享各種資源,多進程運行期間互不干擾,進程運行是有獨立性的。
進程運行具有獨立性,不會因為一個進程掛掉或者異常,而導致其他進程出現問題!
使用STL將對象放到各種容器中,就像在linux系統當中,將PCB放來是一個道理。
2.2 并行與并發
并行: 多個進程在多個CPU下分別,同時進行運行,這稱之為并行。
并發: 多個進程在一個CPU下采用進程切換的方式,在一段時間之內,讓多個進程都得以推進,稱之為并發。
- 不要以為進程一旦占有CPU,就會一直執行到結束,才會釋放CPU資源!
- 我們遇到的大部分操作系統都是分時的
- 在一個時間片內,多個進程都會通過切換交叉的方式,讓多個進程代碼,在一段時間內,都得到推進
- 例如一個進程,只能在CPU內執行10ns ,就要從CPU上扒下來,讓其他的進程來執行
- 這種現象,叫做并發
2.3 進程間優先級的體現:
操作系統,就是簡單的根據隊列來進行先后調度的嘛,有沒有可能突然來了一個優先級更高的進程。。
當代計算機都具有的一種機制:搶占式內核!
正在運行的低優先級進程,但如果來個優先級更高的進程,我們的調度器會直接把進程從CPU上剝離,放上優先級更高的進程,進程搶占。
進程搶占:
有可能進程正在跑,突然來了個優先級更高的進程,操作系統直接就把這個進程扒下來了,讓優先級更高的進程來跑。
2.3.1 O(1) 調度算法:
這里我們就簡單介紹一下:
- 允許不同優先級的進程存在
- 相同優先級的進程,是可能存在多個的!
而我們之前學習過數據結構,我們知道隊列是先進先出的,是不允許隨意插入的,那么優先級如何體現出來呢?
操作系統采用的是哈希的數據結構.
根據不同的優先級,將特定的進程放入不同的隊列中!
2.4 進程上下文:
CPU一定具有把數據暫時保存起來的能力。
CPU內的寄存器更多是用來保存一些臨時數據。
CPU內的寄存器是:可以臨時的存儲數據,非常少,但是非常重要。
int func()
{int a = 10 + 20;return a;
}int main()
{int ret = func();return 0;
}
我們把進程在運行中產生的各種寄存器數據,我們叫做進程的硬件上下文數據
- 當進程被剝離:需要保存上下文數據
- 當進程恢復的時候:需要將曾經保存的上下文數據恢復到寄存器中
上下文在哪里保存呢?—— task struct
task_struct- PCB的一種
在Linux中描述進程的結構體叫做task_struct。
task_struct是Linux內核的一種數據結構,它會被裝載到RAM(內存)里并且包含著進程的信息
3 .環境變量
3.1 環境變量的概念:
- 環境變量(environment variables)一般是指在操作系統中用來指定操作系統運行環境的一些參數。
- 如:我們在編寫C/C++代碼的時候,在鏈接的時候,從來不知道我們的所鏈接的動態靜態庫在哪里,但是照樣可以鏈接成功,生成可執行程序,原因就是有相關環境變量幫助編譯器進行查找。
- 環境變量通常具有某些特殊用途,還有 在系統當中通常具有全局特性。
3.2 常用的環境變量:
- PATH : 指定命令的搜索路徑
- HOME : 指定用戶的主工作目錄(即用戶登陸到Linux系統中時,默認的目錄)
- SHELL : 當前Shell,它的值通常是/bin/bash
3.3 環境變量指令:
顯示某個環境變量值:echo $path
echo $NAME //NAME:你的環境變量名稱
查看系統的所有環境變量:env
設置一個新的環境變量:export / (直接使用環境變量名)如 :Path
unset: 清除環境變量
Set: 顯示本地定義的shell變量和環境變量
Linux export :命令用于設置或顯示環境變量
解釋:
環境變量PATH里面有多種變量,中間用冒號:分割開,其中我們在執行某個程序時:例如在執行Is時, 當識別到有Is輸入時,
會在上面的路徑中一個一個的搜索,只要在特定路徑下找到了Is,就會執行特定路徑下的Is,執行完就停止搜索不再往后走了,換言之PATH就提供了可執行程序搜索的路徑。Is或者是很多指令在PATH里面是可以被找到的。
3.4 linux修改環境變量的方法:
-
方式1:
export PATH=$PAHT:/home/路徑
//臨時修改,只對當前終端生效,立即生效 終端一關閉,就失效了 -
方式2:
修改 家目錄下的 .bashrc 文件
這個文件每個用戶都有,都放在自己的家目錄下
用戶每次登錄時,都會加載(執行)這個文件
所以,將export XXX=$XXX:xxx 放到.bashrc這個文件中
就會對當前用戶一直生效了
修改.bashrc文件后 需要重新登錄(重新打開終端 才會生效)
或者 執行 source .bashrc 就可以立即生效了 -
方式3:
-修改系統時會加載的文件 如 /etc/environment 或者 /etc/profile
因為這些文件在系統啟動時候會被執行
所以在這些文件中修改環境變量,沒次啟動系統都生效
因為用戶修改環境變量時 都是以 PATH=$PATH:的方式追加的
所以每個用戶第一次修改時取的基本變量值都是他
所以修改這些文件,是對所有用戶有效的
重啟生效
或者執行 source /etc/profile source /etc/environment 生效
3.5 通過代碼如何獲取環境變量:
-
main函數可以帶參數嗎?可以帶多少?
我們先來看main函數帶兩個參數:
#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;
}
- char* argv[]是個指針數組,而int argc則是指針數組中元素的個數。
- 可執行程序和選項都是字符串,最后都以指針數組的方案存在了指針數組中。
- 指針數組中存的是字符串的起始地址
- 最后以NULL(’\0’)結尾
3.5. 1 環境變量的組織方式
每個程序都會收到一張環境表,環境表是一個字符指針數組,每個指針指向一個以’\0’結尾的環境字符串
3.5. 2 方法一:main函數的第三個參數
#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;
}
- char* env[]也是個指針數組
- 數組里的每個元素都是指向一個字符串,每個字符串就是一個環境變量
- 最后以NULL結尾
3.5. 3 方法二:通過C語言第三方變量environ獲取
int main()
{extern char** environ;for (int i = 0; environ[i]; i++){printf("%d: %s\n", i, environ[i]);}return 0;
}
libc中定義的全局變量environ指向環境變量表,environ沒有包含在任何頭文件中,所以在使用時 要用extern聲明。
3.5. 4 方法三:通過系統調用獲取或設置環境變量
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%s\n", getenv("PATH"));
return 0;
}
常用getenv和putenv函數來訪問特定的環境變量。
3.6 環境變量通常是具有全局屬性的
- 環境變量通常具有全局屬性,可以被子進程繼承下去。
- 如果只進行 MYENV=“helloworld” ,不調用export導出,在用我們的程序查看,會有什么結果?為什
么? 普通變量 不會被子進程繼承下去
#include <stdio.h>
#include <stdlib.h>
int main()
{
char * env = getenv("MYENV");
if(env){
printf("%s\n", env);
}
return 0;
}
直接查看,發現沒有結果,說明該環境變量根本不存在
導出環境變量 export MYENV=“hello world”
再次運行程序,發現結果有了!說明:環境變量是可以被子進程繼承下去的!想想為什么
尾聲
看到這里,相信大家對這個C++有了解了。
如果你感覺這篇博客對你有幫助,不要忘了一鍵三連哦