這里是一個簡明清晰的 Unix 發展史概覽,涵蓋從起源到現代的重要節點和演變過程。
Unix 發展史概覽
1. Unix 起源(1969年)
- 貝爾實驗室:Ken Thompson 和 Dennis Ritchie 開發出 Unix 操作系統。
- 最初設計目標:簡潔、可移植、多任務。
- 用匯編語言開發,后期移植為 C 語言,極大推動了跨平臺發展。
2. 早期版本(1970年代)
-
Unix Version 1 - 6(1971-1975):
- 基礎系統設計與完善。
- Version 6 (V6) 是首個廣泛傳播的版本,成為眾多高校教學和研究基礎。
-
Unix Version 7(1979):
- 被稱為第一個“現代Unix”,功能更完備。
- 引入 Bourne Shell、多種系統調用等。
3. Unix 分支與商業化(1980年代)
-
BSD Unix(伯克利軟件發行版)
- 加入網絡協議棧(TCP/IP)、虛擬內存支持。
- BSD 4.2 和 4.3 成為高性能的學術與商業系統基礎。
-
AT&T System V
- 商業版本 Unix,廣泛推廣。
- 引入 System V Interface Definition(SVID),統一標準。
-
Unix Wars
- BSD 和 System V 爭奪市場主導權,導致標準割裂。
4. 標準化與統一(1990年代)
-
POSIX 標準
- 統一操作系統接口,促使各種 Unix 系統兼容。
-
Unix 品牌管理
- IEEE 和 The Open Group 推出 “The Single UNIX Specification”。
-
Linux 崛起(1991起)
- Linus Torvalds 開發的免費 Unix-like 內核,快速普及。
5. 現代 Unix 與 Unix-like 系統(2000年代至今)
-
商業 Unix 系統
- 如 IBM AIX、HP-UX、Solaris 等繼續發展。
-
開源 Unix-like 系統
- BSD 系列(FreeBSD、OpenBSD、NetBSD)廣泛應用。
- Linux 作為主流服務器和嵌入式平臺。
小結時間線
1969 Unix誕生(貝爾實驗室)
1970s Unix早期版本(V1-V7)
1980s BSD Unix & System V 發展與分裂
1990s POSIX標準化,Linux興起
2000s 現代Unix與開源Unix-like系統共存
在 UNIX V6 中(特別是 PDP-11 架構下),只有進程(process)概念,沒有線程(thread) 的支持。我們來詳細對比一下:
🧠 1. UNIX V6 的執行單元是「進程」
? 每個進程有:
- 獨立的 地址空間(雖然沒有 MMU,但通過 relocation/base 寄存器實現簡單隔離)
- 獨立的 堆棧、代碼段、數據段
- 獨立的 打開的文件描述符列表
- 獨立的 用戶態 / 內核態棧
- PCB(進程控制塊):
proc
結構體
📌 換句話說:一個進程就是一個完整的程序的運行實例
? 2. UNIX V6 沒有線程
🚫 不存在:
- 多個線程共享同一地址空間
- 用戶態或內核態的線程庫
- 沒有 pthread、也沒有類似
clone()
的系統調用
在 UNIX V6 中,線程等同于進程的最小執行單元還未誕生。
📚 補充:現代對比
特性 | UNIX V6 | 現代 Linux / Windows |
---|---|---|
線程支持 | ? 無 | ? 有 pthread / clone / TCB |
地址空間隔離 | ? 基于 relocation | ? 基于 MMU |
并發機制 | ? 多進程 + fork() | ? 多進程 + 多線程 |
同步原語 | ? 無 | ? Mutex、Sem、Cond 等 |
?? 總結一句話:
UNIX V6 的“并發”全靠
fork()
創建多個獨立進程完成,沒有線程這個概念。
UNIX 在早期(包括 UNIX V6/V7)沒有線程的概念,所有的并發都是通過 fork() 創建進程來實現的,每個進程有獨立的地址空間,沒有共享內存,也沒有線程同步原語。
“LWP(輕量級進程,Light Weight Process)” 是線程發展歷史中一個非常關鍵的概念,尤其在早期 UNIX(如 Solaris)中引入,是連接用戶線程與內核線程的中間層。下面我詳細解釋:
? 什么是 LWP(Light Weight Process)?
LWP 是一種內核調度單位,它像一個普通進程一樣能被內核調度,但:
- 它和傳統的 UNIX 進程相比更輕量
- 允許多個用戶線程綁定到一個或多個 LWP 上
- 引入 用戶線程(user-level thread)與內核線程(kernel-level thread)之間的分離
🧠 為什么引入 LWP?
早期 UNIX:
- 每個進程是調度單位
- 多線程程序會導致所有線程都阻塞(因為調度粒度是整個進程)
引入 LWP 的目的:
- 實現線程調度 不完全依賴內核
- 用戶空間可以快速切換線程,減少系統調用
- 實現 M:N 模型(多個用戶線程映射到多個內核線程)
🔧 結構示意圖
用戶空間+--------------------------------+| 用戶線程1 用戶線程2 ... |+--------------------------------+↓ ↓LWP1 LWP2 <- 綁定關系↓ ↓內核線程1 內核線程2 <- LWP由內核調度
📘 Solaris 中的 LWP 模型(經典代表)
概念 | 描述 |
---|---|
用戶線程 | 程序員使用的線程接口(如 thr_create ) |
LWP | 用戶線程與內核之間的橋梁,由內核調度 |
內核線程 | OS 級別線程,是 CPU 的實際執行單位 |
M:N 模型 | 多個用戶線程通過多個 LWP 共享少量內核線程 |
🧵 與 POSIX 線程的關系
- POSIX
pthreads
抽象的是用戶線程接口 - 在 Solaris 中,
pthreads
是基于 LWP 實現的 - 在 Linux 中,
pthreads
實際上就是 每個線程 = 一個 LWP = 一個內核線程,是 1:1 模型
🔍 LWP 的優劣
優點 | 缺點 |
---|---|
用戶線程調度效率高 | 實現復雜(需要管理映射關系) |
可以復用 LWP,節省系統資源 | 用戶線程阻塞時,LWP 也會被阻塞 |
更靈活:適合 IO 密集 + CPU 密集 | 很難在 Linux 等平臺通用實現 |
🧠 總結一句話:
LWP 是一種由內核調度的輕量進程,用于支持用戶線程的執行,是早期 M:N 多線程模型的關鍵組成。
現代主流系統(如 Linux、macOS)已經普遍采用 1:1 模型(每個線程一個內核線程),放棄了復雜的 M:N 和 LWP,但它在線程設計歷史上具有里程碑意義。
是的,RT-Thread Smart 中的 LWP(Light Weight Process) 與 Solaris、早期 UNIX 系統中的 LWP 含義有相似之處,但也有一些區別,下面我來詳細說明:
? RT-Thread Smart 中的 LWP 是什么?
RT-Thread Smart 是 RT-Thread 的類 Unix 擴展(用戶空間 + 內核空間),LWP 是 Smart 中的用戶態進程模型實現的核心結構,代表一個用戶空間進程。
在 RT-Thread Smart 中,LWP(輕量級進程):
- 是一種用戶態進程,具有獨立的地址空間
- 擁有獨立的虛擬內存、文件描述符表、信號處理等
- 內核調度的是線程(
rt_thread
),線程屬于某個 LWP - 一個 LWP 可以有多個線程(共享用戶空間)
🧠 和傳統 UNIX 的 LWP 比較
特性 | Solaris / UNIX LWP | RT-Thread Smart LWP |
---|---|---|
所屬系統 | UNIX(如 Solaris) | RT-Thread Smart |
實質 | 用戶線程的橋梁 / 調度單位 | 用戶空間進程 |
是否被內核調度 | 是(間接調度) | 不是(線程調度) |
是否有獨立地址空間 | 否(多個線程共享) | 是(每個 LWP 是獨立地址空間) |
線程關系 | 多個線程通過 LWP 映射到內核線程 | 多個線程屬于同一個 LWP,共享資源 |
內核視角 | LWP 是調度單位 | LWP 是運行環境(調度單位是 rt_thread ) |
? 可以簡單類比為:
- UNIX LWP ≈ 內核調度用的線程容器
- RT-Thread LWP ≈ 獨立的用戶進程(帶地址空間)
📦 RT-Thread Smart 中的進程-線程模型
結構大致如下:
內核空間
+----------------------------+
| RT-Thread |
| +---------------------+ |
| | rt_thread(線程) | <----- 調度單位
| +---------------------+ |
| | LWP(進程) | <----- 用戶進程環境
| +---------------------+ |
+----------------------------+用戶空間(每個進程)
+----------------------------+
| main() 用戶代碼 |
| libc, heap, stack, ... |
+----------------------------+
?? 為什么叫 LWP?
這個命名是借鑒 UNIX 世界的“輕量級進程”的概念,強調:
- 它不是傳統大內核進程(如 Linux task_struct 那種)
- 它比傳統進程更“輕”,適用于嵌入式環境
- 支持獨立地址空間、用戶態運行,是 Smart 支持應用層的核心機制
? 總結
RT-Thread Smart 的 LWP 是“用戶態進程”的抽象,與傳統 UNIX 的 LWP 都強調輕量、可調度、可擴展,但意義略有差異。
方面 | RT-Thread Smart 中的 LWP |
---|---|
本質 | 用戶進程(獨立地址空間) |
是否支持線程 | 是,多個線程屬于一個 LWP |
是否被調度 | 否,調度的是線程 |
內存隔離 | 支持 MMU 的隔離(Smart 模式) |
在具有多線程與多進程支持的操作系統(如 Linux、RT-Thread Smart 等)中,調度屬于不同進程的線程和調度同一進程內的線程,在實現層面有一些關鍵區別,主要體現在以下幾個方面:
? 1. 地址空間切換(上下文)
? 不同進程的線程切換
- 需要切換地址空間(切換頁表或 MMU 上下文);
- 內核必須刷新 MMU 頁表基地址,切換到另一個進程的內存視圖;
- 代價更高,因為涉及 TLB flush、cache coherence 等;
- 所有進程私有的數據(堆、棧、代碼段)都會發生變化。
👉 舉個例子:
進程 A 的線程 T1 → 切換 → 進程 B 的線程 T2
系統必須切換頁表,所有內存訪問都按 B 的上下文來解釋。
? 同一進程的線程切換
- 無需切換地址空間,因為線程共享進程的地址空間;
- 只需要切換線程的 CPU 上下文(寄存器、堆棧等);
- 開銷較小,調度速度快;
- 常見于用戶態多線程庫、POSIX 線程(pthread)等。
👉 舉個例子:
進程 A 的線程 T1 → 切換 → 進程 A 的線程 T2
頁表不動,僅換棧、寄存器等上下文。
? 2. 資源管理與權限
不同進程的線程:
- 擁有獨立的資源和權限;
- 文件描述符、信號處理器、環境變量等互不干擾;
- 更適合服務隔離、安全場景。
同一進程的線程:
- 共享幾乎所有資源:堆、靜態區、文件句柄、socket 等;
- 適合高效協作、低開銷計算,但不利于隔離。
? 3. 調度粒度與策略
調度項目 | 同進程線程切換 | 跨進程線程切換 |
---|---|---|
時間片輪轉 | 通常一樣 | 通常一樣 |
優先級調度 | 適用 | 適用 |
地址空間切換 | 否(保留) | 是(重載) |
系統負擔 | 較低(僅 CPU 上下文) | 較高(CPU + MMU 上下文) |
? 4. 在 RT-Thread Smart 中的例子
RT-Thread Smart 的 LWP + thread 模型支持這兩類調度:
示例結構:
進程 A(LWP 1)├── 線程 T1└── 線程 T2進程 B(LWP 2)└── 線程 T3
T1 ? T2
切換:共享地址空間,僅切換rt_thread
T2 ? T3
切換:需要執行地址空間切換(虛擬內存重新映射)
? 總結表格
比較項 | 同進程線程切換 | 跨進程線程切換 |
---|---|---|
是否切換地址空間 | 否 | 是 |
切換開銷 | 低(快) | 高(慢) |
資源共享程度 | 高(幾乎完全共享) | 低(完全隔離) |
安全性 | 差 | 好 |
典型用途 | 多線程并發 | 多任務/服務隔離 |
好問題!關于“進程和線程的關系”以及“多進程多線程的調度”,我來詳細解釋一下:
1. 一個進程是一個內核線程嗎?
-
傳統意義上:不完全是。
-
進程(Process) 是資源分配的單位,擁有獨立地址空間、打開的文件等。
-
線程(Thread) 是 CPU 調度的基本單位,負責執行代碼。
在不同操作系統模型中的關系:
模型類型 | 說明 |
---|---|
1:1 模型(如 Linux) | 每個線程是一個內核線程,進程是線程集合。 進程本身不調度,調度的是線程。 |
M:N 模型(如 Solaris 舊版、RT-Thread Smart) | 用戶線程與內核線程映射不是一一對應。進程里可有多個用戶線程,通過多個內核線程調度。 |
單線程進程模型(如早期 UNIX) | 一個進程對應一個執行單元(線程),即進程就是內核線程。 |
2. 多個進程多個線程如何調度?
在現代系統(1:1 模型,如 Linux):
-
內核維護所有線程的 PCB(Linux 中是 task_struct,每個線程一個);
-
調度器按時間片、優先級等策略從所有線程里選擇一個運行;
-
線程調度時,如果跨進程(切換地址空間),內核完成頁表切換;
-
同進程線程調度時,內核切換 CPU 上下文,無需切換地址空間。
舉個例子:
假設有兩個進程:
- 進程A 有線程A1、A2
- 進程B 有線程B1、B2、B3
內核調度器會在這 5 個線程中輪換執行,比如:
A1 → A2 → B1 → B2 → B3 → A1 → ...
切換不同進程線程時切換地址空間,同進程線程切換時地址空間不變。
3. 調度器怎么實現?
-
維護就緒隊列:里面存放所有可運行的線程;
-
上下文切換:保存當前線程狀態,恢復下一個線程狀態;
-
切換頁表(跨進程)或保持不變(同進程);
-
搶占機制:支持搶占式多任務,定時器中斷觸發調度。
4. 在 RT-Thread Smart 中
-
進程被稱為 LWP(輕量級進程);
-
內核調度單位是線程(
rt_thread
); -
每個線程屬于某個 LWP(進程);
-
調度器從所有線程中選一個運行;
-
切換不同 LWP 線程時,完成地址空間切換。
總結:
概念 | 說明 |
---|---|
進程 | 資源容器,擁有獨立地址空間 |
線程 | CPU 調度單位,執行代碼的“實體” |
一個進程=一個內核線程? | 早期 UNIX 是,現代系統否。 |
多進程多線程調度 | 統一調度所有線程,切換時根據是否跨進程切換地址空間。 |
下面是一個用 Mermaid 畫的關于 多進程多線程調度 的簡化流程圖示例,重點表現線程調度時是否需要切換地址空間:
flowchart TDStart[調度器觸發]SelectThread[選擇下一個線程執行]SameProcess{是否與當前線程同一進程?}SwitchContext[切換線程上下文]SwitchAddressSpace[切換地址空間(頁表切換)]RunThread[線程運行]TimerInterrupt[定時器中斷]Start --> SelectThreadSelectThread --> SameProcessSameProcess -- 是 --> SwitchContextSameProcess -- 否 --> SwitchAddressSpaceSwitchAddressSpace --> SwitchContextSwitchContext --> RunThreadRunThread --> TimerInterruptTimerInterrupt --> Start
說明:
-
調度器周期性觸發(通常由定時器中斷觸發)。
-
選擇下一個要執行的線程。
-
判斷是否是同一進程線程:
- 是:只切換線程上下文(寄存器、棧指針等)。
- 否:需要先切換地址空間(更新 MMU 頁表),再切換上下文。
-
切換完成后,線程開始運行。
-
運行過程中,定時器中斷再次觸發調度。