1. 程式人生 > >作業系統3 ————PCB和程序控制

作業系統3 ————PCB和程序控制

作業系統3 ————程序控制塊(PCB)詳解

一.目錄

二. 程序控制塊

1.概述

程序控制塊(Processing Control Block),是作業系統核心中一種資料結構,主要表示程序狀態,其作用是使一個程式成為一個能夠獨立執行的基本單位,並且可以併發執行的程序。或者說,OS是根據PCB來對併發執行的程序進行控制和管理。PCB通常是佔用系統記憶體中一塊連續的記憶體空間,存放著作業系統用於描述程序情況及控制程序執行的全部資訊。

2.程序控制塊中的資訊

a.程序識別符號

  • 內部識別符號:作業系統為每一個程序賦予的唯一數字識別符號,系統使用
  • 外部識別符號:由建立者提供,通常有字母與數字組成,往往是由使用者(程序)在訪問該程序時使用。描述程序的家族關係,設定父程序標識及子程序標識,還可設定使用者標識,以指示擁有該程序的使用者。

b.處理機狀態

  • 主要是由處理機的各種暫存器中的內容組成的,處理機被中斷時,所有這些資訊都必須儲存在PCB中,以便在該程序重新執行時,能從斷點繼續執行。 這些暫存器包括: 通用暫存器、指令計數器、程式狀態字PSW、使用者棧指標

c.程序排程資訊

  • 程序狀態
  • 程序優先順序
  • 程序排程所需要的其他資訊,比如已等待CPU的時間綜合,程序一直想的時間總和。
  • 事件,指程序由執行狀態轉變為阻塞狀態所等待發生的事件,即阻塞原因

d.程序控制資訊

  • 程式和資料的地址
  • 程序同步和通訊機制
  • 資源清單
  • 連結指標

3.程序控制塊的作用

PCB 可以被作業系統中的多個模組讀或修改,如被排程程式、資源分配 程式、中斷處理程式以及監督和分析程式等讀或修改。 OS是根據 PCB來對 併發執行的程序進行控制和管理,所以說PCB是作業系統中最重要的記錄型資料結構 其作主要作用如下:

1、作為獨立執行基本單位的標誌 2、能實現間斷性執行方式 3、提供程序管理所需要的資訊 4、提供程序排程所需要的資訊 5、實現與其他程序的同步與通訊

4.程序控制塊的組織方式

a.線性方式: 即將系統中所有的PCB都組長在一張線性表中,將該表的首地址存放在記憶體的一個專用區域中。適合於系統中程序數目不多的情況 這裡寫圖片描述 **b.連結方式:**該方式是線性表方式的改進,系統按照程序的狀態分別建立就緒索引表、阻塞索引表等。 這裡寫圖片描述 **c.索引方式:**系統按照程序的狀態將程序的PCB組成佇列,從而形成就緒佇列、阻塞佇列、執行佇列等。 這裡寫圖片描述

三.Linux的程序控制塊

1.概述

Linux的程序控制塊為一個由結構task_struct所定義的資料結構,task_struct存於/include/linux/sched.h 中,其中包括管理程序所需的各種資訊。它會被裝載到RAM⾥並且包含著程序的資訊。所有執行在系統裡的程序都以task_struct連結串列的形式存在核心裡。

