🏀🏀🏀來都來了,不妨點個關注!
🎧🎧🎧博客主頁:歡迎各位大佬!
文章目錄
- 1. 操作系統
- 1.1 什么是操作系統
- 1.2 操作系統主要的功能
- 2. 進程
- 2.1 什么是進程
- 2.2 通過PCB描述一個進程
- 2.3 進程的調度
- 2.4 PCB的管理
- 2.5 內存管理
- 2.6 進程間通信的方式
- 3.線程
- 3.1 什么是線程
- 3.2 有了進程為什么還要有線程
- 3.3 進程與線程的聯系和區別
1. 操作系統
1.1 什么是操作系統
操作系統本質上是運行在計算機上的軟件程序,對上,它負責給軟件運行提供穩定的環境,對下,它要管理好各種硬件設備。我們可以通過以下的圖文進行理解:
1.2 操作系統主要的功能
從資源管理的角度來看,操作系統主要有六大功能:
- 進程和線程的管理:進程的創建、撤銷、阻塞、喚醒,進程間的通信等。
- 存儲管理:內存的分配和管理、外存(磁盤等)的分配和管理等。
- 文件管理:文件的讀、寫、創建及刪除等。
- 設備管理:完成設備(輸入輸出設備和外部存儲設備等)的請求或釋放,以及設備啟動等功能。
- 網絡管理:操作系統負責管理計算機網絡的使用。網絡是計算機系統中連接不同計算機的方式,操作系統需要管理計算機網絡的配置、連接、通信和安全等,以提供高效可靠的網絡服務。
- 安全管理:用戶的身份認證、訪問控制、文件加密等,以防止非法用戶對系統資源的訪問和操作。
可以看到操作系統的上述功能中,進程和線程管理和我們今天要講的進程與線程關系密切。
那么為什么要進行進程的管理呢,那當然是因為進程太多了才需要管理嘛,就比如我們上學,學校也都有會一個學生管理系統,里面就記錄著我們每個學生的信息。下面我們分別從進程和線程兩個角度進行講解。
2. 進程
2.1 什么是進程
一個運行起來的程序就是進程,而我們電腦中的.exe文件就是一個可執行的文件(程序),當雙擊這個.exe文件,這個程序跑起來就形成了一個進程。關于這個我們可以通過任務管理器查看,如下圖:
我們從上面兩種圖都可以觀察到我們的計算機上運行著許許多多的進程,我們在最開始提到過,操作系統的一大功能就是進行進程的管理,那么它是如何對進程進行管理的呢?其實就分為兩步,下面我們就來介紹:
- 描述一個進程:使用結構體/類把一個進程有哪些信息描述出來
- 組織這些進程:使用一定的數據結構將這些結構體/對象組織在一起
2.2 通過PCB描述一個進程
在上面我們提到對進程管理分為了兩步,第一步就是描述該進程,而在操作系統中,用于描述系統進程狀態的數據結構通常被稱為進程控制塊(Process Control Block, PCB)。而PCB有很多的屬性,這里我們將介紹幾個核心的:
- pid: 進程的唯一身份標識(這個我們在Linux常用命令章節里提到過)
- 內存指針:表示當前進程使用的內存是哪一部分(進程要運行起來就需要消耗一些硬件資源,這其中就包括了內存)
- 文件描述符表:文件描述符表是一個數據結構,用于記錄當前進程打開了哪些文件。當進程需要操作文件時,它會在文件描述符表中分配一個表項,并構造一個結構體來描述該文件的相關信息。
- 進程狀態:描述當前進程所處的狀態
主要為兩個狀態:
就緒態:該進程已經準備好了,隨時可以在CPU上運行
阻塞態:該進程暫時無法在CPU上運行 - 進程的優先級:優先級用于決定操作系統調度進程的順序。優先級高的進程會獲得更多的CPU資源
- 進程的上下文:進程的上下文就是記錄當前進程執行到哪里的"存檔記錄",進程在離開CPU的時候就需要把進程執行的中間結果進行"存檔",等下一次回到CPU上的時候再恢復之前的"存檔"。從上一次的結果繼續往后面執行。(類似于我們玩游戲玩到一半不玩了進行存檔退出,下一次玩的時候再進行讀檔,回到之前玩的地方繼續往后面玩)
- 進程的記賬信息:統計了每個進程在CPU上執行了多久了,可以作為進程調度的參考依據
其中,第4、5、6,7點都是和進程的調度有關的,下面我們先來介紹一些什么是進程的調度
2.3 進程的調度
在計算機操作系統中,進程調度是指按照某種策略或算法,從就緒隊列中選擇一個進程,將處理機分配給該進程,使之執行的過程。
那為什么要有進程的調度呢
我們先來了解一下CPU,我們的一個個程序能夠運行起來,都是依靠著CPU的調度,我們可以打開任務管理器來看看CPU的相關屬性,如下圖:
這個表示我自己計算機的CPU有8個 物理核心,而一個物理核心相當于兩個邏輯核心,這表示CPU同時能處理16個任務,此時就有人想問了但我們的計算機上同時運行的進程可不止16個,那CPU是如何處理的呢?這里我們介紹兩個核心概念
- 并行:兩個核心同時執行兩個任務(進程),此時這兩個任務就是并行執行的。
- 并發: 一個核心先運行進程1運行一會后再運行進程2運行一會后再運行進程3,只有切換的夠快,這里的進程1、2,3看起來就像是同時執行的一樣。
這也就告訴我們,雖然我的CPU只能同時執行16個任務,但通過并行+并發,我們就可以同時處理多個任務了,通常我們也將這里的并行+并發統稱為并發。
2.4 PCB的管理
操作系統往往是使用雙向鏈表的方式將PCB組織起來,這樣進程相當于鏈表中的節點,方便管理時進行增刪改查的操作
- 創建一個進程,即創建一個鏈表的節點
- 銷毀一個進程,即把鏈表的節點刪除
- 遍歷進程列表,即遍歷鏈表
2.5 內存管理
操作系統對內存資源的分配,采用的是空間模式 —— 不同進程使用內存中的不同區域,互相之間不會干擾。
而操作系統給每一個進程分配的內存空間都是以“虛擬地址空間”的方式分配的。
這里肯定就會有人要問了,有直接的物理地址,為什么不直接給每一個進程直接分配物理地址。我們用下面進程直接訪問實際物理地址的圖片來介紹:
上圖就是每個進程都是直接訪問物理內存的地址,此時可能就會產生一個比較嚴重的問題,萬一進程1的代碼出現了bug(比如數組下標越界,野指針…),可能就會連帶著把進程2搞崩潰了。
下面我們就來看看操作系統是如何通過使用虛擬內存來解決這個問題的:
站在進程自身的角度看,它們的內存地址就是0x00aa-0x00ff,這里訪問的內存地址就會被操作系統自動映射到真正的物理地址上,但是進程自身是感知不到實際的物理地址是啥的。
此時如果進程1代碼出bug,就沒有什么影響,因為任何一個內存操作都需要通過頁表翻譯,比如出現野指針0x11aa,拿著這個地址,頁表無法映射也就不會修改真正物理內存,即不會對進程2的內存數據進行干擾。
- 頁表:操作系統使用頁表來維護虛擬地址到物理地址的映射關系。頁表是一種數據結構,它記錄了每個虛擬頁(通常是4KB大小)對應的物理頁號。
- 地址翻譯:當CPU執行指令并需要訪問某個內存地址時,它首先會檢查這個地址是虛擬地址還是物理地址。如果是虛擬地址,CPU會通過頁表將其轉換為物理地址,然后訪問物理內存。
- 缺頁異常:如果CPU在訪問某個虛擬頁時發現該頁沒有在物理內存中(即發生了缺頁),它會產生一個缺頁異常。操作系統會捕獲這個異常,并從磁盤或其他存儲介質中加載缺失的頁到物理內存中,然后更新頁表以反映這一變化。
2.6 進程間通信的方式
在上面我們說了操作系統給每個進程都分配了一塊獨立的虛擬地址空間,這保證了進程間的地址空間隔離。一個進程無法直接訪問另一個進程的內存,從而避免了內存沖突和數據損壞。
即各個進程互相之間是無法感受到對方存在的,是相互獨立的,這樣進程之間互相具備"隔離性",但有時候需要進程之間進行交互,相互配合。
此時就有了進程間的通信:即在隔離性前提下,找一個公共區域,讓進程借助這個區域完成數據交換。
目前,主流操作系統提供的進程通信機制有如下:
- 管道
- 共享內存
- 文件
- 網絡
- 信號量
- 信號
- 套接字(Sockets)
其中,網絡是一種相對特殊的 IPC 機制,它除了支持同主機兩個進程間通信,還支持同一網絡內部非同一主機上的進程間進行通信。
3.線程
3.1 什么是線程
線程(Thread) 也被稱為輕量級進程,更加輕量。多個線程可以在同一個進程中同時執行,并且共享進程的資源比如內存空間、文件句柄、網絡連接等。舉例:你打開的微信里就有一個線程專門用來拉取別人發你的最新的消息。
3.2 有了進程為什么還要有線程
- 進程切換是一個開銷很大的操作,線程切換的成本較低。
- 線程更輕量,一個進程可以創建多個線程。
- 多個線程可以并發處理不同的任務,更有效地利用了多處理器和多核計算機。而進程只能在一個時間干一件事,如果在執行過程中遇到阻塞問題比如 IO 阻塞就會掛起直到結果返回。
- 同一進程內的線程共享內存和文件,因此它們之間相互通信無須調用內核。
3.3 進程與線程的聯系和區別
聯系:一個進程中可以有多個線程,這些線程共享一份堆和方法區(jdk1.8之后稱為元數據區)資源,同時每個線程有自己的虛擬機棧、本地方法棧和程序計數器。這點我們在JVM篇里介紹過。
區別:
- 進程是操作系統資源分配的基本單位,線程是操作系統調度執行的基本單位(這也告訴我們上述我們介紹的進程的調度,其實是對進程里的線程的調度)
- 進程具有獨立性,一個進程不會影響另一個進程,但在同一進程的多個線程之間,一個線程掛了,可能會把整個線程帶走,影響其它線程。
- 進程開銷大,消耗資源多,線程執行開銷小,但不利于資源的管理和保護
本次的分享就結束了,感謝支持!