計算機操作系統雜記

計算機操作系統雜記

1.操作系統

操作系統的作用:
    1.os作爲用戶與計算機硬件系統之間的接口;
    這種接口是軟件接口。
    用戶可以通過3種方式使用計算機:
        1.命令方式;
        2.系統調用方式;
        3.圖形、窗口方式。

    2.os作爲計算機系統資源的管理者
        資源分爲四類:
        處理器、存儲器、i/o設備以及信息(數據和程序)

        對應的:
        處理機管理:用於分配和控制處理機;
        存儲器管理:主要負責內存的分配和回收;
        I/O設備管理:負責I/O設備的分配和操縱;
        文件管理:負責文件的存取、共享和保護。


    3.os實現了對計算機資源的抽象



分時系統:

    分時系統可以很好地將一臺計算機提供給多個用戶同時
    使用,提高計算機的利用率。


分時系統實現中的關鍵問題:
    1.及時接收;
    2.及時處理。

 爲實現人機交互,必須徹底改變原來的批處理系統的
 運行方式。
 首先,用戶作業不能先進入磁盤,然後再調入內存。
 因爲作業在磁盤上不能運行,當然用戶也無法與機器交互,
 因此,作業應直接進入內存。
 其次,不允許一個作業長期佔用處理機,直至它運行結束
 或出現I/O請求後,方纔調度其他作業運行。
 爲此,應該規定每個作業只運行一個很短的時間
 例如0.1秒,通常把這段時間成爲時間片,
 然後便暫停該作業的運行,並立即調度下一個程序運行。
 如果在不長的時間如3秒內能使所有的用戶作業
 都執行一次,也就是一個時間片的時間,
 便可使每個用戶都能及時地與自己的作業交互,從而
 可使用戶的請求得到及時的響應。




實時系統:
實時系統是指系統能及時響應外部事件的請求,在
規定的時間內完成對該事件的處理,並
控制所有實時任務協調一致地運行。




操作系統的基本特性:

並行和併發:
並行性是指兩個或多個事件在同一時刻發生;
而併發性是指兩個或多個事件在同一時間間隔內發生。

在多道程序環境下,併發性是指在一段時間內
宏觀上有多個程序在同時運行,
但在單處理機系統中,每一時刻僅能有一道程序執行,
故微觀上這些程序只能是分時地交替執行。
倘若在計算機系統中有多個處理機,則這些可以
併發執行的程序便可分配到多個處理機上,
實現並行執行,即利用每個處理機來處理一個
可併發執行的程序。
這樣,多個程序便可同時執行。


引入進程:

在操作系統中引入進程的目的,就是爲了使多個
程度能併發執行。

這樣可以極大地提高系統資源的利用率,增加系統的吞吐量。


爲使多個程序能併發執行,系統必須分別爲每個程序
建立進程。
簡單來說,進程是指在系統中能
獨立運行 並作爲資源分配的基本單位。
他是由一組機器指令、數據和堆棧等組成的,
是一個能獨立運行的活動實體。
多個進程之間可以併發執行和交換信息。


引入線程:

進程是操作系統中可以擁有資源並獨立運行的基本單位。
當一個進車因故不能繼續運行時,操作系統
便調度另一進程運行。
由於進程擁有自己的資源,故使調度的付出的開銷較大。


通常在一個進程中包含若干個線程,他們
可以利用進程所擁有的資源。
在引入線程的os中,通常都是把進程作爲分配
資源的基本單位,
而把線程作爲獨立運行和獨立調度的基本單位。

由於線程比進程更小,基本上不擁有系統資源,
故對它的調度所付出的開銷就會小得多,能更
高效地提高系統內多個程序間併發執行的而程度。

引入線程,進一步提高系統的併發性。



共享性:
系統中的資源供內存中多個併發執行的進程,線程
共同使用,相應的,把這種資源共同使用稱爲資源共享,
或稱爲資源複用。

目前主要實現資源共享的方式有如下兩種:
    1.互斥共享方式
    計算機系統中的大多數物理設備,以及
    某些軟件中所用的棧、變量和表格,
    都屬於臨界資源,他們要求被互斥地共享。

    2.同時訪問方式
    這裏所謂的“同時”,宏觀上,和微觀上。
    典型的可供多個進程“同時”訪問的資源是磁盤設備,
    一些用重入碼編寫的文件也可以
    “同時”共享,即若干個用戶同時訪問該文件。





虛擬技術:
通過某種技術把一個物理實體變爲若干個邏輯上的對應物。
物理實體是實的,即實際存在的,
而後者是虛的,僅是用戶感覺上的東西,
相應的,用於實現虛擬的技術成爲虛擬技術。
在操作系統中利用了兩種方式實現虛擬技術,
就是時分複用技術和空分複用技術。

    1.時分複用技術:
    時分複用,就是分時使用方式。。
    爲了提高信道利用率,人們利用時分複用方式,
    將一條物理信道虛擬爲多條邏輯信道,
    將每條信道供一對用戶通話。

        1.虛擬處理機技術
        利用多道程序設計技術,爲每道程序建立一個進程,讓多道程
        序併發地執行,以此來分時使用一臺處理機。此時,雖然系統中只有一臺處理機,但它卻
        能同時爲多個用戶服務,使每個終端用戶都認爲是有一個處理機在專門爲他服務。亦即,
        利用多道程序設計技術,把一臺物理上的處理機虛擬爲多臺邏輯上的處理機,在每臺邏輯
        處理機上運行一道程序。我們把用戶所感覺到的處理機稱爲虛擬處理器


        2.虛擬設備技術
        我們還可以通過虛擬設備技術,將一臺物理 I/O 設備虛擬爲多臺邏輯上的 I/O 設備,並
        允許每個用戶佔用一臺邏輯上的 I/O 設備,這樣便可使原來僅允許在一段時間內由一個用戶
        訪問的設備(即臨界資源),變爲在一段時間內允許多個用戶同時訪問的共享設備。例如,原
        來的打印機屬於臨界資源,而通過虛擬設備技術,可以把它變爲多臺邏輯上的打印機,供
        多個用戶“同時”打印。


    2.空分複用技術
    聯繫頻分複用技術。
    使用空分複用技術提高存儲空間的利用率。

        1.虛擬磁盤技術
        通常在一臺機器上只配置一臺硬盤。我們可以通過虛擬磁盤技術將一臺硬盤虛擬爲多
        臺虛擬磁盤,這樣使用起來既方便又安全。虛擬磁盤技術也是採用了空分複用方式,即它
        將硬盤劃分爲若干個卷,例如 1、2、3、4 四個卷,再通過安裝程序將它們分別安裝在 C、
        D、E、F 四個邏輯驅動器上,這樣,機器上便有了四個虛擬磁盤。當用戶要訪問 D 盤中的
        內容時,系統便會訪問卷 2 中的內容。


        2.虛擬存儲器技術
        在單道程序環境下,處理機會有很多空閒時間,內存也會有很多空閒空間,顯然,這
        會使處理機和內存的效率低下。如果說時分複用技術是利用處理機的空閒時間來運行其它
        的程序,使處理機的利用率得以提高,那麼空分複用則是利用存儲器的空閒空間來存放其
        它的程序,以提高內存的利用率


        但是,單純的空分複用存儲器只能提高
        內存的利用率,並不能實現在邏輯上擴大
        存儲器容量的功能,必須引入虛擬存儲技術
        才能達到此目的。
        虛擬存儲技術在本質上就是使內存分時複用。
        他可以使一道程序通過時分複用方式,
        在遠小於它的內存空間中運行。
        例如,一個100M的應用程序
        可以運行在20M的空間。



異步性:
    由於資源等因素的限制,進程的執行通常都不是
    “一氣呵成”的,而是“走走停停”的。

    由於各用戶程序性能的不同,比如,
    有的側重於計算而較少需要I/O,
    而有的程序其計算少而I/O多。
    這樣,很可能是先進入內存的作業後完成,
    後進入內存的作業先完成。

    或者說,進程是以人們不可預知的速度向前推進。
    這就是進程的異步性。

    儘管如此,但只要在操作系統中配置有完善的
    進程同步機制,且運行環境相同,
    作業經多次運行都會獲得完全相同的結果。
    因此,異步運行方式是允許的。




操作系統的主要功能:
    1.處理機管理功能:
        1.進程控制
        主要功能是爲作業創建進程,撤銷已結束的進程,
        以及控制進程在運行過程中的狀態轉換。

        2.進程同步
        進程同步的主要任務是爲多個進程含線程的運行進行協調。
        有兩種協調方式:
        進程互斥方式、進程同步方式。


        3.進程通信

        例如,有三個相互合作的進程,
        他們是輸入進程、計算進程、打印進程。
        進程通信的任務是用來實現在相互合作的進程之間的信息交換。

        4.調度 
        在後備隊列上等待的每個作業都需經過調度才能執行。
        在傳統的操作系統中,
        包括作業調度和進程調度兩步。
            1.作業調度。
            作業調度的基本任務是從後備隊列中按照一定的算法,選擇出若干個
            作業,爲它們分配運行所需的資源(首先是分配內存)。在將它們調入內存後,便分別爲它
            們建立進程,使它們都成爲可能獲得處理機的就緒進程,並按照一定的算法將它們插入就
            緒隊列。

            2.進程調度
            進程調度的任務是從進程的就緒隊列中,按照一定的算法選出一個進程,
            把處理機分配給它,併爲它設置運行現場,使進程投入執行。值得提出的是,在多線程 OS
            中,通常是把線程作爲獨立運行和分配處理機的基本單位,爲此,須把就緒線程排成一個
            隊列,每次調度時,是從就緒線程隊列中選出一個線程,把處理機分配給它。


    2.存儲器管理功能

        存儲器管理應該提高存儲器的利用率以及
        能從邏輯上擴充內存。
        爲此,存儲器管理應具有內存分配、內存保護。
        地址映射和內存擴充等功能。

        1.內存分配
            內存分配的主要任務是爲每道程序分配內存空間,
            使他們“各得其所”;提高存儲器的利用率,
            以減少不可用的內存空間;
            允許正在運行的程序申請附加的內存空間,
            以適應程序和數據動態增長的需要。

            OS 在實現內存分配時,可採取靜態和動態兩種方式。在靜態分配方式中,每個作業的
            內存空間是在作業裝入時確定的;在作業裝入後的整個運行期間,不允許該作業再申請新
            的內存空間,也不允許作業在內存中“移動”。在動態分配方式中,每個作業所要求的基本
            內存空間也是在裝入時確定的,但允許作業在運行過程中繼續申請新的附加內存空間,以
            適應程序和數據的動態增長,也允許作業在內存中“移動”。


            1.內存分配數據結構;
            2.內存分配功能;
            3.內存回收功能。


        2.內存保護 
            內存保護的主要任務是確保每道用戶程序都只在自己的內存空間內運行,彼此互不幹
            擾;絕不允許用戶程序訪問操作系統的程序和數據;也不允許用戶程序轉移到非共享的其
            它用戶程序中去執行。
            爲了確保每道程序都只在自己的內存區中運行,必須設置內存保護機制。一種比較簡
            單的內存保護機制是設置兩個界限寄存器,分別用於存放正在執行程序的上界和下界。系
            統須對每條指令所要訪問的地址進行檢查,如果發生越界,便發出越界中斷請求,以停止
            該程序的執行。如果這種檢查完全用軟件實現,則每執行一條指令,便須增加若干條指令
            去進行越界檢查,這將顯著降低程序的運行速度。因此,越界檢查都由硬件實現。當然,
            對發生越界後的處理,還須與軟件配合來完成。


        3.地址映射 
            一個應用程序(源程序)經編譯後,通常會形成若干個目標程序;這些目標程序再經過鏈
            接便形成了可裝入程序。這些程序的地址都是從“0”開始的,程序中的其它地址都是相對
            於起始地址計算的。由這些地址所形成的地址範圍稱爲“地址空間”,其中的地址稱爲“邏
            輯地址”或“相對地址”。此外,由內存中的一系列單元所限定的地址範圍稱爲“內存空間”,
            其中的地址稱爲“物理地址”。
            在多道程序環境下,每道程序不可能都從“0”地址開始裝入(內存),這就致使地址空
            間內的邏輯地址和內存空間中的物理地址不相一致。爲使程序能正確運行,存儲器管理必
            須提供地址映射功能,以將地址空間中的邏輯地址轉換爲內存空間中與之對應的物理地址。
            該功能應在硬件的支持下完成。



        4.內存擴充
            存儲器管理中的內存擴充任務並非是去擴大物理內存的容量,而是藉助於虛擬存儲技
            術,從邏輯上去擴充內存容量,使用戶所感覺到的內存容量比實際內存容量大得多,以便
            讓更多的用戶程序併發運行。這樣,既滿足了用戶的需要,又改善了系統的性能。爲此,
            只需增加少量的硬件。爲了能在邏輯上擴充內存,系統必須具有內存擴充機制,用於實現
            下述各功能:

            1.請求調入功能。
            允許在裝入一部分用戶程序和數據的情況下,
            便能啓動該程序運行。在程序運行過程中,若發現要繼續
            運行時所需的程序和數據尚未裝入內存,
            可向os發出請求,由os從磁盤中將所需部分調入內存,
            以便繼續運行。程序局部性原理。

            2.置換功能
            若發現在內存中已無足夠的空間來轉入需要
            調入的程序和數據時,系統應能將內存中
            的一部分暫時不用的程序和數據調至磁盤上,
            以騰出內存空間,然後再將所需的部分裝入內存。



    3.設備管理功能
        設備管理用於管理計算機系統中所有的外圍設備,而設備管理的主要任務是:完成用
        戶進程提出的 I/O 請求;爲用戶進程分配其所需的 I/O 設備;提高 CPU 和 I/O 設備的利用
        率;提高 I/O 速度;方便用戶使用 I/O 設備。爲實現上述任務,設備管理應具有緩衝管理、
        設備分配和設備處理以及虛擬設備等功能。

        1.緩衝管理
        CPU 運行的高速性和 I/O 低速性間的矛盾自計算機誕生時起便已存在了。而隨着 CPU
        速度迅速提高,使得此矛盾更爲突出,嚴重降低了 CPU 的利用率。如果在 I/O 設備和 CPU
        之間引入緩衝,則可有效地緩和 CPU 與 I/O 設備速度不匹配的矛盾,提高 CPU 的利用率,
        進而提高系統吞吐量。因此,在現代計算機系統中,都無一例外地在內存中設置了緩衝區,
        而且還可通過增加緩衝區容量的方法來改善系統的性能。
        對於不同的系統,可以採用不同的緩衝區機制。最常見的緩衝區機制有單緩衝機制、
        能實現雙向同時傳送數據的雙緩衝機制,以及能供多個設備同時使用的公用緩衝池機制。
        上述這些緩衝區都將由 OS 中的緩衝管理機制將它們管理起來。

        2.設備分配 
        設備分配的基本任務是根據用戶進程的 I/O 請求、系統的現有資源情況以及按照某種設
        備的分配策略,爲之分配其所需的設備。如果在 I/O 設備和 CPU 之間還存在着設備控制器
        和 I/O 通道時,還須爲分配出去的設備分配相應的控制器和通道。
        爲了實現設備分配,系統中應設置設備控制表、控制器控制表等數據結構,用於記錄
        設備及控制器的標識符和狀態。根據這些表格可以瞭解指定設備當前是否可用,是否忙碌,
        以供進行設備分配時參考。在進行設備分配時,應針對不同的設備類型而採用不同的設備
        分配方式。對於獨佔設備(臨界資源)的分配,還應考慮到該設備被分配出去後系統是否安全。
        在設備使用完後,應立即由系統回收。

        3.設備處理 
        設備處理程序又稱爲設備驅動程序。其基本任務是用於實現 CPU 和設備控制器之間的
        通信,即由 CPU 向設備控制器發出 I/O 命令,要求它完成指定的 I/O 操作;反之,由 CPU
        接收從控制器發來的中斷請求,並給予迅速的響應和相應的處理。
        處理過程是:設備處理程序首先檢查 I/O 請求的合法性,瞭解設備狀態是否是空閒的,
        瞭解有關的傳遞參數及設置設備的工作方式。然後,便向設備控制器發出 I/O 命令,啓動 I/O
        設備去完成指定的 I/O 操作。設備驅動程序還應能及時響應由控制器發來的中斷請求,並根
        據該中斷請求的類型,調用相應的中斷處理程序進行處理。對於設置了通道的計算機系統,
        設備處理程序還應能根據用戶的 I/O 請求,自動地構成通道程序。



    4.文件管理功能

    在現代的計算機管理中,總是把程序和數據以文件的
    形式存儲在磁盤和磁帶上,供所有的或指定的用戶使用。
    爲此,在操作系統中必須配置文件管理機構。
    文件管理的主要任務是對用戶文件和系統文件進行管理,
    以方便用戶使用,並保證文件的安全性。
    爲此,文件管理應具有對文件存儲空間的 管理。
    目錄管理、文件的讀寫管理、以及
    文件的共享和保護等功能。

        1.文件存儲空間的管理
        爲了方便用戶的使用,對於一些當前需要使用的系統文件和用戶文件,都必須放在可
        隨機存取的磁盤上。在多用戶環境下,若由用戶自己對文件的存儲進行管理,不僅非常困
        難,而且也必然是十分低效的。因而,需要由文件系統對諸多文件及文件的存儲空間實施
        統一的管理。其主要任務是爲每個文件分配必要的外存空間,提高外存的利用率,並能有
        助於提高文件系統的存、取速度。
        爲此,系統應設置相應的數據結構,用於記錄文件存儲空間的使用情況,以供分配存
        儲空間時參考;系統還應具有對存儲空間進行分配和回收的功能。爲了提高存儲空間的利
        用率,對存儲空間的分配,通常是採用離散分配方式,以減少外存零頭,並以盤塊爲基本
        分配單位。盤塊的大小通常爲 1~8 KB

        2.目錄管理 
        爲了使用戶能方便地在外存上找到自己所需的文件,通常由系統爲每個文件建立一個
        目錄項。目錄項包括文件名、文件屬性、文件在磁盤上的物理位置等。由若干個目錄項又
        可構成一個目錄文件。目錄管理的主要任務是爲每個文件建立其目錄項,並對衆多的目錄
        項加以有效的組織,以實現方便的按名存取,即用戶只須提供文件名便可對該文件進行存
        取。其次,目錄管理還應能實現文件共享,這樣,只須在外存上保留一份該共享文件的副
        本。此外,還應能提供快速的目錄查詢手段,以提高對文件的檢索速度。

        3.文件的讀寫管理和保護
        (1) 文件的讀/寫管理。該功能是根據用戶的請求,從外存中讀取數據,或將數據寫入
        外存。在進行文件讀(寫)時,系統先根據用戶給出的文件名去檢索文件目錄,從中獲得文件
        在外存中的位置。然後,利用文件讀(寫)指針,對文件進行讀(寫)。一旦讀(寫)完成,便修
        改讀(寫)指針,爲下一次讀(寫)做好準備。由於讀和寫操作不會同時進行,故可合用一個
        讀/寫指針。
        (2) 文件保護。爲了防止系統中的文件被非法竊取和破壞,在文件系統中必須提供有效
        的存取控制功能,以實現下述目標:
        ① 防止未經覈準的用戶存取文件;
        ② 防止冒名頂替存取文件;
        ③ 防止以不正確的方式使用文件。




