Upload
fenella-peoples
View
23
Download
3
Embed Size (px)
DESCRIPTION
作業系統. 第七章 行程相關實作. 第七章 行程相關實作. 資料結構 行程描述器 行程狀態 行程串列 就緒佇列 行程運作 行程間的溝通 摘要. 資料結構. 以作業系統的觀點來看行程,一個行程控制區塊就代表一個行程。 Linux 中與行程相關的資料結構 行程控制 區塊 行程狀態 行程串列 就緒佇列. 行程描述器. 描述器用來描述系統元件,如行程描述器。 描述器就是對應到實作的程式碼中的某個結構。 行程描述器是個儲存在核心位址空間中的龐大結構。 - PowerPoint PPT Presentation
Citation preview
資工系網媒所 NEWS實驗室
01:46 /434
行程描述器描述器用來描述系統元件,如行程描述器。描述器就是對應到實作的程式碼中的某個結構。行程描述器是個儲存在核心位址空間中的龐大結構。Linux 中行程描述器稱為 task_struct 。定義在 Linux 核心源碼的 include/linux/sched.h 中。
資工系網媒所 NEWS實驗室
01:46 /435
行程狀態
在 Linux 中,行程的狀態記錄在行程描述器中的 state 欄位:
#define TASK_RUNNING 0#define TASK_INTERRUPTIBLE 1#define TASK_UNINTERRUPTIBLE 2#define TASK_ZOMBIE 4#define TASK_STOPPED 8
volatile long state; /* -1 不可執行, 0 可執行, >0 被停止*/
資工系網媒所 NEWS實驗室
01:46 /436
行程狀態 ( 續 )
TASK_RUNNING :行程正在執行或是等待被執行時。TASK_INTERRUPTIBLE :等待某些事件發生時,如等待信號的傳遞。TASK_UNINTERRUPTIBLE :與TASK_INTERRUPTIBLE 一樣,不同的是信號傳遞時並不會造成狀態的改變。TASK_STOPPED :收到 SIGSTOP 、 SIGTSTP 、 SIGTTIN 或 SIGTTOU 信號時。TASK_ZOMBIE :當子行程結束時,父行程尚未呼叫類似 wait() 的系統呼叫來得知子行程的狀態並作適當處理,於是子行程就會處於這個狀態。
資工系網媒所 NEWS實驗室
01:46 /437
行程串列
Linux 使用鏈結串列將系統中所有的 PCB 串在一起。行程描述器中的 next_task 與 prev_task 這兩個欄位,就是鏈結串列的指標。
使用 for_each_task 巨集可以輕易地走訪整個行程串列。
struct task_struct *next_task, *prev_task;
資工系網媒所 NEWS實驗室
01:46 /438
Linux 的行程串列
prev_task prev_tasknext_taskprev_task next_task next_task
init_task
資工系網媒所 NEWS實驗室
01:46 /439
就緒佇列
在就緒佇列中的所有行程,其狀態皆為TASK_RUNNING 。行程描述器中實作就緒佇列的 run_list 欄位:
就緒佇列的開頭
struct list_head run_list;
static LIST_HEAD(runqueue_head);
資工系網媒所 NEWS實驗室
01:46 /4310
就緒佇列 ( 續 )
將一個行程加入就緒佇列:add_to_runqueue()
static inline void add_to_runqueue(struct task_struct * p){
list_add(&p->run_list, &runqueue_head);nr_running++;
}
資工系網媒所 NEWS實驗室
01:46 /4313
行程建立與建立行程有關的系統呼叫
fork()
vfork()
clone()
fork() 複製一份與父行程相同的位址空間copy-on-write 技術
vfork() 允許父行程與子行程共用相同的位址空間
父行程呼叫 vfork() 後會被阻隔
資工系網媒所 NEWS實驗室
01:46 /4314
行程建立 ( 續 )
clone() 可以透過一些參數來設定父行程與子行程間可以共用那一些系統資源。在核心中 fork() 、 vfork() 與 clone() 系統呼叫皆會觸發 do_fork() 。以 vfork() 為例: asmlinkage int sys_vfork(struct pt_regs regs){
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0);}
資工系網媒所 NEWS實驗室
01:46 /4315
行程建立 ( 續 )
do_fork() 函式執行的內容大致可以分成 6 個部分,分別為:
配置 task_struct 的空間。複製父行程 task_struct 中所有的欄位。改變子行程 task_struct 中不可繼承的欄位並作一些初始化的設定。根據 clone_flags 判斷要複製那些父行程資源,並且初始化子行程的核心堆疊。將子行程的 task_struct 加入系統的行程串列中。將子行程喚醒。
資工系網媒所 NEWS實驗室
01:46 /4316
內文切換
內文切換時,最重要的就是將行程執行時的 CPU 暫存器值保存下來。與硬體架構關係非常地密切,需要使用組合語言來輔助撰寫。Linux 中內文切換的工作是由 switch_to 這個巨集來執行。
資工系網媒所 NEWS實驗室
01:46 /4317
行程與 CPU 暫存器狀態的示意圖( 1 )
行程 next
行程 prev
stack
data
text
stack
data
text
ESP
ESI
EDI
EIP
CPU 暫存器
0x1d001d00
esp:0x1f002100
esp:0x1a00c100
0x1c100100
0x1c001100
0x1b00a100
行程 prev 的行程描述器
行程 next 的行程描述器
主記憶體
eip:0x1a00a000
eip:0x1b01c000
資工系網媒所 NEWS實驗室
01:46 /4318
行程與 CPU 暫存器狀態的示意圖( 2 )
esp:0x1a00c100行程 next
行程 prev
stack
data
text
stack
data
text
ESP
ESI
EDI
EIP
CPU 暫存器
0x1d001d00
esp:0x1d001d000x1c100100
0x1c001100
0x1b00a104
行程 prev 的行程描述器
行程 next 的行程描述器
eip:0x1b01c000
eip:0x1a00a000
主記憶體
資工系網媒所 NEWS實驗室
01:46 /4319
行程與 CPU 暫存器狀態的示意圖( 3 )
行程 next
行程 prev
stack
data
text
stack
data
text
ESP
ESI
EDI
EIP
CPU 暫存器
0x1a00c100
esp:0x1d001d00
esp:0x1a00c100
0x1c100100
0x1c001100
0x1b00a108
行程 prev 的行程描述器
行程 next 的行程描述器
eip:0x1b01c000
eip:0x1a00a000
主記憶體
資工系網媒所 NEWS實驗室
01:46 /4320
行程與 CPU 暫存器狀態的示意圖( 4 )
行程 next
行程 prev
stack
data
text
stack
data
text
ESP
ESI
EDI
EIP
CPU 暫存器
0x1a00c100
esp:0x1d001d00
esp:0x1a00c100
0x1c100100
0x1c001100
0x1b00a10c
行程 prev 的行程描述器
行程 next 的行程描述器
eip:0x1a00a000
eip:0x1d001d18
主記憶體
資工系網媒所 NEWS實驗室
01:46 /4321
行程與 CPU 暫存器狀態的示意圖( 5 )
行程 next
行程 prev
stack
data
text
stack
data
text
ESP
ESI
EDI
EIP
CPU 暫存器
0x1a00c100
esp:0x1d001d00
esp:0x1a00c100
0x1c100100
0x1c001100
行程 prev 的行程描述器
行程 next 的行程描述器
主記憶體eip:0x1a00a000
0x1a00a000
eip:0x1d001d18
資工系網媒所 NEWS實驗室
01:46 /4322
行程與 CPU 暫存器狀態的示意圖( 6 )
行程 next
行程 prev
stack
data
text
stack
data
text
ESP
ESI
EDI
EIP
CPU 暫存器
0x1a00c100
esp:0x1d001d00
esp:0x1a00c100
0x1c100100
0x1c001100
0x1a00a00c
行程 prev 的行程描述器
行程 next 的行程描述器
主記憶體eip:0x1a00a000
eip:0x1d001d18
資工系網媒所 NEWS實驗室
01:46 /4323
行程結束
大部分的行程結束是指行程執行完最後一個指令。需要將行程先前使用過的一些系統資源回收。正常的情況下,行程執行到最後一個指令時會觸發 exit() 系統呼叫。在核心中真正作處理的是 do_exit() 函式。
資工系網媒所 NEWS實驗室
01:46 /4324
行程結束 ( 續 )
do_exit() 函式會依序執行下列動作:將行程描述器中的 flag 欄位設為 PF_EXITING ,代表這個行程正在結束。分別移除號誌佇列與計時器佇列中該行程曾經插入的元素。將行程所用到的記憶體空間、開啟的檔案、檔案系統資源與信號佇列回收。將行程描述器中的 state 與 exit_code 欄位分別設為 TASK_ZOMBIE 與相應的返回值。 更新父行程與子行程間的相互關係。呼叫排程器 schedule() 選出下一個可以執行的行程。
資工系網媒所 NEWS實驗室
01:46 /4326
行程間的溝通 Linux 提供了一些行程的通訊機制,讓行程間進行溝通:管道號誌訊息共享記憶體插口
Linux 核心中進行行程間的溝通時,為了保持重要核心資料結構的一致性,使用了一些同步機制,如:旋轉鎖號誌
資工系網媒所 NEWS實驗室
01:46 /4327
旋轉鎖
最基本的同步機制之一,它就像門鎖一樣,當門鎖鎖上後,其他人就不能再進入這個房間。在單處理器的環境下,有可能造成等待的行程一直忙碌等待,而將鎖鎖上的行程卻沒有機會進行內文切換,將鎖打開。 多處理器的環境下旋轉鎖相當有效率。
資工系網媒所 NEWS實驗室
01:46 /4328
旋轉鎖 ( 續 )
每個旋轉鎖以 spinlock_t 結構來代表,其中只有一個 lock 欄位:
lock 的值為 1 時,表示鎖是開著的。lock 的值小於等於 0 時,則表示鎖已被鎖上。
spin_lock() 將 spinlock_t 結構中的 lock 欄位值減 1 ,如果 lock 的值小於 0 ,則使用迴圈一直去測試 lock 欄位值是否等於 0 。spin_unlock() 將 lock 的欄位值設為 1 。當兩個行程同時讀取同一份資料時,使用旋轉鎖是比較沒有效率的:讀 / 寫的旋轉鎖。
資工系網媒所 NEWS實驗室
01:46 /4329
讀 / 寫旋轉鎖
臨界區
行程 A行程 AR
行程 B行程 BR
行程 C行程 CW
臨界區
行程 D行程 DW
行程 F行程 FR
行程 E行程 EW
R
W
:讀取用:寫入用
資工系網媒所 NEWS實驗室
01:46 /4330
號誌Linux 號誌可分為核心號誌與使用者號誌。Linux 核心號誌的型別為 struct semaphore 。struct semaphore 的欄位 count :
大於 0 時,代表現在可以使用此號誌。小於或等於 0 時,代表這個號誌現在正忙碌中。
使用或釋出信號:down() - 將號誌的 count 值減 1 。 up() - 將 count 值加 1 。
資工系網媒所 NEWS實驗室
01:46 /4331
訊息佇列使用者號誌、訊息與共用記憶體屬於 IPC 的範圍。 透過代號來使用 IPC 資源。semget() 、 msgget() 或 shmget() 分別取得信號、訊息或共用記憶體的 IPC 代號。Linux 中所有與 IPC 相關的函式都是透過 ipc() 系統呼叫來完成的。訊息佇列:
msgget() - 取得訊息佇列的代號。msgsnd() - 傳送訊息。msgrcv() - 接受訊息。
資工系網媒所 NEWS實驗室
01:46 /4332
訊息佇列 ( 續 )Linux IPC 訊息佇列的資料結構:
struct ipc_ids - 每一種 IPC 資源各自擁有一個 ipc_ids 結構,訊息佇列為 msg_ids 。struct msg_queue - 代表一個訊息佇列。struct msg_msg 、 struct msg_msgseg - struct msg_msg 用來代表一個訊息,每個訊息使用雙向鏈結串列連接在一起。訊息超過一個分頁( 4 KB)時,使用其它的 struct msg_msgseg 來儲存。struct msg_sender 、 struct msg_receiver - 用來代表正在等待的傳送端與接收端行程。
msgsnd() 在核心中是呼叫 sys_msgsnd() ,大致可分為三個部分,分別為:
初始化。檢查訊息佇列是否有空間存放訊息。檢查訊息佇列中的接收端行程串列是否有行程正等待訊息。
資工系網媒所 NEWS實驗室
01:46 /4333
IPC 訊息佇列的資料結構
m_listm_list
……
……
entries[]entries[]
……
q_messagesq_messages
q_sendersq_senders
q_receiversq_receivers
msg_queue
…… 77 … … …… … …
msg_ids
msg_msg
nextnext
m_listm_list
……
msg_msg
nextnext
msg_msgseg
listlist
tsktsk
nextnext
msg_sender
r_listr_list
r_tskr_tsk
……
r_msgr_msg
msg_receiver
資工系網媒所 NEWS實驗室
01:46 /4334
摘要 (1)
Linux 核心中的行程控制區塊是由一個 task_struct 結構來代表。Linux 核心中動態建立行程的系統呼叫
fork()
vfork()
clone()
Linux 核心中處理內文切換的巨集:switch_to