作業系統 - 學習筆記 (2) Process

「Program」、「Process」、「Thread」傻傻分不清楚?本文介紹作業系統 Process 的概念。

Program vs. Process vs. Thread

Program

  • 靜態的指令集 (file)
  • 例如:秘密小文件、週記、Hello world 程式

Process

  • 正在執行的指令集,有被載入主記憶體的 Program (executable file)
  • 簡而言之,就是正在執行的程式
  • 首先會先被傳入 Ready Queue (準備變成 Process 的動作),再來被載入主記憶體、載入 CPU 裡面正在執行

Process 組成架構

  • Text:一個 C 語言的程式
  • Data:全域變數
  • Heap:動態記憶體配置
  • Stack:放一些暫存的資料

I/O-bound process

  • I/O 的東西使用的比較多
    • 例如:Word processor
  • CPU bound process
    • 需要 CPU 不斷運算的程式
    • 例如:算圓周率
    • 平常的程式通常是兩個結合起來

Process 狀態及流程

  • New:新增一個 Process 出來
  • Ready:程式載入記憶體
  • Running:正在跑,Process 正在運算
  • Waiting:有中斷,進入等待
  • Terminated:Process 結束

Thread

  • Process 的小分身,寄生在 Process 裡面,共用 Process 的記憶體,且自己也擁有一個獨立的空間 (Stack) 可以做自己的事
  • 一定要有 Process 才會有 Thread
  • 一個 Process 有好多個 Thread (看 Chrome 就知道)
  • 例如:Word 拼音檢查的紅線
    • 如果拼音檢查也寫成 Process 的話,Word 的 Process 會先被關掉才能做拼音檢查

PCB (Process Control Block)

  • 像是 ER 圖用資料庫存起來,或者像是排球紀錄表,而 OS 管理 Process 所使用的紀錄表,就叫做 PCB
  • 幾個重要資訊:
    • Process State:上面提到的那五個狀態 (e.g. new, ready, etc.)
    • Process Number:Process 的 ID
    • Process Counter:記錄下一個 Process 的位址
    • CPU Registers:紀錄一些中斷資訊

排程器

長程排程器 (Long-Term Scheduler)

  • 不一定每個 OS 都有
  • 看哪個 Process 適合現在載入主記憶體,將它放入 Ready Queue

短程排程器 (Short-Term Scheduler)

  • 不管哪個 OS 都一定有
  • 因為 CPU 暫存器大小有限,所以會挑選哪些 Process 最適合現在做、最有效率

中程排程器 (Median-Term Scheduler)

  • 類似資源短程排程
  • 在 Process 載入 CPU 之前,已經通過了長程、短程排程器的篩選,使 CPU 以最有效率的排程完成 Process 們

    但是,排程的 Process 愈多,Content Switch 轉換的次數就愈多,代表 Drgree of Mutiprogramming 愈高,也就是 CPU 大部分的時間都在做 Content Switch!

    因此,中程排程器就會在 Drgree of Mutiprogramming 過高的時候,挑選幾個 Process 回到 Ready Queue

    • 例如:Content Switch 轉換太頻繁時,100 個工作 1000 秒會完成,其中 CPU 花 500 秒在轉換工作,這對 CPU 來講很沒效率!
      這時候就需要中程排程器,把幾個 Process 拉回 Ready Queue
  • 以下三個例子都是發生中斷,使 Process 跳回 Ready Queue:
    • 需要鍵盤或滑鼠,產生 I/O Request、中斷,先放在 I/O Queue 裡面再逐一使用
    • 某一個 Process 使用時間到了,它會先跳回 Ready Queue,再重新分配
    • OS 發現其他東西有中斷,做 Context Switch

Context Switch

  • 轉換 CPU 至另一個行程。先儲存舊行程的狀態,再載入新行程的狀態
    • 例如:A 發生中斷,要把 A Process 的 PCB 表轉換成 B Process 的 PCB 表,才能繼續執行
    • 有點類似交接班表
    • 花的時間的多寡取決於硬體的快慢

Process 的溝通方式

  • 獨立的 Process (Independent Process)
    • 獨立不受其他 Process 影響
  • 需要溝通的 Process (Cooperating Process)
    • 例如:「洗手」這個 Process 必須搭配「開水龍頭」這個 Process 才能達成洗手的動作
    • 用 Interprocess Communication (IPC) 溝通