微內核操作系統的優點
    由於微內核 OS 結構是建立在模塊化、層次化結構的基礎上的,並採用了客戶/服務器
    模式和麪向對象的程序設計技術,由此可見,微內核結構的 OS 是集各種技術優點之大成,
    因而使之具有如下優點:
    1) 提高了系統的可擴展性
    由於微內核 OS 的許多功能是由相對獨立的服務器軟件來實現的,當開發了新的硬件和
    軟件時,微內核 OS 只須在相應的服務器中增加新的功能,或再增加一個專門的服務器。與
    此同時,也必然改善系統的靈活性,不僅可在操作系統中增加新的功能,還可修改原有功
    能,以及刪除已過時的功能,以形成一個更爲精幹有效的操作系統。
    2) 增強了系統的可靠性
    這一方面是由於微內核是出於精心設計和嚴格測試的,容易保證其正確性;另一方面
    是它提供了規範而精簡的應用程序接口(API),爲微內核外部的程序編制高質量的代碼創造
    了條件。此外,由於所有服務器都是運行在用戶態,服務器與服務器之間採用的是消息傳
    遞通信機制,因此,當某個服務器出現錯誤時,不會影響內核,也不會影響其它服務器。
    3) 可移植性
    隨着硬件的快速發展,出現了各種各樣的硬件平臺,作爲一個好的操作系統,必須具
    備可移植性,使其能較容易地運行在不同的計算機硬件平臺上。在微內核結構的操作系統
    中,所有與特定 CPU 和 I/O 設備硬件有關的代碼,均放在內核和內核下面的硬件隱藏層中,
    而操作系統其它絕大部分(即各種服務器)均與硬件平臺無關,因而,把操作系統移植到另一
    個計算機硬件平臺上所需作的修改是比較小的。
    4) 提供了對分佈式系統的支持
    由於在微內核 OS 中,客戶和服務器之間以及服務器和服務器之間的通信,是採用消息
    傳遞通信機制進行的,致使微內核 OS 能很好地支持分佈式系統和網絡系統。事實上,只要
    在分佈式系統中賦予所有進程和服務器惟一的標識符,在微內核中再配置一張系統映射表
    (即進程和服務器的標識符與它們所駐留的機器之間的對應表),在進行客戶與服務器通信
    時,只需在所發送的消息中標上發送進程和接收進程的標識符,微內核便可利用系統映射
    表,將消息發往目標,而無論目標是駐留在哪臺機器上。
    5) 融入了面向對象技術
    在設計微內核 OS 時,採用了面嚮對象的技術,其中的“封裝”,“繼承”,“對象類”和
    “多態性”,以及在對象之間採用消息傳遞機制等,都十分有利於提高系統的“正確性”、“可
    靠性”、“易修改性”、“易擴展性”等,而且還能顯著地減少開發系統所付出的開銷。 

2.進程管理
程序順序執行。

    程序併發執行。結合流水線處理來思考。
    例如,輸入程序在輸入第一個程序後,
    在計算程序對該程序進行計算的同時,
    可由輸入程序再輸入第二個程序,
    從而使第一個程序的計算操作可與
    第二個程序的輸入操作併發執行。


進程的特徵和定義
    1.結構特徵:
        通常的程序時不能併發執行的。
        爲使程序含數據能獨立運行,應爲之
        配置一進程控制塊PCB;
        而由程序段、相關的數據段、PCB
        三部分組成的進程實體。

        實際上大多數情況下的進程,是指進程實體。
        所謂創建進程,實質上是創建進程實體中的PCB;
        而撤銷進程,實質上是撤銷進程的PCB。

    2.動態性:
        進程的是指是進程實體的一次執行過程,
        因此,動態性是進程的最基本的特徵。
        動態性還表現在:
        它由創建而產生,
        由調度而執行,
        由撤銷而消亡。

        進程實體具有一定的生命期,
        而程序只是一組有序指令的集合,
        並存放於某種介質中,
        其本身並不具有運動的含義,因而是靜態的。


    3.併發性:
        這是指多個進程實體同存於內存中,
        且能在一段時間內同時運行。

        沒有建立PCB是不能併發執行的。

    4.獨立性:
        獨立性是指進程實體是一個
        能獨立運行、
        能獨立分配資源、
        能獨立接受調度的基本單位。



    5.異步性:
        進程按各自獨立的、不可預知的速度向前推進,
        或說進程實體按異步方式運行。


進程定義:
    (1) 進程是程序的一次執行。
    (2) 進程是一個程序及其數據在處理機上順序執行時所發生的活動。
    (3) 進程是程序在一個數據集合上運行的過程,它是系統進行資源分配和調度的一個獨
    立單位。


進程的3種基本裝態:

    1) 就緒(Ready)狀態
    當進程已分配到除 CPU 以外的所有必要資源後,只要再獲得 CPU,便可立即執行,進
    程這時的狀態稱爲就緒狀態。在一個系統中處於就緒狀態的進程可能有多個,通常將它們
    排成一個隊列,稱爲就緒隊列。
    2) 執行狀態
    進程已獲得 CPU,其程序正在執行。在單處理機系統中,只有一個進程處於執行狀態;
    在多處理機系統中,則有多個進程處於執行狀態。
    3) 阻塞狀態
    正在執行的進程由於發生某事件而暫時無法繼續執行時,便放棄處理機而處於暫停狀態,
    亦即進程的執行受到阻塞,把這種暫停狀態稱爲阻塞狀態,有時也稱爲等待狀態或封鎖狀態。
    致使進程阻塞的典型事件有:請求 I/O,申請緩衝空間等。通常將這種處於阻塞狀態的進程也
    排成一個隊列。有的系統則根據阻塞原因的不同而把處於阻塞狀態的進程排成多個隊列。


    處於就緒裝態的進程,在調度程序爲之分配了
    處理機之後,該進程便可執行,相應的,它就由就緒裝態轉變爲
    執行狀態。
    正在執行的進程也被稱爲當前進程,如果
    因分配給他的時間片已完而被暫停執行時,
    該進程便由執行狀態回覆到就緒裝態;
    如果因發生某事件而使進程的執行受阻,
    例如,進程請求訪問某臨界資源,而該資源正在被其他進程訪問時,
    使之無法繼續執行,該進程將由執行狀態轉變爲
    阻塞狀態。

    阻塞狀態只能由執行狀態變成;
    阻塞狀態只能變成就緒狀態;
    就緒狀態和執行狀態可以互相轉換。


另外的爲了管理需要增加的狀態  

掛起狀態

創建狀態和終止狀態

    創建狀態:
    創建一個進程一般要通過兩個步驟:
    首先,爲一個新進程創建PCB,並填寫必要的管理信息;
    其次,把該進程轉入就緒狀態並插入就緒隊列中。

    ,一般而言,此時的進程已擁有了自己的 PCB,但進程自身還未進
    入主存,即創建工作尚未完成,進程還不能被調度運行,其所處的狀態就是創建狀態。
    引入創建狀態,是爲了保證進程的調度必須在創建工作完成後進行,以確保對進程控
    制塊操作的完整性。同時,創建狀態的引入,也增加了管理的靈活性,操作系統可以根據
    系統性能或主存容量的限制,推遲創建狀態進程的提交。對於處於創建狀態的進程,獲得
    了其所必需的資源,以及對其PCB初始化工作完成後,進程狀態便可由創建狀態轉入就緒
    狀態。


    終止狀態:
    進程的終止也要通過兩個步驟:
    首先等待操作系統進行善後處理,
    然後將將其PCB空間返還系統。
    當一個進程到達了自然結束點,
    或是出現了無法克服的錯誤,
    或者是被操作系統所終結,
    或是被其他有終止權的進程所終結,
    他將進入終止狀態。


    進入終止態的進程以後不能再執行,但在操作系統中依然保留一個記錄,其中保存狀態碼和一些計
    時統計數據,供其它進程收集。一旦其它進程完成了對終止狀態進程的信息提取之後,操
    作系統將刪除該進程。


進程控制塊:
    os是根據PCB來對併發執行的進程進行控制和管理的。
    例如,當 OS 要調度某進程執行時,要從該進程的 PCB
    中查出其現行狀態及優先級;在調度到某進程後,要根據其 PCB 中所保存的處理機狀態信
    息,設置該進程恢復運行的現場,並根據其 PCB 中的程序和數據的內存始址,找到其程序
    和數據;進程在執行過程中,當需要和與之合作的進程實現同步、通信或訪問文件時,也
    都需要訪問 PCB;當進程由於某種原因而暫停執行時,又須將其斷點的處理機環境保存在
    PCB 中。可見,在進程的整個生命期中,系統總是通過 PCB 對進程進行控制的,亦即,系
    統是根據進程的 PCB 而不是任何別的什麼而感知到該進程的存在的。所以說,PCB 是進程
    存在的惟一標誌。

    當系統創建一個新進程時,就爲它建立了一個 PCB;進程結束時又回收其 PCB,進程
    於是也隨之消亡。PCB 可以被操作系統中的多個模塊讀或修改,如被調度程序、資源分配
    程序、中斷處理程序以及監督和分析程序等讀或修改。因爲 PCB 經常被系統訪問,尤其是
    被運行頻率很高的進程及分派程序訪問,故 PCB 應常駐內存。系統將所有的 PCB 組織成若
    幹個鏈表(或隊列),存放在操作系統中專門開闢的 PCB 區內。例如在 Linux 系統中用
    task_struct 數據結構來描述每個進程的進程控制塊,在 Windows 操作系統中則使用一個執行
    體進程塊(EPROCESS)來表示進程對象的基本屬性