2.task_struct資料結構簡述



    struct task_struct  

    {  

        long state; /*任務的執行狀態(-1 不可執行,0 可執行(就緒),>0 已停止)*/  

        long counter;/*執行時間片計數器(遞減)*/  

        long priority;/*優先順序*/  

        long signal;/*訊號*/  

        struct sigaction sigaction[32];/*訊號執行屬性結構,對應訊號將要執行的操作和標誌資訊*/  

        long blocked; /* bitmap of masked signals */  

        /* various fields */  

        int exit_code;/*任務執行停止的退出碼*/  

        unsigned long start_code,end_code,end_data,brk,start_stack;/*程式碼段地址 程式碼長度(位元組數) 

                                        程式碼長度 + 資料長度(位元組數)總長度 堆疊段地址*/  

        long pid,father,pgrp,session,leader;/*程序標識號(程序號) 父程序號 父程序組號 會話號 會話首領*/  

        unsigned short uid,euid,suid;/*使用者標識號(使用者id) 有效使用者id 儲存的使用者id*/  

        unsigned short gid,egid,sgid; /*組標識號(組id) 有效組id 儲存的組id*/  

        long alarm;/*報警定時值*/  

        long utime,stime,cutime,cstime,start_time;/*使用者態執行時間 核心態執行時間 子程序使用者態執行時間 

                               子程序核心態執行時間 程序開始執行時刻*/  

        unsigned short used_math;/*標誌:是否使用協處理器*/  

        /* file system info */  

        int tty; /* -1 if no tty, so it must be signed */  

        unsigned short umask;/*檔案建立屬性遮蔽位*/  

        struct m_inode * pwd;/*當前工作目錄i 節點結構*/  

        struct m_inode * root;/*根目錄i節點結構*/  

        struct m_inode * executable;/*執行檔案i節點結構*/  

        unsigned long close_on_exec;/*執行時關閉檔案控制代碼點陣圖標誌*/  

        struct file * filp[NR_OPEN];/*程序使用的檔案表結構*/  

        /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */  

        struct desc_struct ldt[3];/*本任務的區域性描述符表。0-空,1-程式碼段cs,2-資料和堆疊段ds&ss*/  

        /* tss for this task */  

        struct tss_struct tss;/*本程序的任務狀態段資訊結構*/  

    };  

四.Unix的程序控制塊

1.概述

在UNIX系統Ⅴ中,把程序控制塊(PCB)分為四部分:

  • 程序表項,其中包括最常用的核心資料。
  • U區,用於存放使用者程序表項的一些擴充資料。
  • 系統區表,存放各個區在物理儲存器中的地址資訊等。
  • 程序區表,用於存放各區的起始虛地址及指向系統區表中對應區表項的指標。

2.程序表項(Proc表)

用於描述和控制一個程序的資訊通常都很多,其中有些是經常要被訪問的,如程序識別符號、程序狀態等。為了提高對這些資訊訪問的效率,系統設計者將這些資訊放在程序表項中,又稱之為Proc表或Proc結構,使之常駐記憶體。在每個程序表項中,含有下述一些具體資訊:

  1. 程序識別符號(PID),也稱內部識別符號,為方便使用者使用,這裡惟一地標識一個程序的某個整數。
  2. 使用者識別符號(UID),標識擁有該程序的使用者。
  3. 程序狀態,表示該程序的當前狀態。
  4. 事件描述符,記錄使程序進入睡眠狀態的事件。
  5. 程序和U區在記憶體或外存的地址,核心可利用這些資訊做上、下文切換。
  6. 軟中斷資訊,記錄其它程序發來的軟中斷訊號。
  7. 計時域,給出程序的執行時間和對資源的利用情況。
  8. 程序的大小,這是核心在為程序分配儲存空間時的依據,包括正文段長度和棧段長度等。
  9. 偏置值nice,供計算該程序的優先數時使用,可由使用者設定。
  10. P_Link指標,這是指向就緒佇列中下一個PCB的指標。
  11. 指向U區程序正文、資料及棧在記憶體區域的指標。

3.U區

