linux進程,這塊太難了,太多命令,太多新概念.作為初學者戰戰兢兢.同時也在匍匐前進. ...
進程概念介紹
每次寫筆記的時候總有一種想法,擔心這個觀點是錯誤的.擔心我學到的內容是問題了,從而給看筆記的同學們傳遞一種錯誤的知識.希望看筆記的同學帶疑惑的去看去思考,我寫的是不是有問題,發現錯誤了希望您也能反饋給我.我也從中學到得到.
什麼是進程
瞭解進程之前,需要先瞭解一下什麼是程式,程式就是一個存放在磁碟的有序指令集合,是靜態的;而進程可以簡單理解成磁碟中程式的一個副本,只不過這個副本時動態的,運行台記憶體空間中.而且一個進程不單單隻運行你指定的運行程式的代碼或部分代碼,還包括了程式運行時需要的各種庫文件和數據信息.
同時還要一個概念那就是線程,線程是電腦CPU調度的最小單位,一個進程中可能包含一個線程,也可能包含多個線程.線程就好比公司的員工,而進程就相當於一個公司,一個小公司可能老闆和員工是同一個人,同樣的小進程中就只有一個線程,有的公司還有很多員工,同樣進程也可能有很多線程同時工作.
進程的組成結構
進程是在進程隊列task list中調度進程的,進程隊列又是由一個一個的進程結構體task_sturck組成的雙向迴圈結構.可以說一個進程結構體就管理著一個進程,所以這種進程結構體又稱為進程式控制制塊
一個進程結構體中包含:
進程的ID 用戶ID 和組ID
程式計數器
進程的狀態:就緒態 執行態 睡眠態 阻塞態
進程切換時需要保存和恢復的CPU寄存器中的值
描述虛擬記憶體分配的地址信息
描述控制終端的信息
當前工作目錄
文件描述符表,包含很多指向file結構體的指針
進程可以使用的資源上線
輸入輸出狀態:配置進程使用IO設備
進程眼裡的天地:虛擬記憶體空間
進程是運行在虛擬記憶體空間的,在進程眼裡虛擬記憶體就只有自己和內核.自己完全享有內核和CPU等硬體資源.
如下圖是以32為系統為例,進程以為自己完全享有0-3G的虛擬記憶體,3G-4G記憶體是內核占有的.進程可供自己完全支配的這部分空間稱為用戶空間,內核占有的那部分空間稱為內核空間.
用戶空間劃分為五個段:
代碼段:Text Segment,這裡存放了進程執行時需要用到的代碼.所以這部分是只讀的.
數據段:Data Segment,這裡用來存放已經初始化且值不為0的全部變數和靜態局部變數
BSS段::Block Started by Symbol,存放了未初始化或者已經初始化但是值為0的全局變數和靜態局部變數
堆:heap,用於存放數組和對象,堆是用來存放進程運行中被動態分配的記憶體段,它的大小不固定,可動態擴展或酸鹼,單進程調用malloc等函數分配記憶體時,新分配的記憶體就被動態添加進堆中,當利用free函數釋放記憶體時,就是從堆中剔除該記憶體.同時因為在不斷的malloc 和free這部分記憶體空間是不連接的,所以堆是用鏈表結構來儲存數據的.
棧:stack,棧是用來存放新創建的局部變數和函數參數,參數返回值.由於棧的後進先出特性,棧特別方便用來保存恢復調用現場,即某個進程運行中產生在CPU寄存器中的數據.
內核空間:
內核空間是屬於操作系統的一部分常駐記憶體,操作系統不允許普通用戶的應用程式讀寫這個區域的內容或者直接調用內核空間中定義的函數.
虛擬記憶體和物理記憶體的關係:
存放進程的虛擬記憶體最終會映射到物理記憶體當中.物理記憶體是怎麼分配的呢?
操作系統會把物理記憶體劃分成一個一個的頁框,頁框的大小一般是4k,可以使用
Getconf -a | grep -i size 來搜索查看page 的大小.
[root@CentOS7 411]# getconf -a | grep -i size PAGESIZE 4096 PAGE_SIZE 4096 SSIZE_MAX 32767
在進程看來虛擬記憶體是連續的,而物理記憶體分配的記憶體頁不一定是連續的,就會出現一種出現一種奇怪的映射關係,虛擬記憶體可能對應這多個不連續記憶體頁
可以使用pmap命令來查看某個程式的具體物理地址映射表.也可以通過查看/proc/目錄下對應PID目錄中的maps文件
[root@CentOS7 proc]# pmap 863 863: /usr/sbin/sshd -D 000055ceab69c000 800K r-x-- sshd 000055ceab963000 16K r---- sshd 000055ceab967000 4K rw--- sshd 000055ceab968000 36K rw--- [ anon ] 000055ceac9a4000 132K rw--- [ anon ] 00007f9732117000 48K r-x-- libnss_files-2.17.so 00007f9732123000 2044K ----- libnss_files-2.17.so
[root@CentOS7 proc]# cat /proc/863/maps 55ceab69c000-55ceab764000 r-xp 00000000 08:03 464614 /usr/sbin/sshd 55ceab963000-55ceab967000 r--p 000c7000 08:03 464614 /usr/sbin/sshd 55ceab967000-55ceab968000 rw-p 000cb000 08:03 464614 /usr/sbin/sshd 55ceab968000-55ceab971000 rw-p 00000000 00:00 0 55ceac9a4000-55ceac9c5000 rw-p 00000000 00:00 0 [heap] 7f9732117000-7f9732123000 r-xp 00000000 08:03 46532 /usr/lib64/libnss_files-2.17.so 7f9732123000-7f9732322000 ---p 0000c000 08:03 46532 /usr/lib64/libnss_files-2.17.so 7f9732322000-7f9732323000 r--p 0000b000 08:03 46532 /usr/lib64/libnss_files-2.17.so 7f9732323000-7f9732324000 rw-p 0000c000 08:03 46532 /usr/lib64/libnss_files-2.17.so
虛擬記憶體是通過CPU中的MMU(Memory Mnagement Unit)完成虛擬記憶體地址和物理記憶體地址之間的轉換.程式在訪問虛擬記憶體地址時,這個虛擬記憶體地址就會先發送給MMU,MMU計算出來實際的物理地址,然後再通過匯流排去訪問實際的物理地址.
進程狀態
進程的基本狀態:
創建態:進程在創建時需要申請一個空白的進程式控制制塊PCB,向其中填寫空間和管理進程的信息,完成資源分配.如果創建工作無法完成.例如資源不足無法分配,卡這一步的狀態就是創建態.
就緒態:進程已經準備好,就差等待CPU分配時間片的狀態
在進程創建完成且已經分配好所需資源後,就會等待分配CPU的時間片的狀態,
在上一個時間片內沒有完成就被保存現場以後等待再次被CPU調用的的狀態,
進程在運行時產生長時間的IO操作後經過等待完成IO操作等待被分配時間片時的狀態
執行態:程式正在執行的狀態.擁有CPU的使用權
阻塞態:正在執行的進程由於某些原因產生IO請求而暫時無法運行時,進程就收到阻塞的狀態.這中狀態在滿足請求後就會進入就緒態.
終止態:進程結束或出現錯誤,或者被系統終止的狀態
進程切換路徑6種:
創建 to 就緒
就緒 to 執行
執行 to 就緒
執行 to 阻塞
阻塞 to 就緒
執行 to 結束
進程更多的狀態介紹:
運行態:running
就緒態:reading
睡眠態:分為可中斷睡眠(interruptable)和不可中斷睡眠(uninterruptable)
停止態:stiopped,暫停於記憶體,但不會被再次被調度運行,只能手工啟動
僵屍態:zombie,結束了子進程,但是父進程沒有收屍,此時子進程的狀態就是僵屍態
進程間通訊IPC
Inter process communication
同一主機:
管道
套接字
共用記憶體
信號
文件映射,將一個文件中的一段數據映射到物理記憶體中.
鎖
信號量
不同主機:
SOCKET
RPC,remote procedure call
MQ 消息隊列
進程的優先順序
系統優先順序:
LIUNX內核將系統優先順序劃分兩部分:實時優先順序和非實時優先順序
實時優先順序,0~99
非實時優先順序,100~139
實時優先順序是給內核使用的,
非實時優先順序是給普通進程使用的
優先順序中數字越小數字優先順序越高
NICE優先順序:
NICE優先順序知識給普通進程使用的
範圍是-20~19
NICE的-20對應的系統優先順序是100
NICE的0對應的系統高優先順序是120
NICE的19對應的系統優先順序是139
TOP命令中優先順序
範圍是0~39
TOP中的0對應系統的優先順序是100
TOP中的39對應的系統優先順序是139
普通用戶只能調大優先順序的數字,意思就是普通用戶不能提高進程的優先順序
只有管理員才可以提高進程的優先順序.
提到優先順序就不得不提下時間複雜度了,這裡引用的上頭條作者的文章,我把鏈接放下來:https://www.toutiao.com/a6643648147614597639/,相信感謝作者
時間複雜度O(1)理解:
O(1)表示,隨著計算量的增加他的時間複雜度恆定為固定值.
在linux當中一共有兩組隊列,一組是運行隊列,一組是就緒隊列.每一組隊列當中又由140個子隊列,每個子隊列就代表著一個優先順序,表示0~139個優先順序.根據進程的優先順序就會分佈在這140個子隊列中.
系統會首先判斷140個隊列的優先順序,把0號隊列的優先順序上的進程從前到後先取出一個開始運行,當運行完這個進程後,就會把該進程放進就緒隊列當中,然後再從運行隊列中去下一個進程,運行完在放入到就緒隊列.當0號運行隊列中已經沒有了就緒態的進程就會把,就緒隊列變成運行隊列.而空的原運行隊列就變成就緒隊列.如此往複,實現了系統檢索優先順序的時候只是在這280個對聯中查找.所以時間複雜度是恆定的.
時間複雜度O(n)理解:
這裡用使用contains()方法使用查找List集合裡面的某個元素來舉例。List是有序表,不能直接一次性查找到。比如從{12,23,45,··· ···,76,32}裡面查找76,要從12開始查找,一次次迴圈查找,直到查到76並返回。這裡每次的查找時間複雜度為O(1),需要查找N次才能查到76,則時間複雜度可以看作是N * O(1)=O(n)。註意,這裡的n不是具體的數值N,不要以為查詢了100次就是O(100),這是錯的,這裡只是為了方便理解(前面說了,時間複雜度並不是單指耗時,下同)。
時間複雜度O(logn)理解:
一般的查找都是O(n),但是如果通過演算法,可以使查找的時間複雜度降低,比如二分查找。像上面解釋O(n)的例子中,採用二分查找的話,是不是就是個log(O(n))的對數數學模型,所以其時間複雜度為O(logn)。
時間複雜度O(n^2)理解:
這裡拿冒泡排序對某個數組進行有序排序舉例。在冒泡排序中,分為獲取值、對該值進行排序、重覆取值排序三個步驟。其中取值時間複雜度為O(1),則在N個數中進行該值的比較排序,則為N*O(1)=O(n)時間複雜度。這時候還沒有獲取到有序數組,必須對這N個數重覆進行取值、排序,執行N次,故時間複雜度為N * N * O(1)=O(n^2)。
放在最後還是那句話,作為一個初學的筆者,同學們在看筆記的時候一定要本著一個懷疑的態度來看,來思考寫的對不對,只有自己確認過的才是可以相信.筆記有誤支出,請見諒.