進程控制塊中的信息:
    1.進程標識符:
    進程標識符用於惟一地標識一個進程。一個進程通常有兩種標識符:
    (1) 內部標識符。在所有的操作系統中,都爲每一個進程賦予了一個惟一的數字標識符,
    它通常是一個進程的序號。設置內部標識符主要是爲了方便系統使用。
    (2) 外部標識符。它由創建者提供,通常是由字母、數字組成,往往是由用戶(進程)在
    訪問該進程時使用。爲了描述進程的家族關係,還應設置父進程標識及子進程標識。此外,
    還可設置用戶標識,以指示擁有該進程的用戶。

    2.處理機狀態:
    處理機狀態信息主要是由處理機的各種寄存器中的內容組成的。處理機在運行時,許
    多信息都放在寄存器中。當處理機被中斷時,所有這些信息都必須保存在 PCB 中,以便在
    該進程重新執行時,能從斷點繼續執行。這些寄存器包括:① 通用寄存器,又稱爲用戶可
    視寄存器,它們是用戶程序可以訪問的,用於暫存信息,在大多數處理機中,有 8~32 個
    通用寄存器,在 RISC 結構的計算機中可超過 100 個;② 指令計數器,其中存放了要訪問
    的下一條指令的地址;③ 程序狀態字 PSW,其中含有狀態信息,如條件碼、執行方式、中
    斷屏蔽標誌等;④ 用戶棧指針,指每個用戶進程都有一個或若干個與之相關的系統棧,用
    於存放過程和系統調用參數及調用地址,棧指針指向該棧的棧頂。

    3.進程調度信息:
    在 PCB 中還存放一些與進程調度和進程對換有關的信息,包括:① 進程狀態,指明進
    程的當前狀態,作爲進程調度和對換時的依據;② 進程優先級,用於描述進程使用處理機
    的優先級別的一個整數,優先級高的進程應優先獲得處理機;③ 進程調度所需的其它信息,
    它們與所採用的進程調度算法有關,比如,進程已等待 CPU 的時間總和、進程已執行的時
    間總和等;④ 事件,指進程由執行狀態轉變爲阻塞狀態所等待發生的事件,即阻塞原因。


    4.進程控制信息:
    進程控制信息包括:① 程序和數據的地址,指進程的程序和數據所在的內存或外存地
    (首)址,以便再調度到該進程執行時,能從 PCB 中找到其程序和數據;② 進程同步和通信
    機制,指實現進程同步和進程通信時必需的機制,如消息隊列指針、信號量等,它們可能
    全部或部分地放在 PCB 中;③ 資源清單,即一張列出了除 CPU 以外的、進程所需的全部
    資源及已經分配到該進程的資源的清單;④ 鏈接指針,它給出了本進程(PCB)所在隊列中
    的下一個進程的 PCB 的首地址。


    進程控制塊組織方式:
    鏈接方式
    索引方式


進程控制 
    進程控制一般是由os的內核中的原語來實現的。

    原語是由若干條指令組成的額,用於完成一定功能的一個過程。
    他與一般過程的區別在於:
    所謂原子操作,是指一個操作中的所有動作要麼全做,
    要麼全部做。
    換言之,他是一個不可分割的基本單位。
    因此,在執行的過程中不允許被中斷。
    原子操作在管態下執行,常駐內存。

    原語的作用是爲了實現進程的通信和控制,
    系統對進行的控制如不適用原語,
    就會造成其狀態的不確定性,
    從而達不到進程控制的目的。

    子進程可以繼承父進程所擁有的資源,例
    如,繼承父進程打開的文件,繼承父進程所分配到的緩衝區等。當子進程被撤消時,應將
    其從父進程那裏獲得的資源歸還給父進程。此外,在撤消父進程時,也必須同時撤消其所
    有的子進程。爲了標識進程之間的家族關係,在 PCB 中都設置了家族關係表項,以標明自
    己的父進程及所有的子進程。

    導致一個進程去創建另一個進程的典型事件
    四類:
    1.用戶登錄;
    2.作業調度;
    3.提供服務;
    4.應用請求。


    調用進程創建原語Creat()創建一個新進程:
    1.申請空白PCB;
    2.爲新進程分配資源;
    3.初始化進程控制塊。
    4.將新進程插入就緒隊列。

    進程的終止:
    1.正常結束;
    2.異常結束
        在進程運行期間,由於出現某些錯誤和故障而迫使進程終止(Termination of Process)。
        這類異常事件很多,常見的有下述幾種:
        (1) 越界錯誤。這是指程序所訪問的存儲區已越出該進程的區域。
        (2) 保護錯。這是指進程試圖去訪問一個不允許訪問的資源或文件,或者以不適當的方
        式進行訪問,例如,進程試圖去寫一個只讀文件。
        (3) 非法指令。這是指程序試圖去執行一條不存在的指令。出現該錯誤的原因,可能是
        程序錯誤地轉移到數據區,把數據當成了指令。
        (4) 特權指令錯。這是指用戶進程試圖去執行一條只允許 OS 執行的指令。
        (5) 運行超時。這是指進程的執行時間超過了指定的最大值。
        (6) 等待超時。這是指進程等待某事件的時間超過了規定的最大值。
        (7) 算術運算錯。這是指進程試圖去執行一個被禁止的運算,例如被 0 除。
        (8) I/O 故障。這是指在 I/O 過程中發生了錯誤等。


    3.外界干預
        外界干預並非指在本進程運行中出現了異常事件,而是指進程應外界的請求而終止運
        行。這些干預有:
        (1) 操作員或操作系統干預。由於某種原因,例如,發生了死鎖,由操作員或操作系統
        終止該進程。
        (2) 父進程請求。由於父進程具有終止自己的任何子孫進程的權力,因而當父進程提出
        請求時,系統將終止該進程。
        (3) 父進程終止。當父進程終止時,OS 也將它的所有子孫進程終止。


    進程的終止過程:
        1.根據被終止進程的標識符,
        從PCB集合中檢索出該進程的PCB,
        從中讀出該進程的狀態;
        2.若該終止進程正處於執行狀態,
        應立即終止該進程的執行,
        並置調度標誌爲真,
        用於指示該進程被終止後應重新進行調度;
        3.若該進程還有子孫進程,
        還應將其子孫進程予以終止,
        以防他們成爲不可控的進程。
        4.將被終止進程所擁有的全部資源,
        或者歸還給父進程,
        或者歸還給系統;
        5.將被終止進程PCB從所在隊列或鏈表中移出,
        等待其他程序來蒐集信息。


    進程阻塞和喚醒:

        進程阻塞過程
        正在執行的進程,當發現上述某事件時,由於無法繼續執行,於是進程便通過調用阻
        塞原語 block 把自己阻塞。可見,進程的阻塞是進程自身的一種主動行爲。進入 block 過程
        後,由於此時該進程還處於執行狀態,所以應先立即停止執行,把進程控制塊中的現行狀
        態由“執行”改爲“阻塞”,並將 PCB 插入阻塞隊列。如果系統中設置了因不同事件而阻塞
        的多個阻塞隊列,則應將本進程插入到具有相同事件的阻塞(等待)隊列。最後,轉調度程序
        進行重新調度,將處理機分配給另一就緒進程並進行切換,亦即,保留被阻塞進程的處理
        機狀態(在 PCB 中),再按新進程的 PCB 中的處理機狀態設置 CPU 的環境


        進程喚醒過程:
        當被阻塞進程所期待的事件出現時,如 I/O 完成或其所期待的數據已經到達,則由有關
        進程(比如用完並釋放了該 I/O 設備的進程)調用喚醒原語 wakeup( ),將等待該事件的進程喚
        當被阻塞進程所期待的事件出現時,如 I/O 完成或其所期待的數據已經到達,則由有關
        進程(比如用完並釋放了該 I/O 設備的進程)調用喚醒原語 wakeup( ),將等待該事件的進程喚      



3.進程同步 
    進程同步的主要任務是對多個相關進程在
    執行次序上進行協調,以使併發執行的諸進程之間
    能有效地共享資源和相互合作,
    從而使程序的執行具有可再現性。

    臨界資源
    生產者-消費者問題:
    生產者-消費者(producer-consumer)問題是一個著名的進程同步問題。它描述的是:有一
    羣生產者進程在生產產品,並將這些產品提供給消費者進程去消費。爲使生產者進程與消
    費者進程能併發執行,在兩者之間設置了一個具有 n 個緩衝區的緩衝池,生產者進程將它
    所生產的產品放入一個緩衝區中;消費者進程可從一個緩衝區中取走產品去消費。儘管所
    有的生產者進程和消費者進程都是以異步方式運行的,但它們之間必須保持同步,即不允
    許消費者進程到一個空緩衝區去取產品,也不允許生產者進程向一個已裝滿產品且尚未被
    取走的緩衝區中投放產品。

    具體問題及解答可以參看計算機操作系統P58.

    關鍵點還是原子操作。
    要把變量counter作爲臨街資源處理,
    令生產者進程和消費者進程互斥地訪問變量counter


    同步機制應遵循的原則:
    同步機制應遵循的規則
    爲實現進程互斥地進入自已的臨界區,可用軟件方法,更多的是在系統中設置專門的
    同步機構來協調各進程間的運行。所有同步機制都應遵循下述四條準則:
    (1) 空閒讓進。當無進程處於臨界區時,表明臨界資源處於空閒狀態,應允許一個請求
    進入臨界區的進程立即進入自己的臨界區,以有效地利用臨界資源。
    (2) 忙則等待。當已有進程進入臨界區時,表明臨界資源正在被訪問,因而其它試圖進
    入臨界區的進程必須等待,以保證對臨界資源的互斥訪問。
    (3) 有限等待。對要求訪問臨界資源的進程,應保證在有限時間內能進入自己的臨界區,
    以免陷入“死等”狀態。
    (4) 讓權等待。當進程不能進入自己的臨界區時,應立即釋放處理機,以免進程陷入“忙
    等”狀態。


信號量機制:
    信號量機制是一種卓有成效的進程同步工具。


信號量的應用  

    1.利用信號量實現進程互斥
    爲使多個進程能互斥地訪問某臨界資源,只須爲該資源設置一互斥信號量 mutex,並設
    其初始值爲 1,然後將各進程訪問該資源的臨界區 CS 置於 wait(mutex)和 signal(mutex)操作
    之間即可。這樣,每個欲訪問該臨界資源的進程在進入臨界區之前,都要先對 mutex 執行
    wait 操作,若該資源此刻未被訪問,本次 wait 操作必然成功,進程便可進入自己的臨界區,
    這時若再有其他進程也欲進入自己的臨界區,此時由於對 mutex 執行 wait 操作定會失敗,
    爲使多個進程能互斥地訪問某臨界資源,只須爲該資源設置一互斥信號量 mutex,並設
    其初始值爲 1,然後將各進程訪問該資源的臨界區 CS 置於 wait(mutex)和 signal(mutex)操作
    之間即可。這樣,每個欲訪問該臨界資源的進程在進入臨界區之前,都要先對 mutex 執行
    wait 操作,若該資源此刻未被訪問,本次 wait 操作必然成功,進程便可進入自己的臨界區,
    這時若再有其他進程也欲進入自己的臨界區,此時由於對 mutex 執行 wait 操作定會失敗,     



管程機制--一種新的進程同步工具    
    雖然信號量機制是一種既方便、又有效的進程同步機制,但每個要訪問臨界資源的進
    程都必須自備同步操作 wait(S)和 signal(S)。這就使大量的同步操作分散在各個進程中。這
    不僅給系統的管理帶來了麻煩,而且還會因同步操作的使用不當而導致系統死鎖。這樣,
    在解決上述問題的過程中,便產生了一種新的進程同步工具——管程(Monitors)。


管程和進程不同,主要體現在以下幾個方面:
    (1) 雖然二者都定義了數據結構,但進程定義的是私有數據結構 PCB,管程定義的是公
    共數據結構,如消息隊列等;
    (2) 二者都存在對各自數據結構上的操作,但進程是由順序程序執行有關的操作,而管
    程主要是進行同步操作和初始化操作;
    (3) 設置進程的目的在於實現系統的併發性,而管程的設置則是解決共享資源的互斥使
    用問題;
    (4) 進程通過調用管程中的過程對共享數據結構實行操作,該過程就如通常的子程序一
    樣被調用,因而管程爲被動工作方式,進程則爲主動工作方式;
    (5) 進程之間能併發執行,而管程則不能與其調用者併發;
    (6) 進程具有動態性,由“創建”而誕生,由“撤銷”而消亡,而管程則是操作系統中
    的一個資源管理模塊,供進程調用。    


    管程好複雜。之後再看,理解。


