03.进程和线程.md
文章目錄
- 3. 進程是什么
- 3.1 進程包含的東西
- 3.2 進程狀態
- 3.2.1 操作系統常見狀態定義
- 3.2.1 linux系統狀態定義
- 3.3 進程的控制
- 3.3.1. 執行模式
- 3.3.2. 進程的創建
- 3.3.3. 進程的切換時機
- 3.3.3.4 進程的模式切換
- 3.3.3.5 進程切換
- 3.4 操作系統的執行
- 3.4.1 無進程內核
- 3.4.2 在用戶進程內運行
- 3.4.3 基于進程的操作系統
- 4. 線程
- 4.1 什么是線程
- 4.2 用戶級和內核級線程
- 4.3 線程和進程的區別
- 5. 處理器調度
- 5.1 調度分類
- 5.2 短程調度發生的原因
- 5.3 單處理器調度和多處理器調度
3. 進程是什么
3.1 進程包含的東西
進程的直觀定義很多
從操作系統管理的角度來說,我們可以把進程視為一組元素組成的實體。
進程的兩個基本元素是程序代碼和與代碼相關的數據集。在進程進行的任何時候,可以用下面的一些元素來描述一個進程。
3.2 進程狀態
3.2.1 操作系統常見狀態定義
3.2.1 linux系統狀態定義
這里主要看看linux進程的狀態,這一段參考了這里
執行態,可中斷阻塞態,不可中斷阻塞態,停止,僵死態
通過ps -aux命令我們會看到,一般情況下,進程列表中的絕大多數進程都處于TASK_INTERRUPTIBLE狀態(除非機器的負載很高)。畢竟CPU就這么一兩個,進程動輒幾十上百個,如果不是絕大多數進程都在睡眠,CPU又怎么響應得過來。
而TASK_UNINTERRUPTIBLE狀態存在的意義就在于,內核的某些處理流程是不能被打斷的。如果響應異步信號,程序的執行流程中就會被插入一段用于處理異步信號的流程(這個插入的流程可能只存在于內核態,也可能延伸到用戶態),于是原有的流程就被中斷了。
在進程對某些硬件進行操作時(比如進程調用read系統調用對某個設備文件進行讀操作,而read系統調用最終執行到對應設備驅動的代碼,并與對應的物理設備進行交互),可能需要使用TASK_UNINTERRUPTIBLE狀態對進程進行保護,以避免進程與設備交互的過程被打斷,造成設備陷入不可控的狀態。這種情況下的TASK_UNINTERRUPTIBLE狀態總是非常短暫的,通過ps命令基本上不可能捕捉到
在這個退出過程中,進程占有的所有資源將被回收,除了task_struct結構(以及少數資源)以外。于是進程就只剩下task_struct這么個空殼,故稱為僵尸。之所以保留task_struct,是因為task_struct里面保存了進程的退出碼、以及一些統計信息。而其父進程很可能會關心這些信息。比如在shell中,$?變量就保存了最后一個退出的前臺進程的退出碼,而這個退出碼往往被作為if語句的判斷條件。當然,內核也可以將這些信息保存在別的地方,而將task_struct結構釋放掉,以節省一些空間。但是使用task_struct結構更為方便,因為在內核中已經建立了從pid到task_struct查找關系,還有進程間的父子關系。釋放掉task_struct,則需要建立一些新的數據結構,以便讓父進程找到它的子進程的退出信息。
父進程可以通過wait系列的系統調用(如wait4、waitid)來等待某個或某些子進程的退出,并獲取它的退出信息。然后wait系列的系統調用會順便將子進程的尸體(task_struct)也釋放掉。子進程在退出的過程中,內核會給其父進程發送一個信號,通知父進程來“收尸”。
3.3 進程的控制
3.3.1. 執行模式
執行模式分為 用戶模式和系統模式(也稱為內核模式,控制模式等)。
處理器如何才能知道他正在什么模式下運行,模式如何變化。
程序狀態字中通常會有一個指示模式的位。該位會因事件的改變而改變,當發生系統調用或者中斷的時候,執行模式會被設置為內核模式。在這些程序執行完成后,會自動將該狀態字復位。
3.3.2. 進程的創建
3.3.3. 進程的切換時機
3.3.3.4 進程的模式切換
是指進程因系統調用等從用戶模式進入內核模式,他沒有進行進程的切換,只是需要保存處理器狀態信息的控制部分,包括程序計數器,其他處理器寄存器和棧信息。
3.3.3.5 進程切換
3.4 操作系統的執行
操作系統的執行方式也有多種,常見的有三種
3.4.1 無進程內核
在許多老的操作系統中采用了這種方式,若當前用戶進程發生系統調用或者產生一個中斷,則會保存該進程的模式上下文,控制權轉交給內核。操作系統具有本身控制過程的調用和返回的系統區域與系統棧。操作系統可以完成任何預期的功能并恢復被中斷的進程的上下文,恢復中斷進程的執行或者執行下一個進程。
無論上面什么功能實現,關鍵是這一概念只使用與用戶程序,而操作系統則是在特權模式下單獨運行的實體。
3.4.2 在用戶進程內運行
這個是目前常用的方式,在用戶進程的上下文執行操作系統軟件,在中斷,系統調用發生的時候,處理器cpu處于內核模式,但是不會保存當前進程的上下文,在后面恢復的時候如果還是調度給當前進程的話,那么久不需要進行上下文切換,只需要修改運行模式即可。
3.4.3 基于進程的操作系統
操作系統作為一個獨立的進程執行。
4. 線程
4.1 什么是線程
進程具有如下兩個個特點
??這兩個特點是獨立的,因此操作系統應該能夠分別處理他們。現代操作系統為了區分這一點,將cpu調度的基本單位成為線程(或者叫輕量級進程),而將資源所有權的單位成為進程或者任務。
4.2 用戶級和內核級線程
用戶線程和內核線程的對應關系分成三種。
4.3 線程和進程的區別
5. 處理器調度
處理器的調度涉及到很多調度算法之類的知識,對于這些東西,我覺得對于工程上實際意義不是很大,在這里只是聊一聊工作中遇到的一些與調度有關聯的優化問題。
5.1 調度分類
5.2 短程調度發生的原因
- 時鐘中斷
- I/O中斷
- 操作系統調用
- 信號(如信號量)
5.3 單處理器調度和多處理器調度
cpu綁定:
在處理器進行調度的時候,實際上是有兩種調度的,為了簡化這種討論,我們先假設
在線程從A1–>A2的時候只發生了線程調度,沒有進程調度,切換上下文的時間較短
如果線程從A1–>B2這個時候發生的則是進程的切換(包含了線程的切換),相對來說代價更大。
在多核處理器當中,調度的基本模型是線程,所以會比這個更復雜。其基本原則肯定是希望將cpu的利用率更高,同時用在切換線程上的代價盡可能的小。
??所以一個進程的多個線程有可能是在不同的處理器上同時運行的,這樣提高了并行的效率。但是對于某些單線程的進程,如果處于阻塞的時機比較少(大多是非阻塞式操作),而且對性能要求比較高的,是可以采取綁定cpu的方式的。比如redis的常規優化中就有將redis進程綁定到某個cpu核上,當然,并不會完全搶占該cpu核(完全搶占是指該cpu只能執行該進程),但是操作系統的調用會傾向于這么做,也就是進可能的讓該cpu核多的執行該進程,那么這樣的話,redis的效率反而是得到了提升的。可以參看這里
補一張AMD推土機結構,這也是多核cpu的緩存常見處理方案
總結
以上是生活随笔為你收集整理的03.进程和线程.md的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 02.操作系统概述.md
- 下一篇: 04.并发和互斥.md