為了存放用於描述和控制程序的另一部分資訊,系統為每一個程序設定了一個私用的U區,又稱之為User結構,這部分資料並非常駐記憶體,其中含有下述資訊:

  1. 程序表項指標,指向當前(正在執行)程序的程序表項。
  2. 真正使用者識別符號u-ruid(real user ID),這是由超級使用者分配給使用者的識別符號,以後,每次使用者在登入進入系統時,均須輸入此識別符號。
  3. 有效使用者識別符號u-euid(effective user ID),在一般情況下,它與ruid相同,但在其他使用者允許的情況下,可用系統呼叫setuid將它改變為其他使用者識別符號,以獲得對該使用者的檔案進行操作的權力。
  4. 使用者檔案描述符表,其中記錄了該程序已開啟的所有檔案。
  5. 當前目錄和當前根,用於給出程序的檔案系統環境。
  6. 計時器,記錄該程序及其後代在使用者態和核心態執行的時間。
  7. 內部I/O引數,給出要傳輸的資料量、源(或目標)資料的地址、檔案的輸入/輸出偏移量。
  8. 限制欄位,指對程序的大小及其能“寫”的檔案大小進行限制。
  9. 差錯欄位,記錄系統呼叫執行期間所發生的錯誤。
  10. 返回值,指出系統呼叫的執行結果。
  11. 訊號處理陣列,用於指示在接收到每一種訊號時的處理方式。

4.系統區表

系統V把一個程序的虛地址劃分為若干個連續的區域:正文區,資料區,棧區。這些去是可被共享和保護的獨立實體,多個程序可以共享一個區,例如,多程序共享一個正文區,即幾個程序將執行同一個(子)程式。同樣,多個程序也可以進行共享一個數據區。為了對區進行管理。在核心設定了一個系統區表。在各表項中記錄了以下有關描述活動區的資訊:

  1. 區的型別和大小。
  2. 區的狀態。一個區有這樣幾種狀態: 鎖住、在請求中、在裝入過程、有效(區已裝入記憶體)。
  3. 區在物理儲存器中的位置。
  4. 引用計數,即共享該區的程序數。
  5. 指向檔案索引結點的指標。

5.程序區表

為了記錄程序的每個區在程序中的虛地址,並通過它找到該區在物理儲存器中的實地址,系統為每個程序配置了一張程序區表。表中的每一項記錄一個區的起始虛地址及指向系統區表中對應的區表項的指標。這樣,核心可通過查詢程序區表和系統區表,將區的邏輯地址變換為實體地址。可見,程序區表和系統區表用於對區地址進行映像(射)。這裡用兩張區表實現地址對映,是為了便於實現對區的共享。

五.windows的程序控制塊

1.概述

在windows中執程序控制塊是由 EPROCESS 塊來表示的。 EPROCESS 塊位於核心層之上,它側重於提供各種管理策略,同時為上層應用程式提供基本的功能介面。所以,在執行體層的程序和執行緒資料結構中,有些成員直接對應於上層應用程式中所看到的功能實體。

2.EPROCESS的資料結構