經典進程的同步問題。  
    生產者-消費者問題、讀者-寫者問題、哲學家進餐問題

    生產者-消費者問題

    1.利用記錄型信號量解決生產者—消費者問題
    假定在生產者和消費者之間的公用緩衝池中,具有 n 個緩衝區,這時可利用互斥信號
    量 mutex 實現諸進程對緩衝池的互斥使用。利用信號量 empty 和 full 分別表示緩衝池中空緩
    衝區和滿緩衝區的數量。又假定這些生產者和消費者相互等效,只要緩衝池未滿,生產者
    便可將消息送入緩衝池;只要緩衝池未空,消費者便可從緩衝池中取走一個消息。對生產
    者—消費者問題可描述如下:
    Var mutex,empty,full: semaphore:=1,n,0;
    buffer:array[0,…,n - 1] of item;
    in,out: integer:=0,0;
    begin
    parbegin
    proceducer: begin
    repeat

    producer an item nextp;

    wait(empty);
    wait(mutex);
    buffer(in):=nextp;
    in:=(in+1) mod n;
    signal(mutex);
    signal(full);
    until false;
    end
    consumer: begin
    repeat
    wait(full);
    wait(mutex);
    nextc:=buffer(out);
    out:=(out+1) mod n;
    signal(mutex);
    signal(empty);
    consumer the item in nextc;
    until false;
    end
    parend
    end

    在生產者—消費者問題中應注意:首先,在每個程序中用於實現互斥的 wait(mutex)和
    signal(mutex)必須成對地出現;其次,對資源信號量 empty 和 full 的 wait 和 signal 操作,同
    樣需要成對地出現,但它們分別處於不同的程序中。例如,wait(empty)在計算進程中,而
    signal(empty)則在打印進程中,計算進程若因執行 wait(empty)而阻塞,則以後將由打印進程
    將它喚醒;最後,在每個程序中的多個 wait 操作順序不能顛倒,應先執行對資源信號量的
    wait 操作,然後再執行對互斥信號量的 wait 操作,否則可能引起進程死鎖。


    利用管程解決生產者—消費者問題
    在利用管程方法來解決生產者—消費者問題時,首先便是爲它們建立一個管程,並命
    名爲 ProclucerConsumer,或簡稱爲 PC。其中包括兩個過程:
    (1) put(item)過程。生產者利用該過程將自己生產的產品投放到緩衝池中,並用整型變
    量 count 來表示在緩衝池中已有的產品數目,當 count≥n 時,表示緩衝池已滿,生產者須
    等待。
    (2) get(item)過程。消費者利用該過程從緩衝池中取出一個產品,當 count≤0 時,表示
    緩衝池中已無可取用的產品,消費者應等待。


    哲學家進餐問題 

    由 Dijkstra 提出並解決的哲學家進餐問題(The Dinning Philosophers Problem)是典型的同
    步問題。該問題是描述有五個哲學家共用一張圓桌,分別坐在周圍的五張椅子上,在圓桌
    上有五個碗和五隻筷子,他們的生活方式是交替地進行思考和進餐。平時,一個哲學家進
    行思考,飢餓時便試圖取用其左右最靠近他的筷子,只有在他拿到兩隻筷子時才能進餐。
    進餐完畢,放下筷子繼續思考。
    1.利用記錄型信號量解決哲學家進餐問題
    經分析可知,放在桌子上的筷子是臨界資源,在一段時間內只允許一位哲學家使用。
    爲了實現對筷子的互斥使用,可以用一個信號量表示一隻筷子,由這五個信號量構成信號
    量數組。其描述如下:

    Var chopstick: array[0,…,4] of semaphore;
    所有信號量均被初始化爲 1,第 i 位哲學家的活動可描述爲:
    repeat
    wait(chopstick[i]);
    wait(chopstick[(i+1)mod 5]);

    eat;

    signal(chopstick[i]);
    signal(chopstick[(i+1)mod 5]);

    think;
    until false;
    在以上描述中,當哲學家飢餓時,總是先去拿他左邊的筷子,即執行 wait(chopstick[i]);
    成功後,再去拿他右邊的筷子,即執行 wait(chopstick[(i+1)mod 5]);又成功後便可進餐。進
    餐完畢,又先放下他左邊的筷子,然後再放右邊的筷子。雖然,上述解法可保證不會有兩
    個相鄰的哲學家同時進餐,但有可能引起死鎖。假如五位哲學家同時飢餓而各自拿起左邊
    的筷子時,就會使五個信號量 chopstick 均爲 0; 當他們再試圖去拿右邊的筷子時,都將因
    無筷子可拿而無限期地等待。對於這樣的死鎖問題,可採取以下幾種解決方法:
    (1) 至多隻允許有四位哲學家同時去拿左邊的筷子,最終能保證至少有一位哲學家能夠
    進餐,並在用畢時能釋放出他用過的兩隻筷子,從而使更多的哲學家能夠進餐。
    (2) 僅當哲學家的左、右兩隻筷子均可用時,才允許他拿起筷子進餐。
    (3) 規定奇數號哲學家先拿他左邊的筷子,然後再去拿右邊的筷子,而偶數號哲學家則
    相反。按此規定,將是 1、2 號哲學家競爭 1 號筷子;3、4 號哲學家競爭 3 號筷子。即五位
    哲學家都先競爭奇數號筷子,獲得後,再去競爭偶數號筷子,最後總會有一位哲學家能獲
    得兩隻筷子而進餐。


    讀者—寫者問題
    一個數據文件或記錄,可被多個進程共享,我們把只要求讀該文件的進程稱爲“Reader
    進程”,其他進程則稱爲“Writer 進程”。允許多個進程同時讀一個共享對象,因爲讀操作不
    會使數據文件混亂。但不允許一個 Writer 進程和其他 Reader 進程或 Writer 進程同時訪問共
    享對象,因爲這種訪問將會引起混亂。所謂“讀者—寫者問題(Reader-Writer Problem)”是
    指保證一個 Writer 進程必須與其他進程互斥地訪問共享對象的同步問題。讀者—寫者問題
    常被用來測試新同步原語。


進程通信:
    進程通信,是指進程之間的信息交換,其
    所交換的信息量少者是一個狀態或數值,
    多者則是成千上萬個字節。進程之間的互斥和同步,
    由於其所交換的信息量少而被歸結爲低級通信。

    在進程互斥中,進程通過只修改信號量
    來向其他進程表明臨界資源是否可用。
    在生產者-消費者問題中,
    生產者通過緩衝池將所生產的產品傳送給消費者。
    應當指出,信號量機制作爲同步工具是卓有成效的。
    但是作爲通信工具,不夠理想。
    主要表現在下面兩點:
        1.效率低:生產者每次只能向緩衝池投放一個產品;
        消費者每次只能從緩衝區中取得一個消息。
        2.通信對用戶不透明。

    進程通信的類型:
    目前,高級通信機制可歸結爲三大類:
    共享存儲器系統、
    消息傳遞系統、
    管道通信系統。


    1.共享存儲器系統
    在共享存儲器系統(Shared-Memory System)中,相互通信的進程共享某些數據結構或共
    享存儲區,進程之間能夠通過這些空間進行通信。據此,又可把它們分成以下兩種類型:
    (1) 基於共享數據結構的通信方式。在這種通信方式中,要求諸進程公用某些數據結構,
    藉以實現諸進程間的信息交換。如在生產者—消費者問題中,就是用有界緩衝區這種數據
    結構來實現通信的。這裏,公用數據結構的設置及對進程間同步的處理,都是程序員的職
    責。這無疑增加了程序員的負擔,而操作系統卻只須提供共享存儲器。因此,這種通信方
    式是低效的,只適於傳遞相對少量的數據。
    (2) 基於共享存儲區的通信方式。爲了傳輸大量數據,在存儲器中劃出了一塊共享存儲
    區,諸進程可通過對共享存儲區中數據的讀或寫來實現通信。這種通信方式屬於高級通信。
    進程在通信前,先向系統申請獲得共享存儲區中的一個分區,並指定該分區的關鍵字;若
    系統已經給其他進程分配了這樣的分區,則將該分區的描述符返回給申請者,繼之,由申
    請者把獲得的共享存儲分區連接到本進程上;此後,便可像讀、寫普通存儲器一樣地讀、
    寫該公用存儲分區。

    2.消息傳遞系統
    消息傳遞系統(Message passing system)是當前應用最爲廣泛的一種進程間的通信機制。
    在該機制中,進程間的數據交換是以格式化的消息(message)爲單位的;在計算機網絡中,
    又把 message 稱爲報文。程序員直接利用操作系統提供的一組通信命令(原語),不僅能實現
    大量數據的傳遞,而且還隱藏了通信的實現細節,使通信過程對用戶是透明的,從而大大
    減化了通信程序編制的複雜性,因而獲得了廣泛的應用。
    特別值得一提的是,在當今最爲流行的微內核操作系統中,微內核與服務器之間的通
    信,無一例外地都採用了消息傳遞機制。又由於它能很好地支持多處理機系統、分佈式系
    統和計算機網絡,因此它也成爲這些領域最主要的通信工具。消息傳遞系統的通信方式屬
    於高級通信方式。又因其實現方式的不同而進一步分成直接通信方式和間接通信方式兩種。

    3.管道通信
    所謂“管道”,是指用於連接一個讀進程和一個寫進程以實現它們之間通信的一個共享
    文件,又名 pipe 文件。向管道(共享文件)提供輸入的發送進程(即寫進程),以字符流形式將
    大量的數據送入管道;而接受管道輸出的接收進程(即讀進程),則從管道中接收(讀)數據。
    由於發送進程和接收進程是利用管道進行通信的,故又稱爲管道通信。這種方式首創於
    UNIX 系統,由於它能有效地傳送大量數據,因而又被引入到許多其它的操作系統中。
    爲了協調雙方的通信,管道機制必須提供以下三方面的協調能力:
    (1) 互斥,即當一個進程正在對 pipe 執行讀/寫操作時,其它(另一)進程必須等待。
    (2) 同步,指當寫(輸入)進程把一定數量(如 4 KB)的數據寫入 pipe,便去睡眠等待,直
    到讀(輸出)進程取走數據後,再把它喚醒。當讀進程讀一空 pipe 時,也應睡眠等待,直至寫
    進程將數據寫入管道後,纔將之喚醒。
    (3) 確定對方是否存在,只有確定了對方已存在時,才能進行通信。    



    消息傳遞通信的實現方法:

    在進程之間通信時,源進程可以直接或間接地將消息傳送給目標進程,由此可將進程
    通信分爲直接通信和間接通信兩種通信方式。
    1.直接通信方式
    這是指發送進程利用 OS 所提供的發送命令,直接把消息發送給目標進程。此時,要求
    發送進程和接收進程都以顯式方式提供對方的標識符。通常,系統提供下述兩條通信命令
    (原語):
    Send(Receiver,message); 發送一個消息給接收進程;
    Receive(Sender,message); 接收 Sender 發來的消息;
    例如,原語 Send(P 2 ,m 1 )表示將消息 m 1 發送給接收進程 P 2 ;而原語 Receive(P 1 ,m 1 )
    則表示接收由 P 1 發來的消息 m 1 。
    在某些情況下,接收進程可與多個發送進程通信,因此,它不可能事先指定發送進程。
    例如,用於提供打印服務的進程,它可以接收來自任何一個進程的“打印請求”消息。對
    於這樣的應用,在接收進程接收消息的原語中,表示源進程的參數,也是完成通信後的返
    回值,接收原語可表示爲:
    Receive (id,message);
    我們還可以利用直接通信原語來解決生產者—消費者問題。當生產者生產出一個產品
    (消息)後,便用 Send 原語將消息發送給消費者進程;而消費者進程則利用 Receive 原語來得
    到一個消息。如果消息尚未生產出來,消費者必須等待,直至生產者進程將消息發送過來。
    生產者—消費者的通信過程可分別描述如下:
    repeat
     ?
    produce an item in nextp;
     ?
    send(consumer,nextp);
    until false;
    repeat
    receive(producer,nextc);
     ?
    consume the item in nextc;
    until false;
    2.間接通信方式
    間接通信方式指進程之間的通信需要通過作爲共享數據結構的實體。該實體用來暫存
    發送進程發送給目標進程的消息;接收進程則從該實體中取出對方發送給自己的消息。通
    常把這種中間實體稱爲信箱。消息在信箱中可以安全地保存,只允許覈準的目標用戶隨時
    讀取。因此,利用信箱通信方式,既可實現實時通信,又可實現非實時通信。
    系統爲信箱通信提供了若干條原語,分別用於信箱的創建、撤消和消息的發送、接收等。
    (1) 信箱的創建和撤消。進程可利用信箱創建原語來建立一個新信箱。創建者進程應給
    出信箱名字、信箱屬性(公用、私用或共享);對於共享信箱,還應給出共享者的名字。當進
    程不再需要讀信箱時,可用信箱撤消原語將之撤消。
    (2) 消息的發送和接收。當進程之間要利用信箱進行通信時,必須使用共享信箱,並利
    用系統提供的下述通信原語進行通信:
    Send(mailbox,message); 將一個消息發送到指定信箱;
    Receive(mailbox,message); 從指定信箱中接收一個消息;
    信箱可由操作系統創建,也可由用戶進程創建,創建者是信箱的擁有者。據此,可把
    信箱分爲以下三類。
    1) 私用信箱
    用戶進程可爲自己建立一個新信箱,並作爲該進程的一部分。信箱的擁有者有權從信
    箱中讀取消息,其他用戶則只能將自己構成的消息發送到該信箱中。這種私用信箱可採用
    單向通信鏈路的信箱來實現。當擁有該信箱的進程結束時,信箱也隨之消失。
    2) 公用信箱
    它由操作系統創建,並提供給系統中的所有核準進程使用。覈准進程既可把消息發送       
    到該信箱中,也可從信箱中讀取發送給自己的消息。顯然,公用信箱應採用雙向通信鏈路
    的信箱來實現。通常,公用信箱在系統運行期間始終存在。
    3) 共享信箱
    它由某進程創建,在創建時或創建後指明它是可共享的,同時須指出共享進程(用戶)
    的名字。信箱的擁有者和共享者都有權從信箱中取走發送給自己的消息。
    在利用信箱通信時,在發送進程和接收進程之間存在以下四種關係:
    (1) 一對一關係。這時可爲發送進程和接收進程建立一條兩者專用的通信鏈路,使兩者
    之間的交互不受其他進程的干擾。
    (2) 多對一關係。允許提供服務的進程與多個用戶進程之間進行交互,也稱爲客戶/服
    務器交互(client/server interaction)。
    (3) 一對多關係。允許一個發送進程與多個接收進程進行交互,使發送進程可用廣播方
    式向接收者(多個)發送消息。
    (4) 多對多關係。允許建立一個公用信箱,讓多個進程都能向信箱中投遞消息;也可從
    信箱中取走屬於自己的消息。



消息傳遞系統實現中的若干問題




消息緩衝隊列通信機制  

    在這種通信機制中,發送進程利用 Send 原語將消息直
    接發送給接收進程;接收進程則利用 Receive 原語接收消息。

    1.消息緩衝隊列通信機制中的數據結構
    1) 消息緩衝區
    在消息緩衝隊列通信方式中,主要利用的數據結構是消息緩衝區。它可描述如下:
    type message buffer=record
    sender  ;發送者進程標識符
    size ; 消息長度
    text ; 消息正文
    next ; 指向下一個消息緩衝區的指針
    end
    2) PCB 中有關通信的數據項
    在操作系統中採用了消息緩衝隊列通信機制時,除了需要爲進程設置消息緩衝隊列外,
    還應在進程的 PCB 中增加消息隊列隊首指針,用於對消息隊列進行操作,以及用於實現同
    步的互斥信號量 mutex 和資源信號量 sm。在 PCB 中應增加的數據項可描述如下:
    type processcontrol block=record
     ?
    mq ; 消息隊列隊首指針
    mutex ; 消息隊列互斥信號量
    sm  ; 消息隊列資源信號量
     ?
    end     




