歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

Linux 核心

  進程及進程間通訊機制 程序是保存在磁盤上的文件,其中包含了計算機的執行指令和數據,而進程則可以看成是運行中的程序。程序是靜態的,而進程是動態的。和進程聯系在一起的不僅有進程的指令和數據,而且還有當前的指令指針、所有的 CPU 寄存器以及用來保存臨時數據的堆棧等,所有這些都隨著程序指令的執行在變化。 進程在運行過程中,要使用許多計算機資源,例如 CPU、內存、文件等。Linux 是一個多任務操作系統,同時可能會有多個進程使用同一個資源,因此操作系統要跟蹤所有的進程及其所使用的系統資源,以便能夠管理進程和資源。 Linux 是一個多任務操作系統,它要保證 CPU 時刻保持在使用狀態,如果某個正在運行的進程等待外部設備完成工作(例如等待打印機完成打印任務),這時,操作系統就可以選擇其他進程運行,從而保持 CPU 的最大利用率。這就是多任務的基本思想,進程之間的切換由調度程序完成。 Linux 中的每個進程有自己的虛擬地址空間,操作系統的一個最重要的基本管理目的,就是避免進程之間的互相影響。但有時用戶也希望能夠利用兩個或多個進程的功能完成同一任務,為此,Linux 提供許多機制,利用這些機制,進程之間可以進行通訊並共同完成某項任務,這種機制稱為“進程間通訊(IPC)”。信號和管道是常見的兩種 IPC 機制,但 Linux 也提供其他 IPC 機制。 本章主要描述 Linux 進程的管理、調度以及 Linux 系統支持的進程間通訊機制。 11.1 Linux 進程及線程 Linux 內核利用一個數據結構(task_strUCt)代表一個進程,代表進程的數據結構指針形成了一個 task 數組(Linux 中,任務和進程是兩個相同的術語),這種指針數組有時也成為指針向量。這個數組的大小默認為 512,表明在 Linux 系統中能夠同時運行的進程最多可有 512。當建立新進程的時候,Linux 為新的進程分配一個 task_struct 結構,然後將指針保存在 task 數組中。task_struct 結構中包含了許多字段,按照字段功能,可分成如下幾類: 標識號。系統通過進程標識號唯一識別一個進程,但進程標識號並不是進程對應的 task_struct 結構指針在 task 數組中的索引號。另外,一個進程還有自己的用戶和組標識號,系統通過這兩個標識號判斷進程對文件或設備的訪問權。 狀態信息。一個 Linux 進程可有如下幾種狀態:運行、等待、停止和僵死。 調度信息。調度程序利用該信息完成進程之間的切換。 有關進程間通訊的信息。系統利用這一信息實現進程間的通訊。 進程鏈信息。在 Linux 系統中,除初始化進程之外,任何一個進程都具有父進程。每個進程都是從父進程中“克隆”出來的。進程鏈則包含進程的父進程指針、和該進程具有相同父進程的兄弟進程指針以及進程的子進程指針。另外,Linux 利用一個雙向鏈表記錄系統中所有的進程,這個雙向鏈表的根就是 init 進程。利用這個鏈表中的信息,內核可以很容易地找到某個進程。 時間和定時器。系統在這些字段中保存進程的建立時間,以及在其生命周期中所花費的 CPU 時間,這兩個時間均以 jiffies 為單位。這一時間由兩部分組成,一是進程在用戶模式下花費的時間,二是進程在系統模式下花的時間。Linux 也支持和進程相關的定時器,應用程序可通過系統調用建立定時器,當定時器到期時,操作系統會向該進程發送 SIGALRM 信號。 文件系統信息。進程可以打開文件系統中的文件,系統需要對這些文件進行跟蹤。系統使用這類字段記錄進程所打開的文件描述符信息。另外,還包含指向兩個 VFS 索引節點的指針,這兩個索引節點分別是進程的主目錄以及進程的當前目錄。索引節點中有一個引用計數器,當有新的進程指向某個索引節點時,該索引節點的引用計數器會增加計數。未被引用的索引節點的引用計數為 0,因此,當包含在某個目錄中的文件正在運行時,就無法刪除這一目錄,因為這一目錄的引用計數大於0。 和進程相關的上下文信息。如前所述,進程可被看成是系統狀態的集合,隨著進程的運行,這一集合發生變化。進程上下文就是用來保存系統狀態的 task_struct 字段。當調度程序將某個進程從運行狀態切換到暫停狀態時,會在上下文中保存當前的進程運行環境,包括 CPU 寄存器的值以及堆棧信息;當調度程序再次選擇該進程運行時,則會從進程上下文信息中恢復進程的運行環境。 11.1.1 標識符信息 和所有的 UNIX 系統一樣,Linux 使用用戶標識符和組標識符判斷用戶對文件和目錄的訪問許可。Linux 系統中的所有文件或目錄均具有所有者和許可屬性,Linux 據此判斷某個用戶對文件的訪問權限。對一個進程而言,系統在 task_struct 結構中記錄如表 11-1 所示的四對標識符。 表 11-1 進程的標識符信息 uid 和 gid 運行進程所代表的用戶之用戶標識號和組標識號,通常就是執行該進程的用戶。   有效uid 和 gid 某些程序可以將 uid 和 gid 改變為自己私有的 uid 和 gid。系統在運行這樣的程序時,會根據修改後的 uid 及 gid 判斷程序的特權,例如,是否能夠直接進行 I/O 輸出等。通過 setuid 系統調用,可將程序的有效 uid 和 gid 設置為其他用戶。在該程序映象文件的 VFS 索引節點中,有效 uid 和 gid 由索引節點的屬性描述。


  文件系統uid 和 gid 這兩個標識符和上述標識符類似,但用於檢查對文件系統的訪問許可時。處於用戶模式的 NFS 服務器作為特殊進程訪問文件時使用這兩個標識符。   保存uid 和 gid 如果進程通過系統調用修改了進程的 uid 和 gid,這兩個標識符則保存實際的 uid 和 gid。   11.1.2 進程狀態信息 如前所述,Linux 中的進程有四中狀態,如表 11-2 所示。 表 11-2 進程的狀態信息 運行狀態 該進程是當前正在運行的進程;或者,該進程是可以運行的進程,即正在等待調度程序將 CPU 分配給它。   等待狀態 進程正在等待某個事件或某個資源。這種進程又分為可中斷的進程和不可中斷的進程兩種。可中斷的等待進程可被信號中斷,而不可中斷的等待進程是正在直接等待硬件狀態條件的進程,在任何情況下都不能被中斷。   停止狀態 進程處於停止狀態,通常由於接收到信號而停止,例如,進程在接收到調試信號時處於停止狀態。   僵死狀態 進程已終止,但在 task 數組中仍占據著一個 task_struct 結構。顧名思義,處於這種狀態的進程實際是死進程。   11.1.3 文件信息 如圖 11-1 所示,系統中的每個進程有兩個數據結構用於描述進程與文件相關的信息。其中,fs_struct 描述了上面提到的兩個 VFS 索引節點的指針,即 root 和 pwd。另外,這個結構還包含一個 umask 字段,它是進程創建文件時使用的默認模式,可通過系統調用修改這一默認模式。另一個結構為files_struct,它描述了當前進程所使用的所有文件信息。從圖中可以看出,每個進程能夠同時擁有 256 個打開的文件,fs[0] 到 fs[255] 就是指向這些 file 結構的指針。文件的描述符實際就是 fs 指針數組的索引號。 在 file 結構中,f_mode 是文件的打開模式,只讀、只寫或讀寫;f_pos 是文件的當前位置;f_inode 指向 VFS 中該文件的索引節點;f_op 包含了對該文件的操作例程集。利用 f_op,可以針對不同的文件定義不同的操作函數,例如一個用來向文件中寫數據的函數。Linux 利用這一抽象機制,實現了管道這一進程間通訊機制(將在後面詳細描述)。這種抽象方法在 Linux 內核中非常常見,通過這種方法,可使特定的內核對象具有類似 C++ 對象的多態性。 Linux 進程啟動時,有三個文件描述符被打開,它們是標准輸入、標准輸出和錯誤輸出,分別對應 fs 數組的三個索引,即 0、1和2。如果啟動時進行輸入輸出重定向,則這些文件描述符指向指定的文件而不是標准的終端輸入/輸出。每當進程打開一個文件時,就會利用files_struct 的一個空閒 file 指針指向打開的文件描述結構 file。對文件的訪問通過 file 結構中定義的文件操作例程和 VFS 索引節點信息來完成。 11.1.4 虛擬內存 在前一章中看到,進程的虛擬內存包含了進程所有的可執行代碼和數據。運行某個程序時,系統要根據可執行映象中的信息,為進程代碼和數據分配虛擬內存;進程在運行過程中,可能會通過系統調用動態申請虛擬內存或釋放已分配的內存,新分配的虛擬內存必須和進程已有的虛擬地址鏈接起來才能使用;Linux 進程可以使用共享的程序庫代碼或數據,這樣,共享庫的代碼和數據也需要鏈接到進程已有的虛擬地址中。在前一章中還看到,系統利用了需求分頁機制來避免對物理內存的過分使用。因為進程可能會訪問當前不在物理內存中的虛擬內存,這時,操作系統通過對處理器的頁故障處理裝入內存頁。為此,系統需要修改進程的頁表,以便標志虛擬頁是否在物理內存中,同時,Linux 還需要知道進程地址空間中任何一個虛擬地址區域的來源和當前所在位置,以便能夠裝入物理內存。   圖 11-1 進程的文件信息 由於上面這些原因,Linux 采用了比較復雜的數據結構跟蹤進程的虛擬地址。



  圖 11-1 進程的文件信息 由於上面這些原因,Linux 采用了比較復雜的數據結構跟蹤進程的虛擬地址。



Copyright © Linux教程網 All Rights Reserved