Linux進程優先級和環境變量詳解

2023-03-28 11:18:41 來源:入門小站

一、進程優先級

1、基本概念


(資料圖片)

cpu資源分配的先后順序,就是指進程的優先權(priority) .優先權高的進程有優先執行權利。配置進程優先權對多任務環境的 Linux很有用,可以改善系統性能。 還可以把進程運行到指定的 CPU 上,這樣一來,把不重要的進程安排到某個 CPU,可以大大改善系統整體性能。

2、查看以及修改系統進程的優先級

在 Linux 或者 unix 系統中,用ps –al命令則會類似輸出以下幾個內容, 其中:

UID : 代表執行者的身份

PID : 代表這個進程的代號

PPID :代表這個進程是由哪個進程發展衍生而來的,亦即父進程的代號

PRI :代表這個進程可被執行的優先級,其值越小越早被執行

NI :代表這個進程的 nice 值,其表示進程可被執行的優先級的修正數值。

我們看到我們現在有兩個進程 bash ps 它們的進程優先級都是 80,如果我們要修改它們的優先級就要用到 NI 的 nice 值了。

PRI(new)=PRI(old)+nicePRI(new)=PRI(old)+nicePRI(new)=PRI(old)+nice

從這個公式中我們知道 新的 PRI = 老的 PRI + nice 值,但是這個老的 PRI 的值是指 PRI 最初的默認值,例如上面的bash ps 是 80,那么這個 PRI 以后不論怎么改老的 PRI 都是 80,當然大多數進程默認的 PRI 都是 80。

此外 nice 是有范圍的!其取值范圍是 - 20 至 19,一共 40 個級別。于是下面我們去嘗試去更改processC進程的優先級。注意:將進程優先級調高(即將 nice 值設置為負數)需要 root 用戶進行操作!

修改進程優先級的 Linux 指令

top命令

進入top后按 "r" -> 輸入進程 PID -> 輸入 nice 值

按下 “r”

輸入 -20

再次[查看進程]的相關信息:

我們發現進程的優先級確實改變了,但是我們能改變進程優先級有限[ ? 20 , 19 ] [-20,19][?20,19],因為調度器不允許我們將一個進程設置的優先級太高,進而導致其他進程難以被調度。

3、一些其他的關于進程優先級的指令和函數調用

nice指令,nice 命令的功能是用于調整進程的優先級,合理分配系統資源。-n 參數是 nice 值的優先級別,

以 nice 值為 -5 的方式執行指定程序

查看進程優先級

renice命令可以修改正在運行的進程的調度優先級。

renice更改一個或多個進程的調度優先級。第一個參數是要使用的優先級值,另一個參數被表示為進程標識信息。

renice[-n]priority[-gpu]identifier

-g, 后面加組的 pgid, 改變一個組的進程優先級-u, 后面加 user name 或 uid,改變一個用戶所擁有的進程優先級。-p, 后面加 pid ,改變一個進程的進程優先級。

使用renice命令

函數調用

在 Linux 中關于改變進程優先級函數調用主要有兩個:getpriority() 與setpriority()。

4、與進程優先級有關的一些進程性質

競爭性: 系統進程數目眾多,而 CPU 資源只有少量,甚至 1 個,所以進程之間是具有競爭屬性的。為了高效完成任務,更合理競爭相關資源,便具有了優先級

獨立性: 多進程運行,需要獨享各種資源,多進程運行期間互不干擾。

并行: 多個進程在多個 CPU 下,分別同時進行運行,這稱之為并行

并發: 多個進程在一個 CPU 下采用進程切換的方式,在一段時間之內,讓多個進程都得以推進,稱之為并發

二、環境變量

1、基本概念

環境變量 (environment variables) 一般是指在操作系統中用來指定操作系統運行環境的一些參數,環境變量通常具有某些特殊用途,在系統當中通常具有全局特性。

如:我們在編寫 C/C++代碼的時候,在鏈接的時候,從來不知道我們的所鏈接的動態[靜態庫]在哪里,但是照樣可以鏈接成功,生成可執行程序,原因就是有相關環境變量幫助編譯器進行查找。

2、和環境變量相關的命令

1.env: 顯示所有環境變量

2.echo: 顯示的變量值 (需要帶上 $ 符號)

3.export: 設置一個新的環境變量,或者將本地[變量提升]成環境變量。

4.unset: 清除環境變量

5.set: 顯示本地定義的 shell 變量和環境變量

3、Linux 中的常見環境變量介紹

PATH: 指定命令的搜索路徑

例如我們使用的 Linux 中 ls pwd命令,其實就是一個個 C 語言寫的一個個小程序,為什么我們運行自己寫的程序就要用./ + 自己的程序名 ,而我們運行ls pwd 從來不加./,這就和環境變量 PATH 有關了!我們查看環境變量可以使用echo $環境變量命令:

默認情況下我們使用的 Linux 指令會去 PATH 路徑下尋找源程序,由于ls指令的路徑位置就在 PATH 的環境變量中所以我們可以不用加./我們現在嘗試將我們的路徑添加到 PATH 環境變量里面,來讓我們的程序也不需要加./,這時我們就需要使用一個新的指令了:exportexport令可以將本地變量提升成環境變量,于是我們將我們的路徑添加到 PATH 中就可以這樣寫:

exportPATH=$PATH:你要添加的路徑

當然我們使用export命令是暫時將本地變量提升為環境變量,當我們退出云服務器或關機重啟都會消除export暫時提升的環境變量,想要真正的修改我們要修改相應的配置文件。

當然我們還可以將我們寫的程序拷貝到 Linux 的 PATH 默認路徑下,這樣我們也不用使用./了,在 Linux 中,把可執行程序,拷貝到系統默認路徑下,讓我們可以直接訪問的方式,相當于 Linux 下軟件的安裝!

HOME : 指定用戶的主工作目錄 (即用戶登陸到 Linux 系統中時, 默認的目錄)

由于 HOME 環境變量的存在,我們使用相同的命令cd ~卻得到了不同的結果。

SHELL : 當前 Shell, 它的值通常是 / bin/bash。

4、環境變量的組織方式以及在 C 代碼中如何獲取環境變量

在 Shell 內部,環境變量其實是以環境變量表的方式進行維護的!

此外環境變量還具有全局性,我們知道我們在 bash 下運行的程序其父進程都是 bash, 那么 bash 就可以將自己的環境變量傳遞給子進程,并在子進程中發揮作用!

我們來看一段代碼來驗證環境變量具有全局性。

1. C 庫函數getenv()獲得單個環境變量在看驗證代碼之前我們先了解一個函數getenv() getenv()是一個 C 庫函數, 它可以獲取一個環境變量的內容函數原型:

函數的參數是環境變量的名稱,返回值是一個char*字符串記錄了環境變量里面的內容, 如果調用失敗會返回 NULL 指針。

實例代碼

#include#includeintmain(){char*env=getenv("USER");//USER是環境變量if(env==NULL){perror("getenvfail:");}printf("%s",env);return0;}

代碼輸出結果

我們在代碼里面多出來的USER變量就是來自 Shell 傳遞給我們的test1c進程的環境變量!

2. main()函數參數獲得環境變量

此外我們我們還可以用main函數的參數來獲得所有環境變量的地址,通過地址我們也能遍歷所有環境變量

函數原型

intmain(intargc,char*argv[],char*envp[]);

在這里我們先不談論函數的參數 argc *argv[], 我們來談論第三個參數!其中*envp[]是一個字符數組指針,指向的是一個指針數組,數組名代表首元素的地址,首元素是一個字符指針,*envp[]剛好又是指向首元素的指針,故其實*envp[]其實是一個二級指針!

明白了這些,我們來看下面一段代碼:

#includeintmain(intargc,int*argv[],int*envp[]){for(inti=0;envp[i]!=NULL;++i){//打印所有環境變量,相當于 env 命令!printf("envp[%d]-->%s",i,envp[i]);}return0;}

可以看到我們確實打印出了所有的環境變量,而且這個環境變量來自于其父進程 bash。

3. C 語言全局變量environ獲得環境變量

變量詳情:

environ變量是一個二級指針與main()函數參數的char *envp[]類似。遍歷所有環境變量也可以這樣寫:

#include#includeintmain(){externchar**environ;for(inti=0;environ[i]!=NULL;++i){printf("environ[%d]-->%s",i,environ[i]);}return0;}

5、不同用戶的環境變量是怎么形成的

通過上面的講解我們知道了環境變量的概念與作用,環境變量中的每一個,都有自己的用途: 有的是進行路徑查找的,有的時進行身份認證的,有的時進行動態庫查找的,有的是用來進行確認當前路徑等等每一個環境變量都有自己的特定應用場景。

我們也知道為什么,對于不同的用戶其環境變量也并不相同,例如我們上面的 root 用戶的環境變量與 pan 的環境變量有的一樣有的不一樣,那么 Linux 是怎樣形成不同的環境變量的呢?

這里先給出結論:環境變量本質就是一個內存級的一張表,這張表由用戶在登陸會統的時候,給特定用戶形成屬于自己的環境變量表

在我們的家目錄下有兩個文件叫 .bashrc .bash_profile 在根目錄下有一個bashrc的文件

打開這些文件看看!

6、main() 函數的命令行參數

在前面我們談論中我們說到過main()函數的參數問題,我們還有兩個參數沒有談論int argc char *argv[]。現在我們來討論它們!

由于 C 語言中無法傳遞整個數組,所以在函數中想要獲得數組元素的個數必須在傳參時就要提前傳遞好,于是其中int argc 就是char *argv[]數組指針指向的數組的有效元素個數,不包含 NULL

這個char *argv[]是一個數組指針,其指向的數組里面存放的都是char *的指針,這些char *的指針指向的內容需要我們使用命令行的方式進行設置。

我們先看下面一段代碼:

#includeintmain(intargc,int*argv[]){printf("argc=%d",argc);for(inti=0;argv[i]!=NULL;++i){printf("argv[%d]-->%s",i,argv[i]);}return0;}

運行結果:

我們 Linux 中ls命令有許多參數如-a -l -d -n,ls本質上就是 C 語言寫的一個程序,它為什么能根據不同的參數執行不同的功能就是因為使用了 mian() 函數的命令行參數!

審核編輯:湯梓紅

標簽:

上一篇:
下一篇: