作業系統抽象與網路 (OS Abstractions & Networks)

Overview Table

小節 主題 核心概念 一句話重點
1.7 (p.50-51) OS 管理硬體 layered view、三大抽象 應用程式操作硬體一律必須經過 OS
1.7.1 (p.51-53) Processes processcontext switchsystem callkernel process 是「執行中程式」的 OS 抽象,提供獨占硬體的假象
1.7.2 (p.53) Threads thread、共享 code/global data 一個 process 內的多個執行單元,共享資料比跨 process 容易
1.7.3 (p.54-55) Virtual Memory virtual address space、五大區域 每個 process 有相同、統一的記憶體視圖
1.7.4 (p.55) Files file = byte sequenceUnix I/O 所有 I/O 裝置都建模成檔案
1.8 (p.55-57) Networks 網路 = 另一個 I/O deviceclient-server 跨機器複製資料是現代系統最重要用途之一
1.9 開頭 (p.58) Important Themes Amdahl's law 引入 系統 = 硬體 + 系統軟體交織合作;詳見 01-Computer-Systems-Tour/04-Amdahls-Law-and-Concurrency-Themes

1.7 作業系統管理硬體 (The OS Manages the Hardware) (p.50-51)

回到 hello 範例:shell 載入並執行 hellohello 印出訊息時,兩者都不曾直接存取 keyboard、display、disk 或 main memory,而是依賴 operating system 提供的服務。OS 是一層插在應用程式與硬體之間的軟體,應用程式對硬體的所有操作都必須經過 OS(Figure 1.10)。

┌────────────────────────────────────────┐
│        Application programs            │ ┐
├────────────────────────────────────────┤ ├ Software
│        Operating system                │ ┘
├─────────────┬──────────────┬───────────┤
│  Processor  │ Main memory  │ I/O devices│ ─ Hardware
└─────────────┴──────────────┴───────────┘
        Figure 1.10 電腦系統的分層視圖

OS 的兩大目的:

OS 透過三個基本抽象 (fundamental abstractions) 同時達成兩個目標(Figure 1.11),抽象層層包含:

┌───────────────────────────────────────────┐
│                Processes                  │
│   ┌───────────────────────────────────┐   │
│   │         Virtual memory            │   │
│   │        ┌──────────────────┐       │   │
│   │        │      Files       │       │   │
│   │        └──────────────────┘       │   │
│   └───────────────────────────────────┘   │
└───────────────────────────────────────────┘
   Processor      Main memory     I/O devices
     Figure 1.11 OS 提供的抽象與其涵蓋的硬體
抽象 抽象化的硬體對象
Files I/O devices
Virtual memory Main memory + disk(I/O devices)
Processes Processor + main memory + I/O devices
Important

這張對應表是經典考點:process 涵蓋範圍最大(處理器、記憶體、I/O 全包),virtual memory 次之(記憶體 + 磁碟),file 最小(只抽象 I/O 裝置)。

1.7.1 行程 (Processes) (p.51-53)

Process 是 OS 對「執行中程式 (running program)」的抽象——電腦科學最重要且成功的想法之一。它提供三重假象 (illusion):程式彷彿是系統上唯一執行的程式、獨占 processor / main memory / I/O devices;processor 彷彿不被中斷地逐一執行指令;程式的 code 與 data 彷彿是記憶體中唯一的物件。

Context(上下文):process 執行所需的全部狀態資訊,包括 PC 目前值、register filemain memory 內容。OS 決定轉移控制權時執行 context switch:

  1. 儲存 (save) 目前 process 的 context
  2. 還原 (restore) 新 process 的 context
  3. 把控制權交給新 process —— 新 process 從它上次停下的地方精確地繼續
Time      Process A              Process B
  │   ┌─ User code
  │   │                                        ┐
 read └─ Kernel code  ──────┐                  ├ Context switch
  │                         ▼                  ┘
  │                      User code
  │   Disk interrupt        │                  ┐
  │   ┌─ Kernel code  ◀─────┘                  ├ Context switch
Return└─ User code                             ┘
from read
  ▼
     Figure 1.12 Process context switching(hello 情境)

hello 情境中有兩個並行 process:shell processhello process。流程:shell 等待命令列輸入 → 使用者要求執行 hello → shell 呼叫 system call 把控制權交給 OS → OS 儲存 shell 的 context、建立新的 hello process 及其 context、把控制權交給 hello → hello 終止後,OS 還原 shell 的 context 並交回控制權,shell 繼續等待下一個指令。

Kernel(核心):

Warning

易錯:kernel ≠ process。它是被所有 process 共用的程式碼與資料結構集合。另外 process 抽象需要低階硬體與 OS 軟體密切合作才能實現,細節見 08-Exceptional-Control-Flow/02-Processes-and-Context-Switches

Aside:Unix、Posix 與 Standard Unix Specification (p.52)