Interprocess Communication (IPC)

  • Shared Memory (共享記憶體)
    • Process 之間共用一個記憶空間,你的資料就是我的資料,我的資料就是你的資料
  • Message Passing (Block send / receive, rendezvous)
  • 兩個 Process 中間會多一個 Process Queue (類似郵箱的功能) 暫存,需要的 Process 可以從這裡拿取資料
  • 隔開來多一個 Queue 去傳送
    • Blocking send:確保一定寄出
    • Blocking receive:確保一定收到
    • Rendezvous:兩者兼具,確保一定會寄出去,也確保一定會收到

Client-Server 之間 Process 的傳遞

  • 以上都是同一台電腦,但是現在網路發達,通常會在不同電腦之間做傳輸
  • Socket : IP address (IP 位址) + Port (服務口) = a socket
  • 3 種 Socket 方式:
    • Connection-Oriented (TCP):確保兩邊都活著,規範嚴謹、動作多、檢查需要時間
    • Connectionless (UDP):串流影音、通常需要大量傳遞的
    • Muticast Socket (類似廣播):傳播出去讓很多主機連接。
  • 使用 Socket 是比較底層、有效率的,通常傳一些位元、字串等比較難懂的東西,一個一個傳
  • Remote Procedure Call (RPC)
    • 運用在應用層 (最上層) 的服務
    • 把需要的東西 (服務) 包起來,傳出去給其他主機,就像是我這台主機本身有另一台主機的東西 (服務)
    • 最常見的例子:分散式網路服務、遠端管理、NFS 檔案分享

RPC 傳遞中間會有一些小問題

XDR 轉換

  • 不同主機,定義存取 (儲存記憶體) 的方式不同
  • Big endian:數字最大的東西放在記憶體位置最大的地方
    • 例如:1 儲存在 A;5 儲存在 E
  • Small endian:數字最小的東西放在記憶體位置最大的地方
    • 例如:1 儲存在 E;5 儲存在 A
  • 造成雙方聽不懂、雞同鴨講的問題,因此需要一位翻譯、代理人,也就是 Stub

Stub (proxy)

  • 主要就是做 XDR 轉換 (external data representation):轉換 big / small 的部分。
  • XDR 的意思是一種通用的格式
  • big / small endian 的資料經過 stub 都會轉換成這種大家都看得懂的格式
  • stub 轉換成 XDR 送出去的動作是 marshalling
    • 翻譯好丟出去 (例如:中翻英,再用英文講出去的這個動作)
    • 而 stub 收到 XDR 格式的資料就會依自身主機需求,轉換成 big / small endian (unmarshalling)
    • 聽到英文,轉成中文再傳給 Server 聽 (解譯)
  • 過去 big endian 比較常見,但現在的作業系統 big 跟 small 兩種都會,比較少出問題了

RPC 在 TCP/IP 傳輸的時候可能會漏掉一些東西,或者多傳了幾次

  • 改善的技術
  • Exactly once (僅處理一次):一定要剛好傳一次就到
    • 資料不能重複,要求 100%,做法較難
    • 使用 match maker,類似三方交握的方法
  • At most once (最多處理一次):最多傳一次就到
  • 一直傳,使用時間戳記 (timestamp) 紀錄,發現時間戳記不對就丟掉,因此資料可能會丟失
  • 大部分都是這個方式,因為比較簡單

Pipe

  • 仿照硬體 Pipeline 的行為,在 process 之間開一條或數條線來放資料
  • 電腦如果要一次做很多工作,會先把動作切成碎片,每個工作輪流做一些、快速切換,讓人看起來是很多工作同時被做
  • 有讀取端 (read-end) 與寫入端 (write-end),就叫做 Pipeline
  • 輸入 Linux 指令或 CGI 時會看到
  • Ordinary Pipe (單向) / Named Pipe (雙向)

Ordinary Pipe

  • 兩個 Process 的 f_inode 會指向同一個地方
  • f_op 代表這個 process 是要做什麼的
  • 有 fd[0] (write end) 跟 fd[1] (read end)
  • 步驟:首先有一個人先建管線,假設是 A process 自願建 Pipe 跟 B 連接
    • A 的 f_inode 連到 Pipe,此時 A process 的 f_op 有寫入端與讀取端
    • A Process 透過 fork() 的動作,複製子 Process (fd[0], fd[1]) 的定義給 B Process
    • B 把它的 f_inode 也連起來,此時兩邊都有讀取端與寫入端
    • 因為一端只能是讀或是寫,所以 A 把自己的讀取端砍掉,B 把自己的寫入端砍掉,變成 A process 寫給 B Process 去讀取

Named Pipe

  • 有一端可以同時是讀 + 寫

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫。