1. 程式人生 > 其它 >學習筆記6(必做)

學習筆記6(必做)

第3章 Unix/Linux程序管理

3.1 多工處理

多工處理指的是同時執行幾個獨立的任務。
在單處理器(單CPU)系統中,一次只能執行一個任務。
多工處理是通過在不同任務之間多路複用CPU的執行時間來實現的,即將CPU執行操作從一個任務切換到另一個任務。
不同任務之間的執行切換機制稱為上下文切換,將一個任務的執行環境更改為另一個任務的執行環境。如果切換速度足夠快,就會給人一種同時執行所有任務的錯覺。這種邏輯並行性成為“併發”。
在有多個CPU或處理器也可以通過同時執行不同的任務來實現多工處理。多工處理是所有作業系統的基礎。
總體來說,它是並行程式設計的基礎。

3.2 程序的概念

作業系統是一個多工處理系統。在作業系統中,任務也稱為程序。
在實際應用中,任務和程序這兩個術語可以互換使用。在第2章中,我們把執行映像定義為包含執行程式碼、資料和堆疊的儲存區。
程序的正式定義:

程序是對映像的執行。

作業系統核心將一系列執行視為使用系統資源的單一實體。系統資源包括記憶體空間、I/O裝置以及最重要的CPU時間。在作業系統核心中,每個程序用一個獨特的資料結構表示,叫作程序控制塊(PCB)或任務控制塊(執行緒控制塊)(TCB)等。在本書中,我們直接稱它為PROC結構體。與包含某個人所有資訊的個人紀錄一樣,PROC結構體包含某個程序的所有資訊。在實際作業系統中,PROC結構體可能包含許多欄位,而且數量可能很龐大。首先,我們來定義一個非常簡單的PROC結構體來表示程序。

typedef struct proc{
    struct proc *next;
    int *ksp;
    int pid;
    int ppid;
    int status;
    int priority;
    int kstack[1024];
} PROC;

在PROC結構體中,next是指向下一個PROC結構體的指標。ksp欄位是儲存的堆疊指標。當某程序放棄使用CPU時,它會將執行上下文儲存在堆疊中,並將堆疊指標儲存在PROC.ksp中,以便以後恢復。在PROC結構體的其他欄位中,pid是標識一個程序的程序ID編號,ppid是父程序ID編號,status是程序的當前狀態,priority是程序排程優先順序,kstack是程序執行時的堆疊。作業系統核心通常會在其資料區中定義有限數量的PROC結構體,表示為:

PROC proc[NPROC];       // NPROC a constant, e.g. 64

用來表示系統中的程序。在一個單CPU系統中,一次只能執行一個程序。作業系統核心通常會使用正在執行的或當前的全域性變數PROC指標,指向當前正在執行的PROC。在有多個CPU的多處理作業系統中,可在不同CPU上實時、並行執行多個程序。因此,在一個多處理器系統中正在執行的[NCPU]可能是一個指標陣列,每個指標指向一個正在特定CPU上執行的程序。為簡便起見,我們只考慮單CPU系統。

3.3 多工處理系統

多工處理系統,簡稱MT。

3.4 程序同步

一個作業系統包含許多併發程序,這些程序可以彼此互動。程序同步是指控制和協調程序互動以確保其正確執行所需的各項規則和機制。最簡單的程序同步工具是休眠和喚醒操作。

3.4.1 睡眠模式

當某程序需要某些當前沒有的東西時,例如申請獨佔一個儲存區域、等待使用者通過標準輸入來輸入字元等,它就會在某個事件值上進入休眠狀態,該事件值表示休眠的原因。為實現休眠操作,我們可在PROC結構體中新增一個event欄位,並實現ksleep(int event)函式,使得程序進入休眠狀態。

typedef struct proc{
    struct proc *next;
    int *ksp;
    int pid;
    int ppid;
    int status;
    int priority;
    int event;
    int exitCode;
    struct proc *child;
    struct proc *sibling;
    struct proc *parent;
    int kstack[1024];
} PROC;

ksleep()演算法為:

/****************** Algorithm of ksleep(int event) **********************/
1. record event value in PROC.event:    running->event = event;
2. change status to SLEEP;              running ->status = SLEEP;
3. for ease of maintencance, enter caller into a PROC *sleepList
                                        enqueue(&sleepList, running);
4.give up CPU;                          tswitch();

由於休眠程序不在readyQueue中,所以它在被另一個程序喚醒之前不可執行。因此,在讓自己進入休眠狀態之後,程序呼叫tswitch()來放棄使用CPU。

3.4.2 喚醒操作

多個進可能會進入休眠狀態等待同一個事件,這是很自然的,因為這些程序可能都需要同一個資源,例如一臺當前正處於繁忙狀態的印表機。在這種情況下,所有這些程序都將休眠等待同一個事件值。當某個等待時間發生時,另一個執行實體(可能是某個程序或中斷處理程式)將會呼叫kwakeup(event),喚醒正處於休眠狀態等待該事件值的所有程式。如果沒有任何程式休眠等待該程式,kwakeup()就不工作,即不執行任何操作。kwakeup()演算法是:

/****************** Algorithm of kwakeup(int event) **********************/
// Assume SLEEPing procs are in a global sleepList
for each PROC *p in a global sleepList
for each PROC *p in sleepList do{
    if (p->event == event){         // if p is sleeping for the event
        delete p from sleepList;
        p->status = READY;          // make p READY to run again
        enqueue(&readyQueue, p);    // enter p into readyQueue
    }
}

注意,被喚醒的程序可能不會立即執行。它只是被放入readyQueue中,排隊等待執行。
當被喚醒的程序執行時,如果它在休眠之前正在試圖獲取資源,那麼它必須嘗試重新獲取資源。這是因為該資源在它執行時可能不再可用。ksleep()和kwakeup()函式一般用於程序同步,但在特殊情況下也用於同步父程序和子程序,這是我們接下來要論述的主題。

3.5 程序終止

在作業系統中,程序可能終止或死亡,這是程序終止的通俗說法。如第2章所述,程序能以兩種方式終止:

  • 正常終止:程序呼叫exit(value),發出_exit(value)系統呼叫來執行在作業系統核心中的kexit(value),這就是我們本節要討論的情況。
  • 異常終止:程序因某個訊號而異常終止。訊號和訊號處理將在第六章討論。

在這兩種情況下,當程序終止時,最終都會在作業系統核心中呼叫kexit()。

3.5.1 kexit()的演算法

/****************** Algorithm of kexit(int exitValue) **********************/
1. Erase process user-mode context, e.g. close file descriptors,
    release resources, deallocate user-mode image memory, etc.
2. Dispose of children processes, if any
3. Record exitValue in PROC.exitCode for parent to get
4. Become a ZOMBIE (but do not free the PROC)
5. Wakeup parent and, if needed, also the INIT process P1
———————————————————————————————————————————————————————————————— 轉載麻煩附上本文連結和本宣告,感謝! 博主<葉家星>部落格園連結如下:https://www.cnblogs.com/yejiaxing-01/