線程:
    如果說,在操作系統中引入進程的目的,是爲了使多個程序能併發執行,以提高資源
    利用率和系統吞吐量,那麼,在操作系統中再引入線程,則是爲了減少程序在併發執行時
    所付出的時空開銷,使 OS 具有更好的併發性。

    由於進程是一個資源的擁有者,因而在創建、撤消和切換中,系統必須爲之
    付出較大的時空開銷。正因如此,在系統中所設置的進程,其數目不宜過多,進程切換的
    頻率也不宜過高,這也就限制了併發程度的進一步提高。

    如何能使多個程序更好地併發執行同時又儘量減少系統的開銷?
    若能將進程的上述兩個
    屬性分開,由操作系統分開處理,亦即對於作爲調度和分派的基本單位,不同時作爲擁有
    資源的單位,以做到“輕裝上陣”;而對於擁有資源的基本單位,又不對之進行頻繁的切換。
    正是在這種思想的指導下,形成了線程的概念。


    比較進程和線程:

    從調度性、併發性、系統開銷和擁有資源等方面對線程和進程進行比較

    1) 調度
    在傳統的操作系統中,作爲擁有資源的基本單位和獨立調度、分派的基本單位都是進
    程。而在引入線程的操作系統中,則把線程作爲調度和分派的基本單位,而進程作爲資源
    擁有的基本單位,把傳統進程的兩個屬性分開,使線程基本上不擁有資源,這樣線程便能
    輕裝前進,從而可顯著地提高系統的併發程度。在同一進程中,線程的切換不會引起進程
    的切換,但從一個進程中的線程切換到另一個進程中的線程時,將會引起進程的切換。
    2) 併發性
    在引入線程的操作系統中,不僅進程之間可以併發執行,而且在一個進程中的多個線
    程之間亦可併發執行,使得操作系統具有更好的併發性,從而能更加有效地提高系統資源
    的利用率和系統的吞吐量。例如,在一個未引入線程的單 CPU 操作系統中,若僅設置一個
    文件服務進程,當該進程由於某種原因而被阻塞時,便沒有其它的文件服務進程來提供服
    務。在引入線程的操作系統中,則可以在一個文件服務進程中設置多個服務線程。當第一
    個線程等待時,文件服務進程中的第二個線程可以繼續運行,以提供文件服務;當第二個
    線程阻塞時,則可由第三個繼續執行,提供服務。顯然,這樣的方法可以顯著地提高文件
    服務的質量和系統的吞吐量。
    3) 擁有資源
    不論是傳統的操作系統,還是引入了線程的操作系統,進程都可以擁有資源,是系統
    中擁有資源的一個基本單位。一般而言,線程自己不擁有系統資源(也有一點必不可少的資
    源),但它可以訪問其隸屬進程的資源,即一個進程的代碼段、數據段及所擁有的系統資源,
    如已打開的文件、I/O 設備等,可以供該進程中的所有線程所共享。
    4) 系統開銷
    在創建或撤消進程時,系統都要爲之創建和回收進程控制塊,分配或回收資源,如內
    存空間和 I/O 設備等,操作系統所付出的開銷明顯大於線程創建或撤消時的開銷。類似地,
    在進程切換時,涉及到當前進程 CPU 環境的保存及新被調度運行進程的 CPU 環境的設置,
    而線程的切換則僅需保存和設置少量寄存器內容,不涉及存儲器管理方面的操作,所以就
    切換代價而言,進程也是遠高於線程的。此外,由於一個進程中的多個線程具有相同的地
    址空間,在同步和通信的實現方面線程也比進程容易。在一些操作系統中,線程的切換、
    同步和通信都無須操作系統內核的干預。


線程的屬性
    在多線程 OS 中,通常是在一個進程中包括多個線程,每個線程都是作爲利用 CPU 的
    基本單位,是花費最小開銷的實體。線程具有下述屬性。
    (1) 輕型實體。線程中的實體基本上不擁有系統資源,只是有一點必不可少的、 能保
    證其獨立運行的資源,比如,在每個線程中都應具有一個用於控制線程運行的線程控制塊
    TCB,用於指示被執行指令序列的程序計數器,保留局部變量、少數狀態參數和返回地址
    等的一組寄存器和堆棧。
    (2) 獨立調度和分派的基本單位。在多線程 OS 中,線程是能獨立運行的基本單位,因
    而也是獨立調度和分派的基本單位。由於線程很“輕”,故線程的切換非常迅速且開銷小。
    (3) 可併發執行。在一個進程中的多個線程之間可以併發執行,甚至允許在一個進程中
    的所有線程都能併發執行;同樣,不同進程中的線程也能併發執行。
    (4) 共享進程資源。在同一進程中的各個線程都可以共享該進程所擁有的資源,這首先
    表現在所有線程都具有相同的地址空間(進程的地址空間)。這意味着線程可以訪問該地址空
    間中的每一個虛地址;此外,還可以訪問進程所擁有的已打開文件、定時器、信號量機構
    等。


線程的狀態
    (1) 狀態參數。在 OS 中的每一個線程都可以利用線程標識符和一組狀態參數進行描述。
    狀態參數通常有這樣幾項:① 寄存器狀態,它包括程序計數器 PC 和堆棧指針中的內容;
    ② 堆棧,在堆棧中通常保存有局部變量和返回地址;③ 線程運行狀態,用於描述線程正
    處於何種運行狀態;④ 優先級,描述線程執行的優先程度;⑤ 線程專有存儲器,用於保
    存線程自己的局部變量拷貝;⑥ 信號屏蔽,即對某些信號加以屏蔽。
    (2) 線程運行狀態。如同傳統的進程一樣,在各線程之間也存在着共享資源和相互合作
    的制約關係,致使線程在運行時也具有間斷性。相應地,線程在運行時也具有下述三種基
    本狀態: ① 執行狀態,表示線程正獲得處理機而運行;② 就緒狀態,指線程已具備了各種
    執行條件,一旦獲得 CPU 便可執行的狀態;③ 阻塞狀態,指線程在執行中因某事件而受
    阻,處於暫停執行時的狀態。   


線程的創建和終止
    在多線程 OS 環境下,應用程序在啓動時,通常僅有一個線程在執行,該線程被人們稱
    爲“初始化線程”。它可根據需要再去創建若干個線程。在創建新線程時,需要利用一個線
    程創建函數(或系統調用),並提供相應的參數,如指向線程主程序的入口指針、堆棧的大
    小,以及用於調度的優先級等。在線程創建函數執行完後,將返回一個線程標識符供以後
    使用。
    如同進程一樣,線程也是具有生命期的。終止線程的方式有兩種:一種是在線程完成
    了自己的工作後自願退出;另一種是線程在運行中出現錯誤或由於某種原因而被其它線程
    強行終止。但有些線程(主要是系統線程),在它們一旦被建立起來之後,便一直運行下去而
    不再被終止。在大多數的 OS 中,線程被中止後並不立即釋放它所佔有的資源,只有當進程
    中的其它線程執行了分離函數後,被終止的線程才與資源分離,此時的資源才能被其它線
    程利用。
    雖已被終止但尚未釋放資源的線程,仍可以被需要它的線程所調用,以使被終止線程
    重新恢復運行。爲此,調用者線程須調用一條被稱爲“等待線程終止”的連接命令,來與
    該線程進行連接。如果在一個調用者線程調用“等待線程終止”的連接命令試圖與指定線
    程相連接時,若指定線程尚未被終止,則調用連接命令的線程將會阻塞,直至指定線程被
    終止後才能實現它與調用者線程的連接並繼續執行;若指定線程已被終止,則調用者線程
    不會被阻塞而是繼續執行。    


線程間的同步和通信   

    爲了支持不同頻率的交互操作和不同程度的並行性,在多線程 OS 中通常提供多
    種同步機制,如互斥鎖、條件變量、計數信號量以及多讀、單寫鎖等。


    1.互斥鎖(mutex)
    互斥鎖是一種比較簡單的、用於實現線程間對資源互斥訪問的機制。由於操作互斥鎖
    的時間和空間開銷都較低,因而較適合於高頻度使用的關鍵共享數據和程序段。互斥鎖可
    以有兩種狀態,即開鎖(unlock)和關鎖(lock)狀態。相應地,可用兩條命令(函數)對互斥鎖進
    行操作。其中的關鎖 lock 操作用於將 mutex 關上,開鎖操作 unlock 則用於打開 mutex。
    當一個線程需要讀/寫一個共享數據段時,線程首先應爲該數據段所設置的 mutex 執行
    關鎖命令。命令首先判別 mutex 的狀態,如果它已處於關鎖狀態,則試圖訪問該數據段的
    線程將被阻塞;而如果 mutex 是處於開鎖狀態,則將 mutex 關上後便去讀/寫該數據段。在
    線程完成對數據的讀/寫後,必須再發出開鎖命令將 mutex 打開,同時還須將阻塞在該互斥
    鎖上的一個線程喚醒,其它的線程仍被阻塞在等待 mutex 打開的隊列上。
    另外,爲了減少線程被阻塞的機會,在有的系統中還提供了一種用於 mutex 上的操作
    命令 Trylock。當一個線程在利用 Trylock 命令去訪問 mutex 時,若 mutex 處於開鎖狀態,
    Trylock 將返回一個指示成功的狀態碼;反之,若 mutex 處於關鎖狀態,則 Trylock 並不會
    阻塞該線程,而只是返回一個指示操作失敗的狀態碼。
    2.條件變量
    在許多情況下,只利用 mutex 來實現互斥訪問可能會引起死鎖,我們通過一個例子來
    說明這一點。有一個線程在對 mutex 1 執行關鎖操作成功後,便進入一臨界區 C,若在臨界
    區內該線程又須訪問某個臨界資源 R,同樣也爲 R 設置另一互斥鎖 mutex 2。假如資源 R 此
    時正處於忙碌狀態,線程在對 mutex 2 執行關鎖操作後必將被阻塞,這樣將使 mutex 1 一直
    保持關鎖狀態;如果保持了資源 R 的線程也要求進入臨界區 C,但由於 mutex 1 一直保持關
    鎖狀態而無法進入臨界區,這樣便形成了死鎖。爲了解決這個問題便引入了條件變量。
    每一個條件變量通常都與一個互斥鎖一起使用,亦即,在創建一個互斥鎖時便聯繫着
    一個條件變量。單純的互斥鎖用於短期鎖定,主要是用來保證對臨界區的互斥進入。而條
    件變量則用於線程的長期等待,直至所等待的資源成爲可用的資源。
    現在,我們看看如何利用互斥鎖和條件變量來實現對資源 R 的訪問。線程首先對 mutex
    執行關鎖操作,若成功便進入臨界區,然後查找用於描述該資源狀態的數據結構,以瞭解
    資源的情況。只要發現所需資源 R 正處於忙碌狀態,線程便轉爲等待狀態,並對 mutex 執
    行開鎖操作後,等待該資源被釋放;若資源處於空閒狀態,表明線程可以使用該資源,於
    是將該資源設置爲忙碌狀態,再對 mutex 執行開鎖操作。下面給出了對上述資源的申請(左
    半部分)和釋放(右半部分)操作的描述。
    Lock mutex Lock mutex
    check data structures; mark resource as free;
    while(resource busy); unlock mutex;
    wait(condition variable); wakeup(condition variable);
    mark resource as busy;
    unlock mutex;
    原來佔有資源 R 的線程在使用完該資源後,便按照右半部分的描述釋放該資源,其中
    的 wakeup(condition variable)表示去喚醒在指定條件變量上等待的一個或多個線程。在大多
    數情況下,由於所釋放的是臨界資源,此時所喚醒的只能是在條件變量上等待的某一個線
    程,其它線程仍繼續在該隊列上等待。但如果線程所釋放的是一個數據文件,該文件允許
    多個線程同時對它執行讀操作。在這種情況下,當一個寫線程完成寫操作並釋放該文件後,
    如果此時在該條件變量上還有多個讀線程在等待,則該線程可以喚醒所有的等待線程。      



    信號量機制
        前面所介紹的用於實現進程同步的最常用工具——信號量機制,也可用於多線程 OS
        中,實現諸線程或進程之間的同步。爲了提高效率,可爲線程和進程分別設置相應的信
        號量。

3.處理機調度與死鎖

