程序、行程(process)
行程是操作系統結構的基礎;是一次程序的執行;是一個程序及其數據在處理機上順序執行時所發生的活動;是程序在一個數据集合上運行的過程,它是系统進行資源分配和調度的一個獨立單位。
當一個程式在電腦執行時會先向系統進行註冊,讓系統將這個程式記錄在它的執行清單上,系統此時會將這程序標上一個唯一的ID以作為區別,即PID(Process ID),並分配適當的資源給這個程式來進行工作,這些資源包含CPU的使用權以及獨立的資料儲存空間,我們稱此動作為建立一個處理程序(process)。每個程序所擁有的資源在執行期間是獨佔的,不與其它程序共用,所以每個程序只能存取屬於自己的部份,不能直接去更改其它程序的資料,如果程序間需要交流,必須建立通訊的管道才能交換情報。另外,因為CPU的數目有限而待執行的程序可能有很多個,因此系統會為每個程序規劃出一段CPU使用時間,在這段時間內分配給這個程序的CPU就專屬於該程序而不會去處理其它程序的工作。
行程的概念主要有兩點:
- 行程是一個實體。每一個行程都有它自己的地址空間,一般情况下,包括文本區域(text region)、數据區域(data region)和堆栈(stack region)。
- 文本區域存儲處理器執行的代碼;
- 數据區域存儲變量和行程執行期間使用的動態分配的内存;
- 堆棧區域存儲著活動過程調用的指令和本地變量。
- 行程是一個“執行中的程序”。程序是一個有生命的實體,只有處理器賦予程序生命時,它才能成為一個活動的實體,我们稱其為行程。
- 行程是一個實體。每一個行程都有它自己的地址空間,一般情况下,包括文本區域(text region)、數据區域(data region)和堆栈(stack region)。
process:將程式(program)載入記憶體中,變成可執行的process。
- thread:一個process可以產生多個thread。
- process 之間的address space並不相同,thread則共用相同的address space。
- 行程指的是正在執行的程式。
- 行程不只是程式碼 ,有時也稱為本文區(text section)。
- 它包含代表目前運作的程式計數器 (program counter)數值和處理器(processor)的暫存器(registrers)內容。
- 行程堆疊 (stack):存放暫用資料 (副程式的參數、返回位址,及暫時性變數)
- 資料區間(data section):包含全域變數(global variables)
- 堆積 (heap):堆積就是在行程執行期間動態配置的記憶體。
行程狀態(Process State)
- 一個行程的生命期可以劃分為一組狀態,系統根據PCB結構中的狀態值控制行程。行程在生命消失前處於且僅處於三種基本狀態之一。
- 行程的基本狀態有三種:就緒、執行、等待(阻塞)。
- 就緒狀態:當行程已分配到除CPU以外的所有必要資源後,只要在獲得CPU,便可立即執行,行程這時的狀態稱為就緒狀態。處於該狀態的行程構成緒列隊。
- 執行狀態:行程正在處理器上運行的狀態,該行程已獲得必要的資源,也獲得了處理器,用戶程序正在處理器上運行。
- 等待(阻塞)狀態:正在執行的行程由於發生某事件而暫時無法繼續執行時,變放棄處理器而處於暫停狀態,即行程的執行收到阻塞,成為阻塞狀態,也成為等待狀態。
- 行程在執行時會改變其狀態。行程的狀態 (state)部份是指該行程目前的動作,每一個行程可能會處於以下數種狀態之一:
- 新產生(new):該行程正在產生中。
- 執行(running):指令正在執行。
- 等待(waiting):等待某件事件的發生(譬如輸出入完成或接收到一個信號)。
- 就绪(ready):該行程正等待指定一個處理器。
- 结束(terminated):該行程完成執行。
行程控制表(Process Control Block (PCB))
- 每一個行程在作業系統之中都對應著一個行程控制表 (Process control block (PCB))也可稱為任務控制表 (task control block)
- 行程狀態(Process state):running、waiting
- 程式計數器(Program counter):指出行程接著要執行的指令位址
- CPU暫存器(CPU registers):所有暫存器內容
- CPU排班法則相關資訊(CPU scheduling information):行程的優先順序 (Priorities)、排班佇列(scheduling queue)指標以及其它的排班參數
- 記憶體管理資訊(Memory-management information):分配給行程的記憶體
- 帳號資訊(Accounting information):CPU和實際時間的使用數量、時限、帳號工作或行程號碼。
- 輸入/輸出狀態資訊(I/O status information):配置給行程的輸入/輸出裝置,開啟檔案的串列
創建行程
- 在多道程序環境中,只有(作為)行程(時)才能在系統中運行。因此,為使程序能運行,就必須為它創建行程。導致一個行程去創建另一個行程的典型事件,可以有以下四類:
- 用戶登錄
- 在分時系統中,用戶在終端鍵入登錄命令後,如果是合法用戶,系統將為該終端建立一個行程,並把它插入到就緒隊列中。
- 作業調度
- 在批處理系統中,當作業調度程序按照一定的算法調度到某作業時,便將該作業裝入到內存,為它分配必要的資源,並立即為它創建行程,再插入到就緒隊列中。
- 提供服務
- 當運行中的用戶程序提出某種請求後,系統將專門創建一個行程來提供用戶所需要的服務,例如,用戶程序要求進行文件打印,操作系統將為它創建一個打印行程,這樣,不僅可以使打印行程與該用戶行程並發執行,而且還便於計算出為完成打印任務所花費的時間。
- 應用請求
- 在上述三種情況中,都是由系統內核為它創建一個新行程,而這一類事件則是基於應用行程的需求,由它創建一個新的行程,以便使新行程以並發的運行方式完成特定任務。
- 用戶登錄
行程的創建過程
- 一旦操作系統發現了要求創建新行程的事件後,便調用行程創建API按下述步驟創建一個新行程。
- 申請空白PCB。為新行程申請獲得唯一的數字標識符,並從PCB集合中索取一個空白PCB。
- 為新行程分配資源。為新行程的程序和數據以及用戶棧分配必要的內存空間。顯然,此時操作系統必須知道新行程所需要的內存大小。
- 初始化行程控制塊。 PCB的初始化包括:
- 始化標識信息,將系統分配的標識符和父行程標識符,填入新的PCB中。
- 始化處理機狀態信息,使程序計數器指向程序的入口地址,使棧指針指向棧頂。
- 始化處理機控制信息,將行程的狀態設置為就緒狀態或靜止就緒狀態,對於優先級,通常是將它設置為最低優先級,除非用戶以顯式的方式提出高優先級要求。
- 將新行程插入就緒隊列,如果行程就緒隊列能夠接納新行程,便將新行程插入到就緒隊列中。
行程终止
- 引起行程终止的事件
- 正常結束
- 在任何計算機系統中,都應該有一個表示行程已經運行完成的指示。例如,在批處理系統中,通常在程序的最後安排一條Hold指令或終止的系統調用。當程序運行到Hold指令時,將產生一個中斷,去通知OS本行程已經完成。
- 異常結束
- 在行程運行期間,由於出現某些錯誤和故障而迫使行程終止。這類異常事件很多,常見的有:越界錯誤,保護錯,非法指令,特權指令錯,運行超時,等待超時,算術運算錯,I/O故障。 +外界干預
- 外界干預並非指在本行程運行中出現了異常事件,而是指行程應外界的請求而終止運行。這些干預有:操作員或操作系統干預,父行程請求,父行程終止。
- 正常結束
行程的终止過程
- 如果系統發生了上述要求終止行程的某事件後,OS便調用行程終止原語,按下述過程去終止指定的行程。
- 根據被終止行程的標識符,從PCB集合中檢索出該行程的PCB,從中讀出該行程狀態。
- 若被終止行程正處於執行狀態,應立即終止該行程的執行,並置調度標誌為真。用於指示該行程被終止後應重新進行調度。
- 若該行程還有子孫行程,還應將其所有子孫行程予以終止,以防他們成為不可控的行程。
- 將被終止的行程所擁有的全部資源,或者歸還給其父行程,或者歸還給系統。
- 將被終止行程(它的PCB)從所在隊列(或鍊錶)中移出,等待其它程序來蒐集信息。
等待(阻塞)喚醒
- 引起行程等待(阻塞)和喚醒的事件
- 請求系統服務
- 當正在執行的行程請求操作系統提供服務時,由於某種原因,操作系統並不立即滿足該行程的要求時,該行程只能轉變為阻塞狀態來等待,一旦要求得到滿足後,行程被喚醒。
- 啟動某種操作
- 當行程啟動某種操作後,如果該行程必須在該操作完成之後才能繼續執行,則必須先使該行程阻塞,以等待該操作完成,該操作完成後,將該行程喚醒。
- 新數據尚未到達
- 對於相互合作的行程,如果其中一個行程需要先獲得另一(合作)行程提供的數據才能運行以對數據進行處理,則是要其所需數據尚未到達,該行程只有(等待)阻塞,等到數據到達後,該行程被喚醒。
- 無新工作可做
- 系統往往設置一些具有某特定功能的系統行程,每當這種行程完成任務後,便把自己阻塞起來以等待新任務到來,新任務到達後,該行程被喚醒。
- 請求系統服務
行程阻塞過程
- 正在執行的行程,當發現上述某事件後,由於無法繼續執行,於是行程便通過調用阻塞原語block把自己阻塞。可見,行程的阻塞是行程自身的一種主動行為。進入block過程後,由於此時該行程還處於執行狀態,所以應先立即停止執行,把行程控制塊中的現行狀態由執行改為阻塞,並將PCB插入阻塞隊列。如果系統中設置了因不同事件而阻塞的多個阻塞隊列,則應將本行程插入到具有相同事件的阻塞(等待)隊列。最後,轉調度程序進行重新調度,將處理機分配給另一就緒行程,並進行切換,亦即,保留被阻塞行程的處理機狀態(在PCB中),再按新行程的PCB中的處理機狀態設置CPU環境。
行程喚醒過程
- 當被阻塞的行程所期待的事件出現時,如I/O完成或者其所期待的數據已經到達,則由有關行程(比如,用完並釋放了該I/O設備的行程)調用喚醒原語wakeup(),將等待該事件的行程喚醒。喚醒原語執行的過程是:首先把被阻塞的行程從等待該事件的阻塞隊列中移出,將其PCB中的現行狀態由阻塞改為就緒,然後再將該PCB插入到就緒隊列中。
執行緒(thread)
執行緒是系統處理工作的基本單元,通常一個CPU在同一時間只能提供一個執行緒(在此不考慮Hyper-Threading技術),讓系統調用去執行程式。程序跟執行緒間的關係我們可以把它想像成是工廠與員工的關係,工廠擁有資源與設備但需要由員工去操作才能生產產品,所以要做出一件成品,工廠內至少要有一位員工在做事,不同的程序就像是不同的工廠,而執行緒像是一位派遣員工一樣,由作業系統負責調度他在什麼時間該去那家工廠上班,如果電腦擁有多個處理核心,即代表系統可以同時調用多個員工。
Thread存在有以下的目的:
- Responsiveness: 響應度高:一個多線程的應用在執行中,即使其中的某個線程堵塞,其他的線程還可繼續執行,從而提高響應速度。
- 例如允許程式可以在被I/O中斷時,能夠繼續執行,譬如Web瀏覽器,可以同時看影片及下載檔案
- Resource Sharing: thread分享同樣的memory和resource,而process只能透過shared memory和message passing的方法來分享資料
- Economy: thread比process輕巧,創建和context switch thread比創建一個process來的快速
- Scalability: 可以平行執行於多核心的平台
- Responsiveness: 響應度高:一個多線程的應用在執行中,即使其中的某個線程堵塞,其他的線程還可繼續執行,從而提高響應速度。
多執行緒(multi-threading)
延續剛剛工廠、員工的比喻,系統可以同時間內把多個員工派到同一家工廠去工作,此法稱做多執行緒(multi-threading)平行執行,相較於單一執行緒處理方式,它有機會讓工作在比較短的時間內完成,多執行緒工作時,隸屬同一程序下的所有執行緒會分享該程序的所有資源,此外各執行緒彼此間也可以擁有自己私有的資源,而不與其它同一程序內的執行緒共用。這就像是工廠內的公共設備是所有員工可以自由使用一樣,但每個員工也都會有自己的工作空間與置物櫃可以擺放自己私人的物品。
用戶執行緒(User Threads)和內核執行緒(Kernel Threads)
- 用戶執行緒——由用户级執行緒库进行管理
- 三個主要用戶執行緒:
- POSIX Pthreads
- Windows執行緒
- Java 執行緒
- 內核執行緒——由内核支持
- 內核執行緒的例子:
- Windows
- Solaris
- Linux
- Mas OS X
多執行緒模型(Mutithreading Models)
多對一(Many-to-One)模型
- 多對一個模型的實現(許多用戶線程到一個內核線程)允許應用程序創建任意數量可以並發執行的線程。在一個多到一(用戶級線程)執行,所有線程的活動僅限於用戶空間。
- 此外,只有一個線程時可以訪問內核,所以只有一個調度實體是已知的操作系統。因此,這種多線程模型提供有限的並發性和不利用多處理器。
一對一(One-to-One)模型
- 一對一模型(一個用戶線程1內核線程)是真實的多線程的最早的實現中。
- 在這個實現中,由應用程序創建的每個用戶級線程被稱為內核,並且所有線程可以同時訪問內核。
- 這種模式的主要問題是,它將會限制使用者要小心,節儉與線程,因為每個額外的線程增加了更多的“權重”的過程。
多對多(Many-to-Many)模型
- 一個many- to-many的實現在用戶級別上降低了編程的工作量。