[TOC]
>操作系統筆記十篇:[https://blog.csdn.net/qq\_37205708/article/category/8618355](https://blog.csdn.net/qq_37205708/article/category/8618355)
# 操作系統的基本功能
1.進程管理
進程控制、進程同步、進程通信、死鎖處理、處理機調度等。
2.內存管理
內存分配、地址映射、內存保護與共享、虛擬內存等。
3.文件管理
文件存儲空間的管理、目錄管理、文件讀寫管理和保護等。
4.設備管理
完成用戶的 I/O 請求,方便用戶使用各種設備,并提高設備的利用率。
主要包括緩沖管理、設備分配、設備處理、虛擬設備等。
## 系統調用
如果一個進程在用戶態需要使用內核態的功能,就進行系統調用從而陷入內核,由操作系統代為完成。

Linux 的系統調用主要有以下這些:
| Task | Commands |
| :-: | --- |
| 進程控制 | fork(); exit(); wait(); |
| 進程通信 | pipe(); shmget(); mmap(); |
| 文件操作 | open(); read(); write(); |
| 設備操作 | ioctl(); read(); write(); |
| 信息維護 | getpid(); alarm(); sleep(); |
| 安全 | chmod(); umask(); chown(); |
注意特權指令(privileged instruction)和系統調用(system call)并不是一回事,比如如下一些操作屬于特權指令:
- 設置定時器
- 清空內存
- 關閉中斷
- 修改設備狀態表中的條目
- 接入 I/O 設備
可以把特權指令理解為會引起損害的機器指令,如果在用戶模式下試圖執行特權指令,那么硬件將不會執行該指令,而是認為該指令非法,并將其以 trap 的形式通知 OS。
*****
**系統調用**提供了進程與操作系統間的接口,其目的就是讓用戶級空間能夠請求系統級的服務。比如編寫一個從一個文件讀取數據并復制到另一個文件的簡單程序,對于交互系統,這過程需要一系列的系統調用:首先在屏幕上寫出提示信息,再從鍵盤上讀取定義兩個文件名稱的字符。這個過程就需要許多 I/O 系統調用。后續也還需要許多各方面的系統調用,從中即可看出,系統調用的作用就是讓用戶級的進程能夠請求操作系統的服務。
## 中斷的種類
一般來說,同步中斷又稱為異常(exception),異步中斷稱為中斷(interrupt)
異常又可分為故障(fault)、陷阱(trap)和終止(abort)三類。
| 類別 | 原因 | 異步/同步 | 返回行為 |
| --- | --- | --- | --- |
| 中斷 | 來自IO設備的信號 | 異步 | 總是返回到下一條指令 |
| 陷阱 | 有意的異常 | 同步 | 總是返回到下一條指令 |
| 故障 | 潛在可恢復的錯誤 | 同步 | 返回到當前的指令 |
| 終止 | 不可恢復的錯誤 | 同步 | 不會返回 |
[https://blog.csdn.net/u014134180/article/details/78418428](https://blog.csdn.net/u014134180/article/details/78418428)
# 進程與線程
## 進程
進程是資源分配的基本單位。
進程控制塊 (Process Control Block, PCB) 描述進程的基本信息和運行狀態,所謂的創建進程和撤銷進程,都是指對 PCB 的操作。
## 線程
線程是獨立調度的基本單位。
一個進程中可以有多個線程,它們共享進程資源。
QQ 和瀏覽器是兩個進程,瀏覽器進程里面有很多線程,例如 HTTP 請求線程、事件響應線程、渲染線程等等,線程的并發執行使得在瀏覽器中點擊一個新鏈接從而發起 HTTP 請求時,瀏覽器還可以響應用戶的其它事件。

## 區別
Ⅰ 擁有資源
進程是資源分配的基本單位,但是線程不擁有資源,線程可以訪問隸屬進程的資源。
更為具體地說,線程之間共享**堆**和**全局變量**,因為堆是在進程空間中開辟出來的,所以肯定是跨線程共享的;同理,全局變量是整個程序所共享的,也應由線程共享。而每個線程都會獨立地維護屬于自己的**寄存器**與**棧**。
Ⅱ 調度
線程是獨立調度的基本單位,在同一進程中,線程的切換不會引起進程切換,從一個進程中的線程切換到另一個進程中的線程時,會引起進程切換。
Ⅲ 系統開銷
由于創建或撤銷進程時,系統都要為之分配或回收資源,如內存空間、I/O 設備等,所付出的開銷遠大于創建或撤銷線程時的開銷。類似地,在進行進程切換時,涉及當前執行進程 CPU 環境的保存及新調度進程 CPU 環境的設置,而線程切換時只需保存和設置少量寄存器內容,開銷很小。
Ⅳ 通信方面
線程間可以通過直接讀寫同一進程中的數據進行通信,但是進程通信需要借助 IPC。
具體來說,進程間通信一般有以下兩種形式:1.共享內存 2.消息傳遞

- 共享內存模式:建立一塊供協作進程共享的內存區域,進程通過向此共享區域讀或寫入數據來交換信息。
- 消息傳遞模式:通過在協作進程間交換消息來實現通信。
# 程序在內存中的分布

<span style="font-family: 楷體;font-weight: 700;">代碼段 .text</span>
也稱文本段(Text Segment),存放著程序的機器碼和只讀數據,可執行指令就是從這里取得的。如果可能,系統會安排好相同程序的多個運行實體共享這些實例代碼。這個段在內存中一般被標記為只讀,任何對該區的寫操作都會導致段錯誤(Segmentation Fault)。
<span style="font-family: 楷體;font-weight: 700;">BSS段 .bss</span>
BSS 段通常是指用來存放程序中未初始化的全局變量和靜態變量的一塊內存區域。BSS 是英文 Block Started by Symbol 的簡稱。BSS 段屬于靜態內存分配。
<span style="font-family: 楷體;font-weight: 700;">數據段 .data</span>
數據段(data segment)通常是指用來存放程序中已初始化的全局變量和靜態變量的一塊內存區域。數據段屬于靜態內存分配。
<span style="font-family: 楷體;font-weight: 700;">堆 Heap</span>
用來存儲程序運行時分配的變量。堆的大小并不固定,可動態擴張或縮減。堆的內存的分配與釋放由應用程序控制,通常申請的內存都需要釋放,如果沒有釋放,在程序運行結束后操作系統會自動回收。
<span style="font-family: 楷體;font-weight: 700;">棧 Stack</span>
是一種用來存儲函數調用時的臨時信息的結構,如函數調用所傳遞的參數、函數的返回地址、函數的局部變量等。 在程序運行時由編譯器在需要的時候分配,在不需要的時候自動清除。
- 所謂 **動態存儲區域**:即 堆 ?棧??
- 所謂 **靜態存儲區域**:即 存儲靜態變量和全局變量以及代碼段的部分
# 死鎖
## 必要條件

* 互斥:每個資源要么已經分配給了一個進程,要么就是可用的。
* 占有和等待:已經得到了某個資源的進程可以再請求新的資源。
* 不可搶占:已經分配給一個進程的資源不能強制性地被搶占,它只能被占有它的進程顯式地釋放。
* 環路等待:有兩個或者兩個以上的進程組成一條環路,該環路中的每個進程都在等待下一個進程所占有的資源。
## 死鎖處理
主要有以下四種方法:
* 鴕鳥策略
* 死鎖檢測與死鎖恢復
* 死鎖預防
* 死鎖避免
**鴕鳥策略**
把頭埋在沙子里,假裝根本沒發生問題。
因為解決死鎖問題的代價很高,因此鴕鳥策略這種不采取任務措施的方案會獲得更高的性能。當發生死鎖時不會對用戶造成多大影響,或發生死鎖的概率很低,可以采用鴕鳥策略。大多數操作系統,包括 Unix,Linux 和 Windows,處理死鎖問題的辦法僅僅是忽略它。
**死鎖檢測與死鎖恢復**
不試圖阻止死鎖,而是當檢測到死鎖發生時,采取措施進行恢復。

上圖為資源分配圖,其中方框表示資源,圓圈表示進程。資源指向進程表示該資源已經分配給該進程,進程指向資源表示進程請求獲取該資源。
圖 a 可以抽取出環,如圖 b,它滿足了環路等待條件,因此會發生死鎖。
每種類型一個資源的死鎖檢測算法是通過檢測有向圖是否存在環來實現,從一個節點出發進行深度優先搜索,對訪問過的節點進行標記,如果訪問了已經標記的節點,就表示有向圖存在環,也就是檢測到死鎖的發生。
[更多內容參考](https://github.com/CyC2018/CS-Notes/blob/master/notes/%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%20-%20%E6%AD%BB%E9%94%81.md)
**使用銀行家算法來保證資源的合理分配**:[https://blog.csdn.net/qq\_37205708/article/details/86550339](https://blog.csdn.net/qq_37205708/article/details/86550339)
# 內存管理
## 物理地址和虛擬地址
段機制啟動、頁機制未啟動:邏輯地址 -> 段機制處理 \-> 線性地址 = 物理地址
段機制和頁機制都啟動:邏輯地址 -> 段機制處理 \-> 線性地址 -> 頁機制處理 \-> 物理地址
- 邏輯地址:CPU 所生成的地址通常稱為邏輯地址(logical address)
- 虛擬地址:一般是指邏輯地址,但是因為對程序員而言可見的只有線性地址,有時候也把線性地址稱為虛擬地址(可以理解為我們代碼中操作的是虛擬地址)
- 物理地址:內存單元所看到的的地址(即被加載到內存地址寄存器(memory-address register)中的地址)通常被稱為物理地址(physical address)
對虛擬地址的解釋:
每個進程都認為它有獨立的物理地址空間且不會認識到物理內存被虛擬化了。操作系統和硬件負責完成虛擬地址到物理地址的轉化。
OS 需要建立一個便于使用的物理內存的抽象,這個抽象便是(虛擬)地址空間。對于進程而言,可見的只是(虛擬)地址空間而不是物理內存,即其使用的地址都是虛擬地址,由 OS 轉化為物理地址。
## 分段機制
CPU 把邏輯地址(由段選擇子 selector 和段偏移 offset 組成)中的段選擇子的內容作為段描述符表的索引,找到表中對應的段描述符,然后把段描述符中保存的段基址加上段偏移值,形成線性地址(Linear Address)。如果不啟動分頁存儲管理機制,則線性地址等于物理地址。

舉個例子:

4200 這個邏輯地址(虛擬地址)被劃分為段選擇子和段偏移:

它的段偏移就是 0000 0110 1000, or hex 0x068, or 104 in decimal,段選擇子 01 選的是 34K,最后得到對應的物理地址就是 34K+104
- 優點:支持用戶視角,實現簡單,可以有效利用內存
- 缺點:無法利用碎片,必須搬移內存,造成性能損失(管理空閑空間較難)
## 分頁機制
將物理內存分為固定大小的塊,稱為幀(frame);將邏輯內存也分為同樣大小的塊,稱為頁(page)。
每個進程有獨立的頁表。CPU 生成的地址(虛擬地址)被分為兩個部分:頁號和偏移,頁號作為頁表中的索引,頁表中的每一項稱為頁表條目,頁表條目存儲地址轉換的信息。
每新建一個進程 OS 都會為其新建一個頁表,即使虛擬地址相同但映射到的物理地址是不同的。頁表往往可能很大,所以存儲在物理內存中。

概述一下 TLB和(用于加速地址轉換的硬件,可以理解為緩存)頁表一起使用的流程:
當 CPU 產生邏輯地址后,其 VPN 提交給 TLB,如果 TLB 命中則得到了幀號并可用來訪問內存。如果 TLB 失效,則需要訪問頁表,同時將頁號和幀號增加到 TLB 中。如果 TLB 條目已滿,那么 OS 會選擇一個來替換,替換策略有多種如 LRU。另外,有的 TLB 允許某些條目固定,即不會替換它們,如內核代碼的條目。
更詳細的分析見我的 [這篇筆記吧](https://blog.csdn.net/qq_37205708/article/details/86554764)
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直線、矩形、多邊形
- Part2-曲線圖形
- Part3-線條操作
- Part4-文本操作
- Part5-圖像操作
- Part6-變形操作
- Part7-像素操作
- Part8-漸變與陰影
- Part9-路徑與狀態
- Part10-物理動畫
- Part11-邊界檢測
- Part12-碰撞檢測
- Part13-用戶交互
- Part14-高級動畫
- CSS
- SCSS
- codePen
- 速查表
- 面試題
- 《CSS Secrets》
- SVG
- 移動端適配
- 濾鏡(filter)的使用
- JS
- 基礎概念
- 作用域、作用域鏈、閉包
- this
- 原型與繼承
- 數組、字符串、Map、Set方法整理
- 垃圾回收機制
- DOM
- BOM
- 事件循環
- 嚴格模式
- 正則表達式
- ES6部分
- 設計模式
- AJAX
- 模塊化
- 讀冴羽博客筆記
- 第一部分總結-深入JS系列
- 第二部分總結-專題系列
- 第三部分總結-ES6系列
- 網絡請求中的數據類型
- 事件
- 表單
- 函數式編程
- Tips
- JS-Coding
- Framework
- Vue
- 書寫規范
- 基礎
- vue-router & vuex
- 深入淺出 Vue
- 響應式原理及其他
- new Vue 發生了什么
- 組件化
- 編譯流程
- Vue Router
- Vuex
- 前端路由的簡單實現
- React
- 基礎
- 書寫規范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 與 Hook
- 《深入淺出React和Redux》筆記
- 前半部分
- 后半部分
- react-transition-group
- Vue 與 React 的對比
- 工程化與架構
- Hybird
- React Native
- 新手上路
- 內置組件
- 常用插件
- 問題記錄
- Echarts
- 基礎
- Electron
- 序言
- 配置 Electron 開發環境 & 基礎概念
- React + TypeScript 仿 Antd
- TypeScript 基礎
- React + ts
- 樣式設計
- 組件測試
- 圖標解決方案
- Storybook 的使用
- Input 組件
- 在線 mock server
- 打包與發布
- Algorithm
- 排序算法及常見問題
- 劍指 offer
- 動態規劃
- DataStruct
- 概述
- 樹
- 鏈表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 課程實戰記錄
- 服務器
- 操作系統基礎知識
- Linux
- Nginx
- redis
- node.js
- 基礎及原生模塊
- express框架
- node.js操作數據庫
- 《深入淺出 node.js》筆記
- 前半部分
- 后半部分
- 數據庫
- SQL
- 面試題收集
- 智力題
- 面試題精選1
- 面試題精選2
- 問答篇
- 2025面試題收集
- Other
- markdown 書寫
- Git
- LaTex 常用命令
- Bugs