在多道程序環境下,主存中有多個進程,
其數目往往多於處理機數目。
這就要求系統能按某種算法,
動態地把處理機分配給就緒隊列中的一個進程,
使之執行。
分配處理機的任務是由處理機調度程序完成的。

    1.處理機調度的層次
    在多道程序系統中,一個作業被提交後必須經過處理機調度後,方能獲得處理機執行。
    對於批量型作業而言,通常需要經歷作業調度(又稱高級調度或長程調度)和進程調度(又稱
    低級調度或短程調度)兩個過程後方能獲得處理機;對於終端型作業,則通常只需經過進程
    調度即可獲得處理機。在較完善的操作系統中,爲提高內存的利用率,往往還設置了中級
    調度(又稱中程調度)。對於上述的每一級調度,又都可採用不同的調度方式和調度算法。對
    於一個批處理型作業,從進入系統並駐留在外存的後備隊列開始,直至作業運行完畢,可
    能要經歷上述的三級調度。本節主要是對處理機調度層次做較詳細的介紹。

    作業調度
    作業調度的主要功能是根據作業控制塊中的信息,審查系統能否滿足用戶作業的資源
    需求,以及按照一定的算法,從外存的後備隊列中選取某些作業調入內存,併爲它們創建
    進程、分配必要的資源。然後再將新創建的進程插入就緒隊列,準備執行。因此,有時也
    把作業調度稱爲接納調度(Admission Scheduling)。

    低級調度的功能
    低級調度用於決定就緒隊列中的哪個進程(或內核級線程,爲敘述方便,以後只寫進程)
    應獲得處理機,然後再由分派程序執行把處理機分配給該進程的具體操作。
    低級調度的主要功能如下:
    (1) 保存處理機的現場信息。在進程調度進行調度時,首先需要保存當前進程的處理機
    的現場信息,如程序計數器、多個通用寄存器中的內容等,將它們送入該進程的進程控制
    塊(PCB)中的相應單元。
    (2) 按某種算法選取進程。低級調度程序按某種算法如優先數算法、輪轉法等,從就緒
    隊列中選取一個進程,把它的狀態改爲運行狀態,並準備把處理機分配給它。
    (3) 把處理器分配給進程。由分派程序(Dispatcher)把處理器分配給進程。此時需爲選中
    的進程恢復處理機現場,即把選中進程的進程控制塊內有關處理機現場的信息裝入處理器
    相應的各個寄存器中,把處理器的控制權交給該進程,讓它從取出的斷點處開始繼續運行。


    進程調度中的三個基本機制
    爲了實現進程調度,應具有如下三個基本機制:
    (1) 排隊器。爲了提高進程調度的效率,應事先將系統中所有的就緒進程按照一定的方
    式排成一個或多個隊列,以便調度程序能最快地找到它。
    (2) 分派器(分派程序)。分派器把由進程調度程序所選定的進程,從就緒隊列中取出該
    進程,然後進行上下文切換,將處理機分配給它。
    (3) 上下文切換機制。當對處理機進行切換時,會發生兩對上下文切換操作。在第一對
    上下文切換時,操作系統將保存當前進程的上下文,而裝入分派程序的上下文,以便分派
    程序運行;在第二對上下文切換時,將移出分派程序,而把新選進程的 CPU 現場信息裝入
    到處理機的各個相應寄存器中。


    進程調度方式
    進程調度可採用下述兩種調度方式。
    1) 非搶佔方式(Nonpreemptive Mode)
    在採用這種調度方式時,一旦把處理機分配給某進程後,不管它要運行多長時間,都
    一直讓它運行下去,決不會因爲時鐘中斷等原因而搶佔正在運行進程的處理機,也不允許
    其它進程搶佔已經分配給它的處理機。直至該進程完成,自願釋放處理機,或發生某事件
    而被阻塞時,纔再把處理機分配給其他進程。
    在採用非搶佔調度方式時,可能引起進程調度的因素可歸結爲如下幾個:
    (1) 正在執行的進程執行完畢,或因發生某事件而不能再繼續執行;
    (2) 執行中的進程因提出 I/O 請求而暫停執行;
    (3) 在進程通信或同步過程中執行了某種原語操作,如 P 操作(wait 操作)、Block 原語、
    Wakeup 原語等。
    這種調度方式的優點是實現簡單,系統開銷小,適用於大多數的批處理系統環境。但
    它難以滿足緊急任務的要求——立即執行,因而可能造成難以預料的後果。顯然,在要求
    比較嚴格的實時系統中,不宜採用這種調度方式。
    2) 搶佔方式(Preemptive Mode)
    這種調度方式允許調度程序根據某種原則去暫停某個正在執行的進程,將已分配給該
    進程的處理機重新分配給另一進程。搶佔方式的優點是,可以防止一個長進程長時間佔用
    處理機,能爲大多數進程提供更公平的服務,特別是能滿足對響應時間有着較嚴格要求的
    實時任務的需求。但搶佔方式比非搶佔方式調度所需付出的開銷較大。搶佔調度方式是基
    於一定原則的,主要有如下幾條:
    (1) 優先權原則。通常是對一些重要的和緊急的作業賦予較高的優先權。當這種作業到
    達時,如果其優先權比正在執行進程的優先權高,便停止正在執行(當前)的進程,將處理機
    分配給優先權高的新到的進程,使之執行;或者說,允許優先權高的新到進程搶佔當前進
    程的處理機。
    (2) 短作業(進程)優先原則。當新到達的作業(進程)比正在執行的作業(進程)明顯的短
    時,將暫停當前長作業(進程)的執行,將處理機分配給新到的短作業(進程),使之優先執行;
    或者說,短作業(進程)可以搶佔當前較長作業(進程)的處理機。
    (3) 時間片原則。各進程按時間片輪流運行,當一個時間片用完後,便停止該進程的執
    行而重新進行調度。這種原則適用於分時系統、大多數的實時系統,以及要求較高的批處
    理系統。


    進程調度的運行頻率最高,
    爲避免進程調度佔用太多的CPU時間,
    進程調度算法不宜太複雜。

    僅有進程調度的調度隊列模型
    在分時系統中,通常僅設置了進程調度,用戶鍵入的命令和數據都直接送入內存。對
    於命令,是由 OS 爲之建立一個進程。系統可以把處於就緒狀態的進程組織成棧、樹或一個
    無序鏈表,至於到底採用其中哪種形式,則與 OS 類型和所採用的調度算法有關。例如,在
    分時系統中,常把就緒進程組織成 FIFO 隊列形式。每當 OS 創建一個新進程時,便將它掛
    在就緒隊列的末尾,然後按時間片輪轉方式運行。
    每個進程在執行時都可能出現以下三種情況:
    (1) 任務在給定的時間片內已經完成,該進程便在釋放處理機後進入完成狀態;
    (2) 任務在本次分得的時間片內尚未完成,OS 便將該任務再放入就緒隊列的末尾;
    (3) 在執行期間,進程因爲某事件而被阻塞後,被 OS 放入阻塞隊列。



    具有高級和低級調度的調度隊列模型
    在批處理系統中,不僅需要進程調度,而且還需有作業調度,由後者按一定的作業調度
    算法,從外存的後備隊列中選擇一批作業調入內存,併爲它們建立進程,送入就緒隊列,然
    後才由進程調度按照一定的進程調度算法選擇一個進程,把處理機分配給該進程。圖 3-2 示
    出了具有高、低兩級調度的調度隊列模型。該模型與上一模型的主要區別在於如下兩個方面。
    (1) 就緒隊列的形式。在批處理系統中,最常用的是最高優先權優先調度算法,相應地,
    最常用的就緒隊列形式是優先權隊列。進程在進入優先級隊列時,根據其優先權的高低,
    被插入具有相應優先權的位置上,這樣,調度程序總是把處理機分配給就緒隊列中的隊首
    進程。在最高優先權優先的調度算法中,也可採用無序鏈表方式,即每次把新到的進程掛
    在鏈尾,而調度程序每次調度時,是依次比較該鏈中各進程的優先權,從中找出優先權最
    高的進程,將之從鏈中摘下,並把處理機分配給它。顯然,無序鏈表方式與優先權隊列相
    比,這種方式的調度效率較低。
    2) 設置多個阻塞隊列。對於小型系統,可以只設置一個阻塞隊列;但當系統較大時,
    若仍只有一個阻塞隊列,其長度必然會很長,隊列中的進程數可以達到數百個,這將嚴重
    影響對阻塞隊列操作的效率。故在大、中型系統中通常都設置了若干個阻塞隊列,每個隊
    列對應於某一種進程阻塞事件。



調度算法
    在 OS 中調度的實質是一種資源分配,因而調度算法是指:根據系統的資源分配策略所
    規定的資源分配算法。對於不同的系統和系統目標,通常採用不同的調度算法,例如,在
    批處理系統中,爲了照顧爲數衆多的短作業,應採用短作業優先的調度算法;又如在分時
    系統中,爲了保證系統具有合理的響應時間,應採用輪轉法進行調度。目前存在的多種調
    度算法中,有的算法適用於作業調度,有的算法適用於進程調度;但也有些調度算法既可
    用於作業調度,也可用於進程調度。


    先來先服務和短作業(進程)優先調度算法
    1.先來先服務調度算法
    先來先服務(FCFS)調度算法是一種最簡單的調度算法,該算法既可用於作業調度,也
    可用於進程調度。當在作業調度中採用該算法時,每次調度都是從後備作業隊列中選擇一
    個或多個最先進入該隊列的作業,將它們調入內存,爲它們分配資源、創建進程,然後放
    入就緒隊列。在進程調度中採用 FCFS 算法時,則每次調度是從就緒隊列中選擇一個最先進
    入該隊列的進程,爲之分配處理機,使之投入運行。該進程一直運行到完成或發生某事件
    而阻塞後才放棄處理機。
    FCFS 算法比較有利於長作業(進程),而不利於短作業(進程)。下表列出了 A、B、C、
    D 四個作業分別到達系統的時間、要求服務的時間、開始執行的時間及各自的完成時間,
    並計算出各自的週轉時間和帶權週轉時間。

    短作業(進程)優先調度算法
    短作業(進程)優先調度算法 SJ(P)F,是指對短作業或短進程優先調度的算法。它們可以
    分別用於作業調度和進程調度。短作業優先(SJF)的調度算法是從後備隊列中選擇一個或若
    幹個估計運行時間最短的作業,將它們調入內存運行。而短進程優先(SPF)調度算法則是從
    就緒隊列中選出一個估計運行時間最短的進程,將處理機分配給它,使它立即執行並一直
    執行到完成,或發生某事件而被阻塞放棄處理機時再重新調度。        



    基於時間片的輪轉調度算法
    如前所述,在分時系統中,爲保證能及時響應用戶的請求,必須採用基於時間片的輪
    轉式進程調度算法。在早期,分時系統中採用的是簡單的時間片輪轉法;進入 20 世紀 90
    年代後,廣泛採用多級反饋隊列調度算法。
    1.時間片輪轉法
    1) 基本原理
    在早期的時間片輪轉法中,系統將所有的就緒進程按先來先服務的原則排成一個隊列,
    每次調度時,把 CPU 分配給隊首進程,並令其執行一個時間片。時間片的大小從幾 ms 到
    幾百 ms。當執行的時間片用完時,由一個計時器發出時鐘中斷請求,調度程序便據此信號
    來停止該進程的執行,並將它送往就緒隊列的末尾;然後,再把處理機分配給就緒隊列中
    新的隊首進程,同時也讓它執行一個時間片。這樣就可以保證就緒隊列中的所有進程在一
    給定的時間內均能獲得一時間片的處理機執行時間。換言之,系統能在給定的時間內響應
    所有用戶的請求。
    2) 時間片大小的確定
    在時間片輪轉算法中,時間片的大小對系統性能有很大的影響,如選擇很小的時間片
    將有利於短作業,因爲它能較快地完成,但會頻繁地發生中斷、進程上下文的切換,從而
    增加系統的開銷;反之,如選擇太長的時間片,使得每個進程都能在一個時間片內完成,
    時間片輪轉算法便退化爲 FCFS 算法,無法滿足交互式用戶的需求。一個較爲可取的大小是,
    時間片略大於一次典型的交互所需要的時間。這樣可使大多數進程在一個時間片內完成。 




實時調度
    採用搶佔式調度機制
    在含有硬實時任務的實時系統中,廣泛採用搶佔機制。當一個優先權更高的任務到達
    時,允許將當前任務暫時掛起,而令高優先權任務立即投入運行,這樣便可滿足該硬實時
    任務對截止時間的要求。但這種調度機制比較複雜。
    對於一些小型實時系統,如果能預知任務的開始截止時間,則對實時任務的調度可採
    用非搶佔調度機制,以簡化調度程序和對任務調度時所花費的系統開銷。但在設計這種調
    度機制時,應使所有的實時任務都比較小,並在執行完關鍵性程序和臨界區後,能及時地
    將自己阻塞起來,以便釋放出處理機,供調度程序去調度那種開始截止時間即將到達的
    任務。



產生死鎖的原因和必要條件        
    產生死鎖的原因可歸結爲以下兩點:
    1.競爭資源。
    當系統中供多個進程共享的資源
    如打印機、公用隊列等,
    其數目不足以滿足諸進程的需要時,
    會引起諸進程對資源的競爭而產生死鎖。

    2.進程間推進順序非法。
    進程在運行過程中,
    請求和釋放資源的順序不當,
    也同樣會導致產生進程死鎖。


    1.競爭資源引起進程死鎖
    1) 可剝奪和非剝奪性資源
    可把系統中的資源分成兩類,一類是可剝奪性資源,是指某進程在獲得這類資源後,
    該資源可以再被其他進程或系統剝奪。例如,優先權高的進程可以剝奪優先權低的進程的
    處理機。又如,內存區可由存儲器管理程序把一個進程從一個存儲區移到另一個存儲區,
    此即剝奪了該進程原來佔有的存儲區。甚至可將一個進程從內存調出到外存上。可見,CPU
    和主存均屬於可剝奪性資源。另一類資源是不可剝奪性資源,當系統把這類資源分配給某
    進程後,再不能強行收回,只能在進程用完後自行釋放,如磁帶機、打印機等。
    2) 競爭非剝奪性資源
    在系統中所配置的非剝奪性資源,由於它們的數量不能滿足諸進程運行的需要,會使
    進程在運行過程中,因爭奪這些資源而陷入僵局。例如,系統中只有一臺打印機 R 1 和一臺
    磁帶機 R 2 ,可供進程 P 1 和 P 2 共享。假定 P 1 已佔用了打印機 R 1 ,P 2 已佔用了磁帶機 R 2 。此
    時,若 P 2 繼續要求打印機,P 2 將阻塞;P 1 若又要求磁帶機,P 1 也將阻塞。於是,在 P 1 與
    P 2 之間便形成了僵局,兩個進程都在等待對方釋
    放出自己所需的資源。但它們又都因不能繼續獲
    得自己所需的資源而不能繼續推進,從而也不能
    釋放出自己已佔有的資源,以致進入死鎖狀態。
    爲便於說明,我們用方塊代表資源,用圓圈代表
    進程,見圖 3-13 所示。當箭頭從進程指向資源
    時,表示進程請求資源;當箭頭從資源指向進程
    時,表示該資源已被分配給該進程。從中可以看
    出,這時在 P 1 、P 2 及 R 1 和 R 2 之間已經形成了一
    個環路,說明已進入死鎖狀態。      


    2) 進程推進順序非法
    若併發進程 P 1 和 P 2 按曲線④所示的順序推進,它們將進入不安全區 D 內。此時 P 1 保
    持了資源 R 1 ,P 2 保持了資源 R 2 ,系統處於不安全狀態。因爲這時兩進程再向前推進,便可
    能發生死鎖。例如,當 P 1 運行到 P 1 :Request(R 2 )時,將因 R 2 已被 P 2 佔用而阻塞;當 P 2 運
    行到 P 2 :Request(R 1 )時,也將因 R 1 已被 P 1 佔用而阻塞,於是發生了進程死鎖。


    產生死鎖的必要條件
    雖然進程在運行過程中可能發生死鎖,但死鎖的發生也必須具備一定的條件。綜上所
    述不難看出,死鎖的發生必須具備下列四個必要條件。
    (1) 互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由
    一個進程佔用。如果此時還有其它進程請求該資源,則請求者只能等待,直至佔有該資源
    的進程用畢釋放。
    (2) 請求和保持條件:指進程已經保持了至少一個資源,但又提出了新的資源請求,而
    該資源又已被其它進程佔有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。
    (3) 不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完
    時由自己釋放。
    (4) 環路等待條件:指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集
    合{P 0 ,P 1 ,P 2 ,…,P n }中的 P 0 正在等待一個 P 1 佔用的資源; P 1 正在等待 P 2 佔用的資源,……,
    P n 正在等待已被 P 0 佔用的資源。



    處理死鎖的基本方法
    爲保證系統中諸進程的正常運行,應事先採取必要的措施,來預防發生死鎖。在系統
    中已經出現死鎖後,則應及時檢測到死鎖的發生,並採取適當措施來解除死鎖。目前,處
    理死鎖的方法可歸結爲以下四種:
    (1) 預防死鎖。這是一種較簡單和直觀的事先預防的方法。該方法是通過設置某些限制
    條件,去破壞產生死鎖的四個必要條件中的一個或幾個條件,來預防發生死鎖。預防死鎖
    是一種較易實現的方法,已被廣泛使用。但由於所施加的限制條件往往太嚴格,因而可能
    會導致系統資源利用率和系統吞吐量降低。
    (2) 避免死鎖。該方法同樣是屬於事先預防的策略,但它並不須事先採取各種限制措施
    去破壞產生死鎖的四個必要條件,而是在資源的動態分配過程中,用某種方法去防止系統
    進入不安全狀態,從而避免發生死鎖。這種方法只需事先施加較弱的限制條件,便可獲得
    較高的資源利用率及系統吞吐量,但在實現上有一定的難度。目前在較完善的系統中常用
    此方法來避免發生死鎖。
    (3) 檢測死鎖。這種方法並不須事先採取任何限制性措施,也不必檢查系統是否已經進
    入不安全區,而是允許系統在運行過程中發生死鎖。但可通過系統所設置的檢測機構,及
    時地檢測出死鎖的發生,並精確地確定與死鎖有關的進程和資源; 然後,採取適當措施,
    從系統中將已發生的死鎖清除掉。
    (4) 解除死鎖。這是與檢測死鎖相配套的一種措施。當檢測到系統中已發生死鎖時,須
    將進程從死鎖狀態中解脫出來。常用的實施方法是撤消或掛起一些進程,以便回收一些資
    源,再將這些資源分配給已處於阻塞狀態的進程,使之轉爲就緒狀態,以繼續運行。死鎖
    的檢測和解除措施有可能使系統獲得較好的資源利用率和吞吐量,但在實現上難度也最大。        






    利用銀行家算法避免死鎖
    最有代表性的避免死鎖的算法,是 Dijkstra 的銀行家算法。這是由於該算法能用於銀行
    系統現金貸款的發放而得名的。爲實現銀行家算法,系統中必須設置若干數據結構。

    詳見P120

