網路城邦
上一篇 回創作列表 下一篇   字體:
作業系統筆記(2) 行程與執行緒
2020/10/04 23:18:07瀏覽2657|回應0|推薦0

2章行程(process)與執行緒(thread)

電腦系統裡頭執行的程式就像是高速公路上的車流,從開始執行到結束會有一個歷程,作業系統就像高速公路網,在設計與管理上必須盡量讓程式陸續完成,不會失敗或是當機。

行程是作業系統裡頭執行當中的程式,通常使用者在電腦的作業系統中可以下指令或是執行各種程式,結果就是產生一些處理元。

假如作業系統中有許多使用者,則可能產生的處理元的數量就非常多,可是CPU的處理能力有限,所以作業系統必須安排好處理元的執行先後順序,這也就是處理元的排程(process scheduling)。 假如作業系統中有許多使用者,則可能產生的處理元的數量就非常多,可是CPU的處理能力有限,所以作業系統必須安排好處理元的執行先後順序,這也就是處理元的排程(process scheduling)

處理元在執行的時候,跟這個處理元相關的資料必須儲存在記憶體中,讓執行程式的處理器能迅速地存取。

程式program)只是一種靜態的內容,程式拿來執行以後產生了具有動態特性的處理元,同一個程式執行多次就產生了多個處理元,基本上,這些處理元都各不相同,在作業系統裡具有唯一的身份,當處理元產生時,作業系統會建立處理元描述資料(process descriptor,是一種資料結構,不同的作業系統所用的處理元描述資料也不一樣

處理元在作業系統中是以處理元控制方塊(PCBprocess control block)來表示的,也稱為工作控制方塊(task control block)可以看成是一種儲存處理元相關資料的資料結構,每一種作業系統的PCB結構可能都不太一樣,不過概念上大同小異。

電腦開機以後,CPU會開始從記憶體中所謂的開機始點(bootstrap entry point),擷取指令執行。這是系統開始執行的第一個程式,裡頭包括了一些最基本的作業,最後的目標當然是建立起作業系統執行的環境。一旦作業系統開始載入執行,馬上會控制電腦系統的硬體資源,同時產生所需要的資料結構與硬體設備的狀態(device state)

通常作業系統會提供一個指令介面(command-line interface)與外界溝通,習慣上稱為外殼(shell) 作業系統的啟動程序決定於第一個執行的處理元,UNIX系統開始是以單一使用者(single user與多處理元(multiple process)的模式執行,單一使用者指superuser,UNIX系統的啟動程序中有一部分是執行/etc/rc檔案,rc代表run control,裡頭含有shell commands,將一些要先執行的程式執行起來,通常rc執行的工作與系統的組態(configuration)有關。

傳統的UNIX系統供多人登入使用,通常伺服器的每個序列埠(serial port)都會執行一個對應的getty程式,getty會呼叫login程式執行,讓使用者登入。使用者登入之後,所用的就是shell介面,使用者執行的shell有個別的資料與堆疊,使用者登出(logout)之後,shell結束,回到login程式,等待下一個使用者登入。

既然處理元會產生其他的處理元,我們可以預期這些相關的處理元將會形成一個樹狀的結構(tree structure),處理元之間的溝通則稱為IPC(Inter-process communication),IPC是作業系統提供的系統呼叫(system call)

系統呼叫是作業系統和使用者程式(user program)之間的介面,不同的作業系統所提供的系統呼叫也不太一樣,但是觀念都十分類似。假如從電腦開始啟動的時候想起,我們可以發現最初執行的處理元不必太複雜,只要能把作業系統帶起來就行了,作業系統本身的功能複雜,有許多功能是借著系統呼叫再產生的,系統就能在已有的基礎上發展出來。

Linux作業系統提供「系統呼叫介面(system call interface),使用者程式可以透過這個介面與作業系統核心溝通,我們可以把新的系統呼叫加入到作業系統核心中,以這種方式來擴充作業系統的功能。

我們要先了解如何透過作業系統核心的原始程式碼來建立核心的執行程式碼(binary),以及如何使用新的核心程式來開機,然後再看看如何為核心程式增加新的功能。

1.取得Linux版本的核心原始程式碼

2.學習如何處理核心原始程式碼

3.將新建的核心程式設定為系統開機的核心程式(bootable kernel)之一

現在可以試著把一個新的原始程式碼檔案加到核心原始程式碼中,通常原始程式碼儲存在「/usr/src/linux-2.x/kernel」的目錄底下,Linux版本不同時這個路徑也會有一點差異。有兩種加入系統呼叫的方式:

1.將系統呼叫加入現有的原始程式檔案中。

2.在原始程式檔案所在的目錄中加入新的原始程式檔案,然後修改「/usr/src/linux-2.x/kernel/Makefile,讓新的檔案也會被編譯。

使用新核心開機以後,新的系統呼叫就可以使用了,不過我們必須寫一個使用者程式來進行呼叫才知道是否成功。

最簡單的作業系統結構是沒有結構的作業系統,也稱為Monolithic systems。在這種作業系統裡頭,作業系統本身由一群程序(procedure)所組成,程序間彼此呼叫,所以這裡談的程序其實就是處理元,CPU執行的模式有兩種:1.Kernel mode2.User mode

使用新核心開機以後,新的系統呼叫就可以使用了,不過我們必須寫一個使用者程式來進行呼叫才知道是否成功。

最簡單的作業系統結構是沒有結構的作業系統,也稱為Monolithic systems。在這種作業系統裡頭,作業系統本身由一群程序(procedure)所組成,程序間彼此呼叫,所以這裡談的程序其實就是處理元,CPU執行的模式有兩種:1.Kernel mode2.User mode

處理元本身的資訊,最主要的是所在的位置與一些重要的屬性,習慣上可以把這些資訊稱為處理元控制方塊(PCB, Process Control Block) ,而和處理元相關的一切,包括資料(data)、程式(program)、系統堆疊(system stack)PCB,則統稱為處理元的影像(process image)。處理元所在的位置就是指處理元的影像所在的位置。處理元的屬性包括3大類:1.處理元的辨識資訊(process identification) 2.處理元的狀態(process state) 3.處理元的控制資訊(process control information)

PCB通常包括下列的資訊:

1.處理元狀態(process state):記錄處理元目前的狀態,例如newreadyrunningwaitingterminated等狀態。

2.程式計數(program counter):記錄該處理元下一個要執行的指令的位址。

3.CPU暫存器(CPU registers):不同的電腦結構使用的CPU暫存器的數目與類型都不太一樣,例如accumulatorsindex registersstack pointersgeneral-purpose registers等都是。當「中斷(interrupt)」發生的時候,這些暫存器裡頭的資訊也要保存起來,當處理元回頭繼續執行時會用得上。

4.處理元排程資訊:包括處理元的優先順序(priority)、指向排程佇列(scheduling queue)的指標,以及其他跟排程相關的參數。

5.記憶體管理的資訊:相關的資訊決定於作業系統所採用的記憶體系統,通常包括base registerlimit register所儲存的值、頁表格(page table)與分段表格(segment table)等。

6.使用統計的資訊(accounting information):包括CPU使用時間、實際使用時間、時間限制、帳號、處理元號碼等資訊。

7.輸入與輸出狀態(I/O status)的資訊:包括處理元占用的輸出入裝置、開啟的檔案等。

程式可由其他電腦主機上的程序(process)獲取資料,這是程序間溝通的方法之一,其實就是網路的通訊,一般也稱為IPC (Interprocess Communication) ,不過IPC也包括在同一台主機上不同程序之間的溝通。 

各種常見的系統呼叫介面,RPCSocket是專供通訊之用的程序庫。

三種常見的IPCpipesemaphoreshared memorypipe是用來建立同一主機上兩個執行中的程式交換資料的管道,一般而言,一條pipe只提供單向的資料傳送。Shared Memory是作業系統特別分配的一部分主記憶體,讓多個程式共用;因此,這一部分主記憶體上的資料,就像放在公佈欄上面一樣。而Semaphore則是一個由作業系統保管的資料結構,用來調節共用資源的使用

pipe的使用限制於同一台電腦上同一個作業系統中,因此,pipe無法用於不同主機上程序之間的通訊。

處理元(process)是一種電腦要完成的工作(task),處理元在作業系統中是指執行中的程式,而且具有兩個明顯的特徵: 處理元可以擁有資源,處理元要經由作業系統排程執行。執行緒算是一種輕量級的處理元(lightweight process),是執行分派(dispatching)的單位,處理元則是資源擁有的單位。

多執行緒(multithreading)是指作業系統支援多個執行緒在同一個處理元中執行的功能,傳統上單一處理元單一執行緒的情況,等於沒有執行緒的觀念,可以稱為單一執行緒的方法(single-threaded approach)

執行緒具有下列的特徵:1.執行的狀態(execution state) 2.在沒有執行時與執行緒相關的資訊(thread context) 3.執行堆疊(execution stack) 4.每個執行緒存放區域變數(local variables)的靜態空間(static storage) 5.對於所屬處理元的記憶體與資源的使用要和其他的執行緒共享。

表示一個處理元,最簡單的方式就是包含PCBuser address spaceuser stackkernel stack,user stackkernel stack主要是用來處理process中呼叫與傳回的行為(call/return behavior) ,當處理元執行的時候,處理器的registers由該處理元控制,處理元停止執行時,registers的資料會儲存起來。

執行緒的使用有什麼好處呢?下面列出幾項從效能方面來觀察的優點:1.執行緒的產生需要的時間比處理元短,終止執行緒所需要的時間也比處理元短。2.在同一個處理元中的執行緒之間切換(switch)很快。3.不同處理元之間的溝通常需要作業系統核心(kernel)的參與,同一個處理元的執行緒之間的溝通就不需要讓kernel插手了,因此效率比較高。

執行緒的主要狀態包括執行(running),備妥(ready) 與阻絕(blocked) ,在執行緒的層次上沒有懸置(suspend)的概念,一旦處理元被置換出(swap out) ,執行緒一樣要被置換出,因為執行緒跟處理元共享同樣的位址空間。下面列出執行緒的基本作業:1.產生(spawn) : 通常當處理元產生的時候,會有一個執行緒也跟著產生。隨後這個執行緒會產生其他的執行緒。2.阻絕(block) : 當執行緒需要等待某個事件發生時,會先阻絕,也就是停止執行,user registersprogram counterstack pointers存起來,處理器轉移到其他的執行緒執行。3.阻絕解除(unblock) : 當執行緒所等待的事件發生以後,執行緒可以再度進入ready queue等待執行。4.完成(finish) : 執行緒完成執行以後,系統取回原來所分配的registerstack

先從一個遠端程序呼叫(RPCremote procedure calls)的例子來看執行緒在效能上能達到的優勢,圖2-15顯示一個程式在兩個遠端主機上執行RPCs,在單一執行緒的情況下,兩個RPCs會按順序執行,程式要分別等待兩個servers的回應,假如使用了執行緒,很顯然兩個RPCs能重疊進行,節省了不少等待的時間。

由於處理元中的執行緒共享相同的位址空間與其他的資源,執行緒對於這些資源的改變也會影響到同一個處理元中的其他執行緒,因此,這些執行緒的活動必須要有同步的管制(synchronization) ,這一部分需要考慮的觀念或是使用的技術跟處理元的同步問題類似。

執行緒的類別: 1. 使用者層次的執行緒(user-level threads) 2.. 核心層次的執行緒(kernel-level threads)

使用者執行緒的環境。單純的使用者執行緒的環境有兩個主要的缺點,由於作業系統中很多的系統呼叫都是阻絕呼叫,假如一個使用者執行緒進行系統呼叫造成阻絕,同一處理元的其他使用者執行緒也會阻絕。

最右邊顯示的是一種綜合的方式,Solaris作業系統就是採用這種方式。執行緒在使用者空間(user space)產生,多個使用者執行緒對應到數目不等的核心執行緒,這種方法使用恰當的話可以兼具上述兩種方法的優點。

Windows 2000在處理元的設計上希望能達到對於多種作業系統環境的支援,不同的作業系統環境所支援的處理元常會有一些差異,例如處理元的命名、處理元中是否含有執行緒、處理元的表示、處理元資源的保護、處理元之間的關係,以及處理元的溝通與同步等,所以Windows 2000對於處理元的原始架構與服務以簡易與通用為主,讓作業系統的子系統能模擬特定的處理元結構與功能。

Windows 2000的處理元具有下列的主要特徵:

1. Windows 2000的處理元以物件(objects)來表示。

2. 一個處理元可能包含一個或多個執行緒。

3. 處理元物件與執行緒物件。

Linux中的處理元是以一個叫做task_struct的資料結構來表示的,系統記錄一個task表格,有指標指向目前定義的task_struct資料結構,Linux的處理元有一個比較特殊的Zombie狀態,這是當處理元已經終止(terminated) ,但是task_structure仍然存在於process table中。Linux產生的新處理元可以和原處理元共享資源,假如兩個處理元共享同樣的虛擬記憶體空間,其實就像同一個處理元中的兩個執行緒,不過Linux沒有使用另外的結構來表示執行緒,所以Linux基本上沒有區分處理元與執行緒的觀念。

( 知識學習隨堂筆記 )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=ben168&aid=151207761