Java程序员需要掌握的计算机底层知识(二):操作系统、内核、用户态与内核态、系统调用的执行过程
操作系統
啟動過程
通電 -> bios uefi 工作 -> 自檢 -> 到硬盤固定位置加載bootloader -> 讀取可配置信息 -> CMOS
CMOS 用來存儲可以配置的信息,需要通電才能存儲信息,主板上有塊電池給它通電。
鴻蒙
操作系統:一遍管理硬件,一般對外暴露接口,管理應用。
內核管理硬件。應用程序屬于外圍程序。
如未特殊說明,后面我們提到的都是Linux操作系統。
推薦一本書《Linux內核設計與實現》,是介于源碼分析和應用中間的一本書,比較淺顯、平實的語言勾勒出Linux內核的原理。
Kernel 內核
1、微內核 - 彈性部署 5G IoT
2、宏內核 - PC phone
3、外核 - 科研 實驗中 為應用定制操作系統 (多租戶 request-based GC JVM)
宏內核
相關的程序都放在一塊內存里
微內核
萬物互聯:不同的占用的資源是不一樣的,有的內存大,有的內存小…
鴻蒙是面向萬物互聯的操作系統,智能家居這樣的小設備都不支持原始宏內核那樣超級大的內核存在,所以使用可插拔式的微內核設計。(類似于微服務的概念)。只要有一個控制器對所有的智能家居進行控制。
部署起來特別靈活,所以叫彈性部署。
外核
針對應用定制自己的操作系統。是一個僅存在于實驗室的概念,沒有應用。
類似于,如果你給JVM寫了一個專門針對WebServer的垃圾回收器,一個Request分配一個獨立內存,Request接收之后直接將這塊內存刪掉(阿里正在做的多租戶的GC的JVM)
VMM
由于硬件資源發展迅速,在硬件資源過剩的情況下,做出一個虛擬層(VMM:Virtual machine monitor,虛擬資源監控器),在虛擬層上面虛擬出幾個操作系統,共享同一套硬件資源。
用戶態、內核態
Intel CPU 分為三級:0,1,2,3三個級別
Linux 只使用了0,3兩個級別。內核訪問Ring 0級,應用程序只能訪問Ring 3級。
linux內核跑在Ring 0級, 用戶程序跑在Ring 3。
用戶想要讀硬盤、寫硬盤、寫網卡等,對于系統的關鍵訪問,需要經過kernel的同意,切換到Ring 0級,保證系統健壯性。
內核執行的操作: 提供了200多個系統調用,例如 sendfile read write pthread fork等對外暴露的函數。
JVM :站在操作系統老大的角度,JVM就是個普通程序
內核空間:只有內核能訪問的空間。用戶是不可能將這塊內存干掉的。
用戶空間:用戶可以直接操作的空間。
用戶態的程序要和內核態的程序打交道,需要通過系統調用。
正是因為這樣的分層,使得現在的Linux,Windows非常健壯,不會輕易被程序搞崩。
系統調用的執行過程
系統調用 是用戶空間訪問內核的唯一手段,除 異常 和 陷入 外,它是內核的唯一合法入口。
系統調用表及源碼鏈接 https://filippo.io/linux-syscall-table/
- Linux 的系統調用,作為 C 庫的一部分提供
- 用戶空間進程 用 系統調用號 來指明執行哪個系統調用。
- 進行系統調用的步驟:
- 用戶空間應用程序把 系統調用號 放入 eax 寄存器中,外部參數 放在另外的 5 或 6 個寄存器中
- 應用程序通過 int $0x80 觸發 軟中斷(異常),系統切換到內核態,執行 128 號異常處理程序,即 system_call() 系統調用處理程序
- system_call() 運行,從 eax 寄存器中得到 系統調用號,檢查其有效性,然后 執行相應的系統調用
- 內核在執行系統調用的時候,處于 進程上下文。在進程上下文中,內核 可以休眠,并且 可以被搶占
- 系統調用返回 的時候,system_call() 負責 切換回用戶空間,并讓用戶進程繼續執行 int $0x80 的下一條指令
匯編示例:
# Simple program that exits and returns a status code back to the Linux kernel ./section .data # 以.為開頭的名稱不會被翻譯為機器指令,而是作為一種匯編提示告知匯編器 ,這個形式直接被稱為 “匯編指令” 或 ”偽操作“ ./section .text # .text 段位保存代碼, 是只讀和可執行的。后面的指令都是屬于 .text 段。 .globl _start # 告訴編譯器,_start 這個符號就像c程序中的main函數一樣,是整個程序的入口 _start : # 是一個符號,符號在匯編中表示一個地址,可以再指令中 ,匯編程序經過匯編器的處理后, 所有的符號都被替換成為它所代表的地址值。(通俗說,c語言中的函數變量名都屬于符號) # movl 是一條數據傳送指令,要求CPU內部產生一個long數字1并保存到eax寄存器中。 # 1表示在CPU內部產生 ,稱為立即數,立即數在前面要加個$ ,寄存器就加個% movl $1 ,%eax # eax 寄存器用來指定系統調用號 movl $4 ,%ebx # _ebx 的值是傳給 _exit 的參數,表示退出狀態。_exit 的系統調用號為1。 int $0x80 # int 指令中的立即數 0x80 是一個參數,可以用于執行系統調用總結
以上是生活随笔為你收集整理的Java程序员需要掌握的计算机底层知识(二):操作系统、内核、用户态与内核态、系统调用的执行过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java程序员需要掌握的计算机底层知识(
- 下一篇: 网络与IO知识扫盲(三):从系统调用的角