死鎖的檢測與解除

    (1) 保存有關資源的請求和分配信息;
    (2) 提供一種算法,以利用這些信息來檢測系統是否已進入死鎖狀態。

    死鎖定理
    我們可以利用把資源分配圖加以簡化的方法(圖 3-21),來檢測當系統處於 S 狀態時是否
    爲死鎖狀態。簡化方法如下:
    (1) 在資源分配圖中,找出一個既不阻塞又非獨立的進程結點 P i 。在順利的情況下,P i
    可獲得所需資源而繼續運行,直至運行完畢,再釋放其所佔有的全部資源,這相當於消去
    p i 所求的請求邊和分配邊,使之成爲孤立的結點。
    (2) p 1 釋放資源後,便可使 p 2 獲得資源而繼續運行,直至 p 2 完成後又釋放出它所佔有
    的全部資源,形成圖(c)所示的情況。
    (3) 在進行一系列的簡化後,若能消去圖中所有的邊,使所有的進程結點都成爲孤立結
    點,則稱該圖是可完全簡化的;若不能通過任何過程使該圖完全簡化,則稱該圖是不可完
    全簡化的。
    對於較複雜的資源分配圖,可能有多個既未阻塞,又非孤立的進程結點,不同的簡化
    順序是否會得到不同的簡化圖?有關文獻已經證明,所有的簡化順序,都將得到相同的不
    可簡化圖。同樣可以證明:S 爲死鎖狀態的充分條件是:當且僅當 S 狀態的資源分配圖是不
    可完全簡化的。該充分條件被稱爲死鎖定理。


    死鎖檢測中的數據結構
    死鎖檢測中的數據結構類似於銀行家算法中的數據結構:
    (1) 可利用資源向量 Available,它表示了 m 類資源中每一類資源的可用數目。
    (2) 把不佔用資源的進程(向量 Allocation i :=0)記入 L 表中,即 L i ∪L。
    (3) 從進程集合中找到一個 Request i ≤Work 的進程,做如下處理:
    ① 將其資源分配圖簡化,釋放出資源,增加工作向量 Work:=Work + Allocation  i 。
    ② 將它記入 L 表中。
    (4) 若不能把所有進程都記入 L 表中,便表明系統狀態 S 的資源分配圖是不可完全簡化
    的。因此,該系統狀態將發生死鎖。


    死鎖的解除
    當發現有進程死鎖時,便應立即把它們從死鎖狀態中解脫出來。常採用解除死鎖的兩
    種方法是:
    (1) 剝奪資源。從其它進程剝奪足夠數量的資源給死鎖進程,以解除死鎖狀態。
    (2) 撤消進程。最簡單的撤消進程的方法是使全部死鎖進程都夭折掉;稍微溫和一點的
    方法是按照某種順序逐個地撤消進程,直至有足夠的資源可用,使死鎖狀態消除爲止。
    在出現死鎖時,可採用各種策略來撤消進程。例如,爲解除死鎖狀態所需撤消的進
    程數目最小;或者,撤消進程所付出的代價最小等。一種付出最小代價的方法如圖 3-22
    所示。 

4.存儲器管理

多級存儲器結構:
    對於通用計算機而言,存儲層次至少應具有三級:最高層爲 CPU 寄存器,中間爲主存,
    最底層是輔存。在較高檔的計算機中,還可以根據具體的功能分工細劃爲寄存器、高速緩
    存、主存儲器、磁盤緩存、固定磁盤、可移動存儲介質等 6 層


    主存儲器
    主存儲器(簡稱內存或主存)是計算機系統中一個主要部件,用於保存進程運行時的程序
    和數據,也稱可執行存儲器,其容量對於當前的微機系統和大中型機,可能一般爲數十 MB
    到數 GB,而且容量還在不斷增加,而嵌入式計算機系統一般僅有幾十 KB 到幾 MB。CPU
    的控制部件只能從主存儲器中取得指令和數據,數據能夠從主存儲器讀取並將它們裝入到
    寄存器中,或者從寄存器存入到主存儲器。CPU 與外圍設備交換的信息一般也依託於主存
    儲器地址空間。由於主存儲器的訪問速度遠低於 CPU 執行指令的速度,爲緩和這一矛盾,
    在計算機系統中引入了寄存器和高速緩存。


    寄存器
    寄存器訪問速度最快,完全能與 CPU 協調工作,但價格卻十分昂貴,因此容量不可能
    做得很大。寄存器的長度一般以字(word)爲單位。寄存器的數目,對於當前的微機系統和大
    中型機,可能有幾十個甚至上百個;而嵌入式計算機系統一般僅有幾個到幾十個。寄存器
    用於加速存儲器的訪問速度,如用寄存器存放操作數,或用作地址寄存器加快地址轉換速
    度等。

    高速緩存是現代計算機結構中的一個重要部件,其容量大於或遠大於寄存器,而比內
    存約小兩到三個數量級左右,從幾十 KB 到幾 MB,訪問速度快於主存儲器。
    根據程序執行的局部性原理(即程序在執行時將呈現出局部性規律,在一較短的時間內,
    程序的執行僅侷限於某個部分),將主存中一些經常訪問的信息存放在高速緩存中,減少訪
    問主存儲器的次數,可大幅度提高程序執行速度。通常,進程的程序和數據是存放在主存
    儲器中,每當使用時,被臨時複製到一個速度較快的高速緩存中。當 CPU 訪問一組特定信
    息時,首先檢查它是否在高速緩存中,如果已存在,可直接從中取出使用,以避免訪問主
    存,否則,再從主存中讀出信息。如大多數計算機有指令高速緩存,用來暫存下一條欲執
    行的指令,如果沒有指令高速緩存,CPU 將會空等若干個週期,直到下一條指令從主存中
    取出。由於高速緩存的速度越高價格也越貴,故有的計算機系統中設置了兩級或多級高速
    緩存。緊靠內存的一級高速緩存的速度最高,而容量最小,二級高速緩存的容量稍大,速
    度也稍低。


程序的裝入和鏈接
    在多道程序環境下,要使程序運行,必須先爲之創建進程。而創建進程的第一件事,
    便是將程序和數據裝入內存。如何將一個用戶源程序變爲一個可在內存中執行的程序,通
    常都要經過以下幾個步驟:首先是要編譯,由編譯程序(Compiler)將用戶源代碼編譯成若干
    個目標模塊(Object Module);其次是鏈接,由鏈接程序(Linker)將編譯後形成的一組目標模
    塊,以及它們所需要的庫函數鏈接在一起,形成一個完整的裝入模塊(Load Module);最後
    是裝入,由裝入程序(Loader)將裝入模塊裝入內存。


    在將一個裝入模塊裝入內存時,可以有絕對裝入方式、可重定位
    裝入方式和動態運行時裝入方式,

    1.絕對裝入方式(Absolute Loading Mode)
    在編譯時,如果知道程序將駐留在內存的什麼位置,那麼,編譯程序將產生絕對地址
    的目標代碼。例如,事先已知用戶程序(進程)駐留在從 R 處開始的位置,則編譯程序所產生
    的目標模塊(即裝入模塊)便從 R 處開始向上擴展。絕對裝入程序按照裝入模塊中的地址,將
    程序和數據裝入內存。裝入模塊被裝入內存後,由於程序中的邏輯地址與實際內存地址完
    全相同,故不須對程序和數據的地址進行修改。
    程序中所使用的絕對地址,既可在編譯或彙編時給出,也可由程序員直接賦予。但在
    由程序員直接給出絕對地址時,不僅要求程序員熟悉內存的使用情況,而且一旦程序或數
    據被修改後,可能要改變程序中的所有地址。因此,通常是寧可在程序中採用符號地址,
    然後在編譯或彙編時,再將這些符號地址轉換爲絕對地址。

    2.可重定位裝入方式(Relocation Loading Mode)
    絕對裝入方式只能將目標模塊裝入到內存中事先指定的位置。在多道程序環境下,編
    譯程序不可能預知所編譯的目標模塊應放在內存的何處,因此,絕對裝入方式只適用於單
    道程序環境。在多道程序環境下,所得到的目標模塊的起始地址通常是從 0 開始的,程序
    中的其它地址也都是相對於起始地址計算的。此時應採用可重定位裝入方式,根據內存的
    當前情況,將裝入模塊裝入到內存的適當位置。
    值得注意的是,在採用可重定位裝入程序將
    裝入模塊裝入內存後,會使裝入模塊中的所有邏
    輯地址與實際裝入內存的物理地址不同,圖 4-3
    示出了這一情況。例如,在用戶程序的 1000 號
    單元處有一條指令 LOAD 1,2500,該指令的功
    能是將 2500 單元中的整數 365 取至寄存器 1。
    但若將該用戶程序裝入到內存的 10000~15000
    號單元而不進行地址變換,則在執行 11000 號單
    元中的指令時,它將仍從 2500 號單元中把數據
    取至寄存器 1 而導致數據錯誤。由圖 4-3 可見,
    正確的方法應該是將取數指令中的地址 2500 修
    改成 12500,即把指令中的相對地址 2500 與本程序在內存中的起始地址 10000 相加,才得
    到正確的物理地址 12500。除了數據地址應修改外,指令地址也須做同樣的修改,即將指令
    的相對地址 1000 與起始地址 10000 相加,得到絕對地址 11000。通常是把在裝入時對目標
    程序中指令和數據的修改過程稱爲重定位。又因爲地址變換通常是在裝入時一次完成的,
    以後不再改變,故稱爲靜態重定位。

    3.動態運行時裝入方式(Dynamic Run-time Loading)
    可重定位裝入方式可將裝入模塊裝入到內存中任何允許的位置,故可用於多道程序環
    境;但這種方式並不允許程序運行時在內存中移動位置。因爲,程序在內存中的移動,意
    味着它的物理位置發生了變化,這時必須對程序和數據的地址(是絕對地址)進行修改後方能
    運行。然而,實際情況是,在運行過程中它在內存中的位置可能經常要改變,此時就應採
    用動態運行時裝入的方式。

    動態運行時的裝入程序在把裝入模塊裝入內存後,並不立即把裝入模塊中的相對地址
    轉換爲絕對地址,而是把這種地址轉換推遲到程序真正要執行時才進行。因此,裝入內存
    後的所有地址都仍是相對地址。爲使地址轉換不影響指令的執行速度,這種方式需要一個
    重定位寄存器的支持,

程序的鏈接
    源程序經過編譯後,可得到一組目標模塊,再利用鏈接程序將這組目標模塊鏈接,形
    成裝入模塊。根據鏈接時間的不同,可把鏈接分成如下三種:
    (1) 靜態鏈接。在程序運行之前,先將各目標模塊及它們所需的庫函數,鏈接成一個完
    整的裝配模塊,以後不再拆開。我們把這種事先進行鏈接的方式稱爲靜態鏈接方式。
    (2) 裝入時動態鏈接。這是指將用戶源程序編譯後所得到的一組目標模塊,在裝入內存
    時,採用邊裝入邊鏈接的鏈接方式。
    (3) 運行時動態鏈接。這是指對某些目標模塊的鏈接,是在程序執行中需要該(目標)模
    塊時,纔對它進行的鏈接。                

    運行時動態鏈接(Run-time Dynamic Linking)
    在許多情況下,應用程序在運行時,每次要運行的模塊可能是不相同的。但由於事先
    無法知道本次要運行哪些模塊,故只能是將所有可能要運行到的模塊都全部裝入內存,並
    在裝入時全部鏈接在一起。顯然這是低效的,因爲往往會有些目標模塊根本就不運行。比
    較典型的例子是作爲錯誤處理用的目標模塊,如果程序在整個運行過程中都不出現錯誤,
    則顯然就不會用到該模塊。
    近幾年流行起來的運行時動態鏈接方式,是對上述在裝入時鏈接方式的一種改進。這
    種鏈接方式是將對某些模塊的鏈接推遲到程序執行時才進行鏈接,亦即,在執行過程中,
    當發現一個被調用模塊尚未裝入內存時,立即由 OS 去找到該模塊並將之裝入內存,把它鏈
    接到調用者模塊上。凡在執行過程中未被用到的目標模塊,都不會被調入內存和被鏈接到
    裝入模塊上,這樣不僅可加快程序的裝入過程,而且可節省大量的內存空間。

    在當前的操作系統中,普遍採用的是下面將要講述的基於分頁和分段
    機制的虛擬內存機制,該機制較夥伴算法更爲合理和高效,但在多處理機系統中,夥伴系
    統仍不失爲一種有效的內存分配和釋放的方法,得到了大量的應用。

哈希算法
    在上述的分類搜索算法和夥伴系統算法中,都是將空閒分區根據分區大小進行分類,   
    對於每一類具有相同大小的空閒分區,單獨設立一個空閒分區鏈表。在爲進程分配空間時,
    需要在一張管理索引表中查找到所需空間大小所對應的表項,從中得到對應的空閒分區鏈
    表表頭指針,從而通過查找得到一個空閒分區。如果對空閒分區分類較細,則相應的空閒
    分區鏈表也較多,因此選擇合適的空閒鏈表的開銷也相應增加,且時間性能降低。
    哈希算法就是利用哈希快速查找的優點,以及空閒分區在可利用空間表中的分佈規律,
    建立哈希函數,構造一張以空閒分區大小爲關鍵字的哈希表,該表的每一個表項記錄了一
    個對應的空閒分區鏈表表頭指針。
    當進行空閒分區分配時,根據所需空閒分區大小,通過哈希函數計算,即得到在哈希
    表中的位置,從中得到相應的空閒分區鏈表,實現最佳分配策略。       