1969 年 Bell Labs 的 Ken Thompson、Dennis Ritchie、Doug McIlroy、Joe Ossanna 因 Multics 計畫過於複雜而退出,在 DEC PDP-7 上以機器語言開發更簡單的 OS;階層式檔案系統與「shell 作為 user-level process」的想法皆借自 Multics。1970 年 Brian Kernighan 取名「Unix」(對 Multics 複雜性的雙關嘲諷);1973 年 kernel 以 C 重寫,1974 年對外發表。柏克萊在 1970 末–1980 初加入 virtual memory 與 Internet protocols,推出 4.xBSD;Bell Labs 同期推出 System V。1980 年代中期各家 Unix 互不相容,IEEE 主導標準化,Richard Stallman 命名為「Posix」,涵蓋 system call 的 C 介面、shell 程式與工具、threads、網路程式設計;後與 Standard Unix Specification 合流成單一標準。

1.7.2 執行緒 (Threads) (p.53)

現代系統中一個 process 可由多個執行單元組成,稱為 thread;每個 thread 都在該 process 的 context 中執行,共享同一份 code 與 global data

Thread 日益重要的三個原因(教科書原列):

多執行緒 (multi-threading) 也是多處理器可用時讓程式跑更快的方法之一(1.9.2 節;實作見 Chapter 12)。

比較 Process Thread
定義 執行中程式的 OS 抽象 process 內的執行單元
code / global data 各自獨立(獨占假象) 同一 process 內共享
資料共享難度 較難 較容易
切換/建立成本 較高 通常較低(更有效率)

1.7.3 虛擬記憶體 (Virtual Memory) (p.54-55)

Virtual memory 提供每個 process「獨占 main memory」的假象。每個 process 看到相同、統一的記憶體視圖,稱為 virtual address space。Linux 的佈局如 Figure 1.13(其他 Unix 類似);位址由下往上遞增,最頂端區域保留給所有 process 共通的 OS code 與 data,下方才是使用者 process 的 code 與 data。

 高位址
┌──────────────────────────────┐
│    Kernel virtual memory     │ ← user code 不可見/不可存取
├──────────────────────────────┤
│         User stack           │ ← run time 建立;函式呼叫時
│  (created at run time)   ↓   │    向下成長,return 時收縮
├──────────────────────────────┤
│            ...               │
│ Memory-mapped region for     │ ← 例:printf 所在的
│      shared libraries        │    C standard library
│            ...               │
├──────────────────────────────┤
│              ↑               │
│        Run-time heap         │ ← malloc/free 動態伸縮
│     (created by malloc)      │
├──────────────────────────────┤
│       Read/write data        │ ┐ 由 hello 執行檔
├──────────────────────────────┤ ├ (executable object file)
│   Read-only code and data    │ ┘ 直接初始化載入
├──────────────────────────────┤ ← program start(固定位址)
│                              │
└──────────────────────────────┘ 0
 低位址
   Figure 1.13 Linux process 的 virtual address space

由低位址往高位址的五個區域:

區域 何時建立/如何變化 相關章節
Program code and data 所有 process 的 code 從同一固定位址開始;之後是對應 global C variables 的 data;由 executable object file 直接初始化,大小固定 Ch.7 linking/loading
Heap 緊跟 code/data 之後;malloc / free 呼叫使其於執行期動態擴張與收縮 Ch.9
Shared libraries 位於位址空間中段;存放 C standard library、math library 等共享函式庫的 code 與 data Ch.7 dynamic linking
Stack (user stack) 位於使用者位址空間頂端;compiler 用它實作函式呼叫;呼叫函式時成長、return 時收縮 Ch.3
Kernel virtual memory 位址空間最頂端,保留給 kernel;應用程式不得讀寫此區內容、不得直接呼叫 kernel 函式,必須透過 system call 請 kernel 代為執行 Ch.8/9

Virtual memory 的運作需要硬體與 OS 軟體的精密互動,包括處理器產生的每一個位址都要做硬體轉譯 (hardware translation)。基本想法:把 process 的 virtual memory 內容存在 disk 上,用 main memory 作為 disk 的 cache(詳見 09-Virtual-Memory/01-Address-Spaces-and-VM-Caching)。

Warning

「code 從同一固定位址開始」是本章的簡化說法;實務上還有 ASLR 等安全機制會隨機化佈局,見 03-Machine-Level-Programs/06-Buffer-Overflow-and-Pointer-Safety。另外圖中各區域未按比例繪製

1.7.4 檔案 (Files) (p.55)

A file is a sequence of bytes, nothing more and nothing less.(檔案就是位元組序列,不多也不少。)

Aside:Linux 專案 (p.56)