typedef struct _EPROCESS 
{
    KPROCESS Pcb;  //KPROCESS被核心用來進行執行緒排程使用

    EX_PUSH_LOCK ProcessLock;//ProcessLock域是一個推鎖(push lock)物件,用於保護EPROCESS中的資料成員。用來對可能產生的並行事件強制序列化。

    LARGE_INTEGER CreateTime; //這兩個域分別代表了程序的建立時間和退出時間
    LARGE_INTEGER ExitTime; 

    EX_RUNDOWN_REF RundownProtect; //RundownProtect域是程序的停止保護鎖,當一個程序到最後被銷燬時,它要等到所有其他程序和執行緒已經釋放了此鎖,才可以繼續進行,否則就會產生孤兒執行緒

    HANDLE UniqueProcessId;  //UniqueProcessId域是程序的唯一編號,在程序建立時就設定好了,我們在"工作管理員"中看到的PID就是從這個域中獲取的值

    LIST_ENTRY ActiveProcessLinks; //ActiveProcessLinks域是一個雙鏈表節點(注意是雙鏈表中的一個節點),在windows系統中,所有的活動程序都連線在一起,構成了一個連結串列。

    SIZE_T QuotaUsage[PsQuotaTypes];//QuotaUsage和QuotaPeak域是指一個程序的記憶體使用量和尖峰使用量
    SIZE_T QuotaPeak[PsQuotaTypes];
    
    SIZE_T CommitCharge; //CommitCharge域中儲存了一個程序的虛擬記憶體已提交的"頁面數量"
    SIZE_T PeakVirtualSize;//PeakVirtualSize域是指虛擬記憶體大小的尖峰值。
    SIZE_T VirtualSize;//VirtualSize域是指一個程序的虛擬記憶體大小。

    LIST_ENTRY SessionProcessLinks;//SessionProcessLinks域是一個雙鏈表節點,當程序加入到一個系統會話中時,這個程序的SessionProcessLinks域將作為一個節點(LIST_ENTRY在核心中很常見)加入到該會話的程序連結串列中。

    PVOID DebugPort; //DebugPort和ExceptionPort域是兩個控制代碼(指標),分別指向當前程序對應的除錯埠和異常埠。
    PVOID ExceptionPort;
    
    PHANDLE_TABLE ObjectTable; //ObjectTable域是當前程序的控制代碼表。

    EX_FAST_REF Token; //Token域是一個快速引用,指向該程序的訪問令牌,用於該程序的安全訪問檢查。

    PFN_NUMBER WorkingSetPage;  //WorkingSetPage域是指包含程序工作集的頁面
    KGUARDED_MUTEX AddressCreationLock;//AddressCreationLock域是一個守護互斥體鎖(guard mutex),用於保護對地址空間的操作。
    KSPIN_LOCK HyperSpaceLock;//HyperSpaceLock是一個自旋鎖,用於保護程序的超空間

    struct _ETHREAD *ForkInProgress;//ForkInProgress指向正在複製地址空間的那個執行緒,僅當在地址空間複製過程中,此域才會被賦值,在其他情況下為NULL。
    ULONG_PTR HardwareTrigger;//HardwareTrigger用於記錄硬體錯誤效能分析次數

    PMM_AVL_TABLE PhysicalVadRoot;//PhysicalVadRoot域指向程序的物理VAD的根。它並不總是存在,只有當確實需要對映實體記憶體時才會被建立。
    PVOID CloneRoot;//CloneRoot指向一個平衡樹的根,當程序地址空間複製時,此樹被建立,創建出來後,一直到程序退出的時候才被銷燬。CloneRoot域完全是為了支援fork語義而引入。
    PFN_NUMBER NumberOfPrivatePages;//指程序私有頁面的數量
    PFN_NUMBER NumberOfLockedPages;//指程序被鎖住的頁面的數量
    PVOID Win32Process;//Win32Process域是一個指標,指向由windows子系統管理的程序區域,如果此值不為NULL,說明這是一個windows子系統程序(GUI程序)
    struct _EJOB *Job;//對於job域,只有當一個程序屬於一個job(作業)的時候,它才會指向一個_EJOB物件。
    PVOID SectionObject;//SectionObject域也是一個指標,代表程序的記憶體去物件(程序的可執行映像檔案的記憶體區物件)

    PVOID SectionBaseAddress;// SectionBaseAddress域為該記憶體區物件的基地址

    PEPROCESS_QUOTA_BLOCK QuotaBlock;//QuotaBlock域指向程序的配額塊,程序的配額塊型別為: EPROCESS_QUOTA_BLOCK

    PPAGEFAULT_HISTORY WorkingSetWatch;//WorkingSetWatch域用於監視一個程序的頁面錯誤,一旦啟用了頁面錯誤監視功能(由全域性變數PsWatchEnabled開關來控制),則每次發生頁面錯誤都會將該頁面錯誤記錄到WorkingSetWatch域的WatchInfo成員陣列中,知道陣列滿為止。
    HANDLE Win32WindowStation;//Win32WindowStation域是一個程序所屬的視窗站的控制代碼。由於控制代碼的值是由每個程序的控制代碼表來決定的,所以,兩個程序即使同屬於一個視窗站,它們的Win32WindowStation也可能不同,但指向的視窗站物件是相同的。視窗站是由windows子系統來管理和控制的。
    HANDLE InheritedFromUniqueProcessId;//InheritedFromUniqueProcessId域說明了一個程序是從哪裡繼承來的,即父程序的識別符號。

    PVOID LdtInformation;//LdtInformation用來維護一個程序的LDT(區域性描述符表)資訊。
    PVOID VadFreeHint;//VadFreeHint域指向一個提示VAD(虛擬地址描述符)節點,用於加速在VAD樹中執行查詢操作。
    PVOID VdmObjects;//VdmObjects域指向當前程序的VDM資料區,其型別為VMD_PROCESS_OBJECTS,程序可通過NtVdmControl系統服務來初始化VDM。
    PVOID DeviceMap;//DeviceMap域指向程序使用的裝置表,通常情況下同一個會話中的程序共享同樣的裝置表。

    PVOID Spare0[3];//Spare0域是一個備用域
    union //頁表項
    {
        HARDWARE_PTE PageDirectoryPte;
        ULONGLONG Filler;
    };
    PVOID Session;//Session指向程序所在的系統會話,實際上它是一個指向MM_SESSION_SPACE的指標。\base\ntos\mm\mi.h 中相關的結構體定義
    UCHAR ImageFileName[ 16 ];//ImageFileName域包含了程序的映像檔名,僅包含最後一個路徑分隔符之後的字串,不超過16位元組。

    LIST_ENTRY JobLinks;//JobLinks域是一個雙鏈表節點,通過此節點,一個job中的所有程序構成了一個連結串列。在windows中,所有的job構成了一個雙鏈表,其連結串列頭為全域性變數PspJobList。每個job中的程序又構成了一個雙鏈表。
    PVOID LockedPagesList;//LockedPagesList域是一個指向LOCK_HEADER結構的指標,該結構包含了一個連結串列頭,windows通過此連結串列來記錄哪些頁面已被鎖住(這裡所謂的鎖住和Mdll中的對映機制有關,本質上就是把使用者空間下的記憶體地址鎖定到核心空間中以便訪問)

    LIST_ENTRY ThreadListHead; //ThreadListHead域是一個雙鏈表的"頭結點",該連結串列中包含了一個程序中的所有"執行緒"。

    PVOID SecurityPort; //SecurityPort域是一個安全埠,指向該程序域lsass.exe程序之間的跨程序通訊埠。
    PVOID PaeTop; //PaeTop域用於支援PAE記憶體訪問機制。

    ULONG ActiveThreads;//ActiveThreads域記錄了當前程序有多少活動執行緒。當該值減為0時,所有的執行緒將退出,於是程序也退出。

    ACCESS_MASK GrantedAccess;//GrantedAccess域包含了程序的訪問許可權,訪問許可權是一個"位組合"。 public\sdk\inc\ntpsapi.h 中的巨集 PROCESS_XXX

    ULONG DefaultHardErrorProcessing;//DefaultHardErrorProcessing域指定了預設的硬體錯誤處理,預設為1

    NTSTATUS LastThreadExitStatus; //LastThreadExitStatus域記錄了剛才最後一個執行緒的退出狀態。

    PPEB Peb; //Peb域是一個程序的"程序環境塊

    EX_FAST_REF PrefetchTrace;//PrefetchTrace域是一個快速引用,指向與該程序關聯的一個"預取痕跡結構",以支援該程序的預取。
    LARGE_INTEGER ReadOperationCount;//ReadOperationCount,WriteOperationCount記錄了當前程序NtReadFile和NtWriteFile系統服務被呼叫的次數,OtherOperationCount記錄了除讀寫操作以外的其他IO服務的次數(檔案資訊設定.)
    LARGE_INTEGER WriteOperationCount;
    LARGE_INTEGER OtherOperationCount;
    LARGE_INTEGER ReadTransferCount;//ReadTransferCount,WriteTransferCount記錄了IO讀寫操作"完成"的次數,OtherTransferCount記錄了除讀寫操作以外操作完成的次數。
    LARGE_INTEGER WriteTransferCount;
    LARGE_INTEGER OtherTransferCount;

    SIZE_T CommitChargeLimit;
    SIZE_T CommitChargePeak;

    PVOID AweInfo; //AweInfo域是一個指向AWEINFO結構的指標,其目的是支援AWE(Adress Windowing Extension 地址視窗擴充套件)

    SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo;//SeAuditProcessCreationInfo域包含了建立程序時指定的程序映像全路徑名

    MMSUPPORT Vm;//Vm域是windows為每個程序管理虛擬記憶體的重要資料結構成員,其型別為MMSUPPORT, \base\ntos\inc\ps.h 中有相關定義
 
    LIST_ENTRY MmProcessLinks; //MmProcessLinks域代表一個雙鏈表節點,所有擁有自己地址空間的程序都將加入到一個雙鏈表中,連結串列頭是全域性變數MmProcessList

    ULONG ModifiedPageCount; //ModifiedPageCount域記錄了該程序中已修改的頁面的數量,即"髒頁面數量",這和快取的讀寫有關。

    ULONG JobStatus; //49. ULONG JobStatus

JobStatus域記錄了程序所屬job的狀態。
 
    union //Flags域包含了程序的標誌位,這些標誌位反映了程序的當前狀態和配置。  \base\ntos\inc\ps.h 中的巨集定義 PS_PROCESS_FLAGS_XXX
    { 
        ULONG Flags; 

        struct {
            ULONG CreateReported            : 1;
            ULONG NoDebugInherit            : 1;
            ULONG ProcessExiting            : 1;
            ULONG ProcessDelete             : 1;
            ULONG Wow64SplitPages           : 1;
            ULONG VmDeleted                 : 1;
            ULONG OutswapEnabled            : 1;
            ULONG Outswapped                : 1;
            ULONG ForkFailed                : 1;
            ULONG Wow64VaSpace4Gb           : 1;
            ULONG AddressSpaceInitialized   : 2;
            ULONG SetTimerResolution        : 1;
            ULONG BreakOnTermination        : 1;
            ULONG SessionCreationUnderway   : 1;
            ULONG WriteWatch                : 1;
            ULONG ProcessInSession          : 1;
            ULONG OverrideAddressSpace      : 1;
            ULONG HasAddressSpace           : 1;
            ULONG LaunchPrefetched          : 1;
            ULONG InjectInpageErrors        : 1;
            ULONG VmTopDown                 : 1;
            ULONG ImageNotifyDone           : 1;
            ULONG PdeUpdateNeeded           : 1;    // NT32 only
            ULONG VdmAllowed                : 1;
            ULONG SmapAllowed               : 1;
            ULONG CreateFailed              : 1;
            ULONG DefaultIoPriority         : 3;
            ULONG Spare1                    : 1;
            ULONG Spare2                    : 1;
        };
    };

    NTSTATUS ExitStatus;//ExitStatus域包含了程序的退出狀態,從程序的退出狀態通常可以獲知程序非正常退出的大致原因。反映退出狀態的一些巨集定義位於 public\sdk\inc\ntstatus.h

    USHORT NextPageColor;//NextPageColor域用於物理頁面分配演算法。
    union 
    {
        struct 
    {
            UCHAR SubSystemMinorVersion;
            UCHAR SubSystemMajorVersion;
        };
        USHORT SubSystemVersion;
    };
    UCHAR PriorityClass;//PriorityClass域是一個單位元組值,它說明了一個程序的優先順序程度

    MM_AVL_TABLE VadRoot;//VadRoot域指向一個平衡二叉樹的根,用於管理該程序的虛擬地址空間。

    ULONG Cookie;//Cookie域存放的是一個代表該程序的隨機值,當第一次通過NtQueryInformationProcess函式獲取此Cookie值的時候,系統會生成一個隨機值,以後就用此值代表此程序

} EPROCESS, *PEPROCESS; 

六.參考資料