可重定位分區分配
    1.動態重定位的引入
    在連續分配方式中,必須把一個系統或用戶程序裝入一連續的內存空間。如果在系統
    中只有若干個小的分區,即使它們容量的總和大於要裝入的程序,但由於這些分區不相鄰
    接,也無法把該程序裝入內存。例如,圖 4-9(a)中示出了在內存中現有四個互不鄰接的小分
    區,它們的容量分別爲 10 KB、30 KB、14 KB 和 26 KB,其總容量是 80 KB。但如果現在
    有一作業到達,要求獲得 40 KB 的內存空間,由於必須爲它分配一連續空間,故此作業無
    法裝入。這種不能被利用的小分區稱爲“零頭”或“碎片”。 

    若想把作業裝入,可採用的一種方法是:將內存中的所有作業進行移動,使它們全都
    相鄰接,這樣,即可把原來分散的多個小分區拼接成一個大分區,這時就可把作業裝入該
    區。這種通過移動內存中作業的位置,以把原來多個分散的小分區拼接成一個大分區的方
    法,稱爲“拼接”或“緊湊”,見圖 4-9(b)。由於經過緊湊後的某些用戶程序在內存中的位
    置發生了變化,此時若不對程序和數據的地址加以修改(變換),則程序必將無法執行。爲此,
    在每次“緊湊”後,都必須對移動了的程序或數據進行重定位。

    2.動態重定位的實現
    在動態運行時裝入的方式中,作業裝入內存後的所有地址都仍然是相對地址,將相對
    地址轉換爲物理地址的工作,被推遲到程序指令要真正執行時進行。爲使地址的轉換不會
    影響到指令的執行速度,必須有硬件地址變換機構的支持,即須在系統中增設一個重定位
    寄存器,用它來存放程序(數據)在內存中的起始地址。程序在執行時,真正訪問的內存地址
    是相對地址與重定位寄存器中的地址相加而形成的。圖 4-10 示出了動態重定位的實現原理。
    地址變換過程是在程序執行期間,隨着對每條指令或數據的訪問自動進行的,故稱爲動態
    重定位。當系統對內存進行了“緊湊”而使若干程序從內存的某處移至另一處時,不需對
    程序做任何修改,只要用該程序在內存的新起始地址,去置換原來的起始地址即可        

    動態重定位分區分配算法
    動態重定位分區分配算法與動態分區分配算法基本上相同,差別僅在於:在這種分配
    算法中,增加了緊湊的功能,通常,在找不到足夠大的空閒分區來滿足用戶需求時進行緊
    湊。



基本分頁存儲管理方式
    連續分配方式會形成許多“碎片”,雖然可通過“緊湊”方法將許多碎片拼接成可用的
    大塊空間,但須爲之付出很大開銷。如果允許將一個進程直接分散地裝入到許多不相鄰接
    的分區中,則無須再進行“緊湊”。基於這一思想而產生了離散分配方式。如果離散分配的
    基本單位是頁,則稱爲分頁存儲管理方式;如果離散分配的基本單位是段,則稱爲分段存
    儲管理方式。
    在分頁存儲管理方式中,如果不具備頁面對換功能,則稱爲基本的分頁存儲管理方式,
    或稱爲純分頁存儲管理方式,它不具有支持實現虛擬存儲器的功能,它要求把每個作業全
    部裝入內存後方能運行

    頁面與頁表
    1.頁面
    1) 頁面和物理塊
    分頁存儲管理是將一個進程的邏輯地址空間分成若干個大小相等的片,稱爲頁面或頁,
    併爲各頁加以編號,從 0 開始,如第 0 頁、第 1 頁等。相應地,也把內存空間分成與頁面
    相同大小的若干個存儲塊,稱爲(物理)塊或頁框(frame),也同樣爲它們加以編號,如 0 # 塊、
    1 # 塊等等。在爲進程分配內存時,以塊爲單位將進程中的若干個頁分別裝入到多個可以不相
    鄰接的物理塊中。由於進程的最後一頁經常裝不滿一塊而形成了不可利用的碎片,稱之爲
    “頁內碎片”。
    2) 頁面大小
    在分頁系統中的頁面其大小應適中。頁面若太小,一方面雖然可使內存碎片減小,從
    而減少了內存碎片的總空間,有利於提高內存利用率,但另一方面也會使每個進程佔用較
    多的頁面,從而導致進程的頁表過長,佔用大量內存;此外,還會降低頁面換進換出的效
    率。然而,如果選擇的頁面較大,雖然可以減少頁表的長度,提高頁面換進換出的速度,
    但卻又會使頁內碎片增大。因此,頁面的大小應選擇適中,且頁面大小應是 2 的冪,通常
    爲 512 B~8 KB。
    2.地址結構
    分頁地址中的地址結構如下:
    31 12 11 0
    頁號 P  位移量 W
    它含有兩部分:前一部分爲頁號 P,後一部分爲位移量 W(或稱爲頁內地址)。圖中的地址長
    度爲 32 位,其中 0~11 位爲頁內地址,即每頁的大小爲 4 KB;12~31 位爲頁號,地址空
    間最多允許有 1 M 頁。               

    對於某特定機器,其地址結構是一定的。若給定一個邏輯地址空間中的地址爲 A,頁
    面的大小爲 L,則頁號 P 和頁內地址 d 可按下式求得:
    P = INT ú

    d = [A] MOD L
    其中,INT 是整除函數,MOD 是取餘函數。例如,其系統的頁面大小爲 1 KB,設 A = 2170 B,
    則由上式可以求得 P = 2,d = 122。

    頁表
    在分頁系統中,允許將進程的各個頁離散地
    存儲在內存不同的物理塊中,
    但系統應能保證進程的正確運行,
    即能在內存中找到每個頁面所對應的物理塊。
    爲此,系統又爲每個進程建立了一張頁面映像表,
    簡稱頁表。
    在進程地址空間內的所有頁0~n,
    依次在頁表中有一頁表項,
    其中記錄了相應頁在內存中對應的物理塊號,
    在配置了頁表後,進程執行時,通過查找該表,
    即可找到哦啊每頁在內存中的物理塊號。
    可見,頁表的作用是實現從頁號到物理塊號的地址映射。



    如果要利用分頁系統去實現虛擬存儲器,
    須增設一數據項。


地址變換機構
    爲了能將用戶地址空間中的邏輯地址變換爲
    內存空間中的物理地址,在系統中必須設置
    地址變換機構。
    該機構的基本任務是實現從邏輯地址到物理地址的轉換。

    由於頁內地址和物理地址是一一對應的,
    例如,對於頁面大小是1kb的頁內地址是0~1023,
    其相應的物理塊內的地址也是0~1023,無須進行轉換。
    因此,地址變換機構的任務實際上只是將邏輯地址
    中的頁號,轉換爲內存中的物理塊號。
    又因爲頁面映射表的作用就是用於實現從頁號
    到物理塊號的變換,
    因此,地址變換任務是藉助於頁表來完成的。



    當進程要訪問某個邏輯地址中的數據時,
    分頁地址變換機構會自動地將有效哦地址的
    分爲頁號和頁內地址兩部分,
    再以頁號爲索引去檢索頁表。
    查找操作有硬件執行就。
    在執行檢索之前,先將頁號與頁表長度進行比較,
    如果頁號大於或等於頁表長度,
    則表示本次所訪問的地址已超越進程的地址空間。
    於是,這一錯誤將被系統發現併產生一
    地址越界中斷。
    若未出現越界錯誤,則將頁表始址與頁號和
    頁表項長度的乘積相加,
    便得到該表項在頁表中的位置,
    於是可從中得到該頁的物理塊號,
    將之裝入物理地址寄存器中。
    與此同時,
    再將有效地址寄存器中的業內地址
    送入物理地址寄存器的塊內地址s


基本分段存儲管理方式

    如果說推動存儲管理方式從固定分區到動態分區分配,
    進而又發展到分頁存儲管理方式的主要動力,
    是提高內存利用率,那麼引入分段存儲管理方式的目的,
    則主要是爲了滿足程序員在編程和使用上多方面的要求,
    其中有些要求是其他幾種存儲管理方式所難以滿足的。
    因此,這種存儲管理方式已成爲當今所有存儲管理方式的基礎。

    爲了方便和實現下面的要求:
    1.方便編程

    2.信息共享

    3.信息保護

    4.動態增長
    在實際應用中,往往有些段,特別是數據段,在使用過程中會不斷地增長,而事先又
    無法確切地知道數據段會增長到多大。前述的其它幾種存儲管理方式,都難以應付這種動
    態增長的情況,而分段存儲管理方式卻能較好地解決這一問題。

    5.動態鏈接
    動態鏈接是指在作業運行之前,並不把幾個目標程序段鏈接起來。要運行時,先將主
    程序所對應的目標程序裝入內存並啓動運行,當運行過程中又需要調用某段時,纔將該段(目
    標程序)調入內存並進行鏈接。可見,動態鏈接也要求以段作爲管理的單位。



分頁和分段的主要區別
    (1) 頁是信息的物理單位,分頁是爲實現離散分配方式,以消減內存的外零頭,提高內
    存的利用率。或者說,分頁僅僅是由於系統管理的需要而不是用戶的需要。段則是信息的
    邏輯單位,它含有一組其意義相對完整的信息。分段的目的是爲了能更好地滿足用戶的
    需要。
    (2) 頁的大小固定且由系統決定,由系統把邏輯地址劃分爲頁號和頁內地址兩部分,是
    由機器硬件實現的,因而在系統中只能有一種大小的頁面;而段的長度卻不固定,決定於
    用戶所編寫的程序,通常由編譯程序在對源程序進行編譯時,根據信息的性質來劃分。
    (3) 分頁的作業地址空間是一維的,即單一的線性地址空間,程序員只需利用一個記憶
    符,即可表示一個地址;而分段的作業地址空間則是二維的,程序員在標識一個地址時,
    既需給出段名,又需給出段內地址。




段頁式存儲管理方式
    分頁和分段存儲管理方式都各有其優缺點。分頁系統能有效地提高內存
    利用率,而分段系統則能很好地滿足用戶需要。如果能對兩種存儲管理方式“各取所長”,
    則可以將兩者結合成一種新的存儲管理方式系統。這種新系統既具有分段系統的便於實現、
    分段可共享、易於保護、可動態鏈接等一系列優點,又能像分頁系統那樣很好地解決內存
    的外部碎片問題,以及可爲各個分段離散地分配內存等問題。把這種結合起來形成的新系
    統稱爲“段頁式系統”。

    1.基本原理
    段頁式系統的基本原理,是分段和分頁原理的結合,即先將用戶程序分成若干個段,
    再把每個段分成若干個頁,併爲每一個段賦予一個段名。圖 4-21 示出了一個作業地址空間
    的結構。該作業有三個段,頁面大小爲 4 KB。在段頁式系統中,其地址結構由段號、段內
    頁號及頁內地址三部分所組成


虛擬存儲器 

    兩種情況:
    (1) 有的作業很大,其所要求的內存空間超過了內存總容量,作業不能全部被裝入內存,
    致使該作業無法運行。
    (2) 有大量作業要求運行,但由於內存容量不足以容納所有這些作業,只能將少數作業
    裝入內存讓它們先運行,而將其它大量的作業留在外存上等待。
    出現上述兩種情況的原因,都是由於內存容量不夠大。一個顯而易見的解決方法,是
    從物理上增加內存容量,但這往往會受到機器自身的限制,而且無疑要增加系統成本,因
    此這種方法是受到一定限制的。另一種方法是從邏輯上擴充內存容量,這正是虛擬存儲技
    術所要解決的主要問題。


    局部性原理
    早在 1968 年,Denning.P 就曾指出:程序在執行時將呈現出局部性規律,即在一較短
    的時間內,程序的執行僅侷限於某個部分;相應地,它所訪問的存儲空間也侷限於某個區
    域。他提出了下述幾個論點:
    (1) 程序執行時,除了少部分的轉移和過程調用指令外,在大多數情況下仍是順序執行
    的。該論點也在後來的許多學者對高級程序設計語言(如 FORTRAN 語言、PASCAL 語言)
    及 C 語言規律的研究中被證實。
    (2) 過程調用將會使程序的執行軌跡由一部分區域轉至另一部分區域,但經研究看出,
    過程調用的深度在大多數情況下都不超過 5。這就是說,程序將會在一段時間內都侷限在這
    些過程的範圍內運行。
    (3) 程序中存在許多循環結構,這些雖然只由少數指令構成,但是它們將多次執行。
    (4) 程序中還包括許多對數據結構的處理,如對數組進行操作,它們往往都侷限於很小
    的範圍內。
    侷限性還表現在下述兩個方面:
    (1) 時間侷限性。如果程序中的某條指令一旦執行,則不久以後該指令可能再次執行;
    如果某數據被訪問過,則不久以後該數據可能再次被訪問。產生時間侷限性的典型原因是
    由於在程序中存在着大量的循環操作。
    (2) 空間侷限性。一旦程序訪問了某個存儲單元,在不久之後,其附近的存儲單元也將
    被訪問,即程序在一段時間內所訪問的地址,可能集中在一定的範圍之內,其典型情況便
    是程序的順序執行。


DMA 工作過程
    我們以從磁盤讀入數據爲例,來說明 DMA 方式的工作流程。當 CPU 要從磁盤讀入一
    數據塊時,便向磁盤控制器發送一條讀命令。該命令被送到其中的命令寄存器(CR)中。同
    時,還鬚髮送本次要將數據讀入的內存起始目標地址,該地址被送入內存地址寄存器(MAR)
    中;本次要讀數據的字(節)數則送入數據計數器(DC)中,還須將磁盤中的源地址直接送至
    DMA 控制器的 I/O 控制邏輯上。然後,啓動 DMA 控制器進行數據傳送,以後,CPU 便可
    去處理其它任務。此後,整個數據傳送過程便由 DMA 控制器進行控制。當 DMA 控制器已
    從磁盤中讀入一個字(節)的數據並送入數據寄存器(DR)後,再挪用一個存儲器週期,將該字
    (節)傳送到 MAR 所指示的內存單元中。接着便對 MAR 內容加 1,將 DC 內容減 1。若減 1
    後 DC 內容不爲 0,表示傳送未完,便繼續傳送下一個字(節);否則,由 DMA 控制器發出
    中斷請求。

5.

發佈了127 篇原創文章 · 獲贊 83 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章