1991 年 8 月,芬蘭研究生 Linus Torvalds 在 comp.os.minix 上低調宣布一個「(free) operating system (just a hobby, won't be big and professional like gnu)」,目標是 386(486) AT clones;起點是 Tanenbaum 為教學開發的 Minix。Linux 之後與 GNU 專案結合,發展成完整、Posix-compliant 的 Unix 系統(kernel + 全部支援基礎設施),可在從手持裝置到大型主機的各種電腦上執行。

1.8 系統利用網路與其他系統溝通 (p.55-57)

至此我們把系統當成孤立的軟硬體集合;實務上現代系統常以網路連結其他系統。從單一系統的觀點,網路只是另一個 I/O 裝置(Figure 1.14):

        CPU chip
   ┌─────────────────┐
   │ Register file   │
   │  PC ──── ALU    │
   └───────┬─────────┘   System bus        Memory bus
     Bus interface ◀══════════▶ I/O bridge ◀═════▶ Main memory
                                   ║
                        ═══════════╬════════════════════ I/O bus
                          ║         ║          ║        ║
                        USB      Graphics    Disk     Network
                     controller  adapter   controller adapter
                        │           │          │        │
                  Mouse/Keyboard Monitor     Disk    Network ←── 通往其他機器
      Figure 1.14 網路是另一個 I/O device

telnet 遠端執行 hello 的五個步驟(Figure 1.15)——典型的 client-server 交換:

 (1) 使用者在鍵盤          (2) client 送 "hello" 字串給 telnet server
     輸入 "hello"       ─────────────────────────────────▶
                 ┌──────────┐        network         ┌──────────┐
                 │  Local   │                        │  Remote  │  (3) server 把 "hello" 交給
                 │  telnet  │                        │  telnet  │      shell;shell 執行 hello
                 │  client  │                        │  server  │      程式,輸出交回 server
                 └──────────┘ ◀───────────────────── └──────────┘
 (5) client 在顯示器印出   (4) server 把 "hello, world\n"
     "hello, world\n"          字串送回 client
      Figure 1.15 用 telnet 跨網路遠端執行 hello
  1. 使用者在鍵盤輸入 hello 並按 enter。
  2. telnet client 把字串經網路送給 telnet server
  3. server 收到後轉交遠端 shell;shell 執行 hello 程式,把輸出行交回 telnet server。
  4. server 把輸出字串 hello, world\n 經網路轉送回 client。
  5. client 在本地終端機印出該字串。

這種 client 與 server 間的交換是所有網路應用的典型模式(建構網路應用與 Web server 見 11-Network-Programming/01-Client-Server-Model-and-Networks)。

1.9 重要主題(開頭,p.58)

本頁開啟 1.9 節:系統不只是硬體,而是硬體與系統軟體交織、必須合作才能執行應用程式的集合體。p.58 並引入 Amdahl's law——加速系統的某一部分時,整體效益取決於該部分的佔比 α加速倍率 k:

Tnew=(1α)Told+αToldk=Told[(1α)+αk](1.1)S=ToldTnew=1(1α)+α/k

例:α = 0.6、k = 3 → S = 1/[0.4 + 0.6/3] = 1.67×。主要洞見:想大幅加速整個系統,必須改善佔整體很大比例的部分。完整討論(含極限情況 k→∞、並行主題)見 01-Computer-Systems-Tour/04-Amdahls-Law-and-Concurrency-Themes


Exam/Test Patterns

情境 / 關鍵字 答案
OS 的兩大目的? (1) 保護硬體不被失控應用程式濫用;(2) 提供簡單一致的機制操作複雜多樣的低階硬體
files / virtual memory / processes 各抽象什麼硬體? files → I/O devices;virtual memory → main memory + disk;processes → processor + main memory + I/O devices
「並行 (concurrently)」在 1.7.1 的定義 一個 process 的指令與另一個 process 的指令交錯 (interleaved) 執行
context 包含哪些狀態? PC 目前值、register file、main memory 內容
context switch 三步驟 儲存目前 process 的 context → 還原新 process 的 context → 把控制權交給新 process
kernel 是不是一個 process? 不是;它是常駐記憶體、用來管理所有 process 的 code 與 data structures 集合
應用程式如何請 OS 做事? 執行 system call 指令,把控制權轉給 kernel;kernel 完成後返回
thread 與 process 共享關係 同一 process 的 threads 共享該 process 的 code 與 global data
為何 thread 越來越重要?(三理由) 網路伺服器需要並行;threads 間共享資料較容易;threads 通常比 processes 更有效率
virtual address space 由低到高五區 program code and data → heap → shared libraries → user stack → kernel virtual memory
哪些區域執行期動態伸縮? heap(malloc/free)與 user stack(函式呼叫/返回);code/data 區在 process 開始後大小固定
virtual memory 的基本想法 process 的 virtual memory 內容存於 disk,main memory 作為 disk 的 cache;每個位址都經硬體轉譯
file 的定義 a sequence of bytes, nothing more and nothing less;所有 I/O 透過 Unix I/O system calls 讀寫檔案
從單一系統看,網路是什麼? 另一個 I/O device(透過 network adapter 收送 bytes)
telnet 遠端執行 hello 的步驟排序 輸入 → client 送字串 → server 交給 shell 執行 → server 送回輸出 → client 印出
Unix 名稱由來 / kernel 何時改用 C Brian Kernighan 1970 年取名(嘲諷 Multics);1973 年 kernel 以 C 重寫
Posix 標準涵蓋什麼? Unix system calls 的 C 介面、shell 程式與工具、threads、網路程式設計
α=0.6、k=3 的 speedup? S = 1/[(1−0.6)+0.6/3] = 1.67×