前言
心裏一直懷揣着做個自己的操作系統的想法。
操作系統概念
一個操作系統,上能接用戶與應用,下能接裸機與虛擬。有下面三大方面的功能:
- 作爲系統資源管理者:文件管理、設備管理、存儲器管理、處理器管理
- 交互:命令接口、程序接口(系統調用)、GUI
- 虛擬/抽象層
關於系統調用,有設備驅動:設備的請求、釋放、啓動。
有文件管理:文件的讀、寫、創建、刪除。
有進程控制:進程的創建、撤銷、阻塞、喚醒。
有進程通信:進程間的消息傳遞、信號傳遞。
有內存管理:完成內存的分配、回收。
簡單點講,操作系統是個將CPU映射成進程、將磁盤映射成文件、將內存映射成地址空間的東西。
Shell
這是層殼,隔離用戶與操作系統。作爲交互的接口、界面等作用。
最早的操作系統——批處理系統、監控程序
- 單道批處理系統:操作系統本身也是程序,最早的操作系統就是一個監控其他程序運行的程序。
- 多道批處理系統:普通的單道程序處理只允許一個程序從頭到尾執行完畢後,纔開始另一個程序。而多道批處理運行多道程序交替執行。從而比起單道程序更大程度利用系統資源
中斷種類
多道程序併發執行本質:發送中斷需要操作系統介入,開展管理工作(用戶態轉爲內核態)
中斷分爲外中斷與內中斷。
外中斷就是IO信號等。
內中斷就是指令中斷、強迫中斷(軟件中斷或硬件故障)
內中斷或者是陷入(trap)、故障(fault)、終止(abort)。
陷入
陷入trap,或者叫陷阱。陷入指令是彙編指令,在用戶程序使用庫函數時,庫函數內部封裝了系統調用System calls
在彙編層面上,在執行系統調用進入內核態前,會執行一種陷入指令(trap指令,訪管指令),之後CPU控制權會交給操作系統。然後就會在內核態執行系統調用的特權指令了。
陷入指令是特殊的只能在用戶態下執行的指令,並且是特殊的不能再內核態(核心態)下執行的指令。
分時操作系統—— 多用戶交互
之前的操作系統不能交互,這就只能寫個程序,等執行完才能再操作。
於是分時操作系統CTSS出現了,這個系統會按固定的時間片的分配,循環給不同的用戶分配使用時間與系統資源。
用戶態與核心態
控制指令中,設計內存、設備、IO等系統資源的操作或是別的特殊操作的時候,這時候使用的就不是普通指令,使用特權指令。特權指令在覈心態(kernel mode)又叫管態下使用,普通指令在用戶態(User mode)又叫目態下使用。
區分用戶態與核心態靠PSW,程序狀態字。
內核
內核中執行核心態相關指令。
內核處理的事有
- 時鐘管理
- 中斷處理
- 原語(不可分割的原子操作,一直執行或者一直不執行):CPU切換、設備驅動
- 系統資源管理:進程管理、存儲器管理、設備管理
內核有微內核與大內核。
原語
原語不允許中斷,是不可分割的操作,所以叫原子操作。運行在kernel mode下。
進程
在沒有線程的情況下,進程是資源分配、調度的基本單位。一個進程控制一個程序,系統可以在不同的進程間切換。
進程有一個頭,叫執行上下文(execution context)或進程狀態(process state)或進程控制塊(process control block)
下面兩塊中,一個是程序塊,存放代碼。一個是數據塊,存放程序運行的中間數據。
PCB信息
- 進程描述信息:進程標識符PID、用戶標識符UID
- 進程控制和管理信息:進程當前狀態、進程優先級
- 資源分配清單:程序段指針、數據段指針、鍵盤、鼠標
- 處理相關信息:各種寄存器值
進程組織方式
進程可以通過鏈接或者索引組織到一起。
- 鏈接指的是按進程狀態將PCB分爲多個隊列,OS擁有指向各個隊列的指針。
- 索引是建立幾張索引表。OS擁有各個索引表的指針。
- 這兩個組織方式中的指針都有三種,執行指針(掛一個運行狀態的PCB),就緒隊列指針(掛一條隊列鏈表,或者掛一張索引表),阻塞隊列指針(和就緒的很像)
進程狀態轉換——五狀態模型
進程狀態有
運行(Running,處理器√,其他資源√)
就緒(Ready,處理器×,其他資源√)
阻塞(Waiting,處理器×,其他資源×)
創建(New)
終止(Terminated)
- 創建是創建一個PCB,一個PCB就可以當做是一個進程。就緒就是準備了其他資源,然後PCB被放入一個就緒隊列。系統從隊列中依次執行一個PCB,執行完一次的要麼釋放掉,要麼放入阻塞隊列,等待進入下一個就緒。
進程控制
進程控制通過原語/原子操作。因爲這時候是不允許中斷的。
比如,首先關中斷,然後執行原語操作,此時是不允許打斷的,之後再開中斷。
在這個原語操作中間,就可以執行更新PCB信息:修改進程狀態標誌、將運行環境保存到PCB中、從PCB中恢復運行環境。
將PCB插入隊列和分配/回收資源。
進程通信
進程通信有三個方法,分別是共享存儲、消息傳遞、管道通信。
共享通信
共享通信又有兩種,基於數據結構和基於存儲區。都是一個道理,是通過共同的存儲位置來通信。兩個進程對共享空間的訪問必須互斥。
消息傳遞
消息傳遞分兩種,直接和間接。消息包由消息頭(發送進程ID,接收進程ID,消息類型)和消息體組成。
直接通信是把自己進程生成一個消息包,然後把這個消息包掛到另一個進程的消息隊列上。等待對方讀取。
間接通信是把消息包放到一個共享空間中,隨便放。然後另一個進程自己去找就行。
管道通信
管道通信是用於連接讀寫進程的共享文件,是固定大小的緩存區。管道通信和共享存儲不同的是,只允許單方向的通信。同樣,這個讀寫也是互斥的。
管道通信有下面三個約定:
- 一邊的進程寫滿了,另一邊的進程才能讀
- 一邊的進程讀完了,另一邊的進程才能寫
- 因爲讀了的內容會被清除,所以一個管道只能有一個進程讀
線程
一個進程可以擁有多個線程,線程可以理解爲輕量化進程。線程也有ID,也有線程控制塊TCB。
有了線程後,進程成爲了資源分配的基本單位,線程是調度的基本單位。傳統進程間併發,需要切換進程運行環境時,系統資源開銷大。引入線程後,同一進程內線程的切換,不需要切換運行環境,系統資源開銷小。
- 用戶級線程 User-level Thread
由應用程序通過線程庫實現。所有的線程管理工作都由應用程序負責。在用戶態下完成,無需操作系統干預。 - 內核級線程 Kernel-level Thread
內核級線程的管理由操作系統的內核完成,線程調度、切換等工作由內核負責,因此內核級線程的切換必然需要在內核態下才能完成。
- 多線程中,往往就是將內核級線程與用戶級線程混在一起用的。