Linux 程序的理解

2021-07-02 19:24:32 字數 2401 閱讀 7004

程序的描述

通俗的講,程序就是正在執行的程式或**。我們知道,程式本身就是一堆**,開始的時候儲存在磁碟上,這時它是靜態的、無生命的;只有當程式的**被載入到記憶體中,**才有了生命,才能被cpu動態的執行。

問題是,現在的作業系統可以並行的執行多個程式,也就是記憶體中同時存放著多個程式的**,為了方便管理,必須要合理的組織它們。方式就是由作業系統給每段**新增一些元資料,這些元資料就是pcb,即任務控制塊。

不難理解的是,每個程式的**實際上可以分為兩部分:指令和資料。指令就是程式**規定的各種操作;資料就是這些操作的物件。乙個程式可以多次被載入到記憶體成為多個程序,比如同時開啟兩個vim分別編輯不同的檔案。那麼問題是:這時候有必要在記憶體中同時存放多個該程式的指令copy嗎?答案是不必的。指令部分被設定為唯讀且允許系統中正在執行的兩個或多個程序之間能夠共享這一**;而資料部分則被各個程序私有,不可以共享,比如每個vim都只能編輯自己的檔案。

那麼pcb裡面都有些什麼呢?

程序的建立

經常聽說「建立乙個程序」,這到底是怎麼回事呢?首先能想到的是,程序不是孫猴子,不可能自己蹦出來,肯定是別人「生」的。linux中,程序是由父程序建立的,準確的說,是父程序中的**的指令部分主動使用了建立程序的函式fork(),然後乙個子程序就被「生」了出來。fork函式如何工作的呢?由於每個程序都有乙個pcb,所以它首先要跟作業系統申請乙個pcb(pcb是有限的),然後分配新程序記憶體,接著copy父程序的**。實際上,fork就是很懶的複製了一下父程序,也就是說,fork函式呼叫過程中,記憶體中會會出現兩個幾乎一模一樣的程序,當然除了程序號(它是唯一的)。程序的複製完成後,兩個程序都有乙個fork函式等待返回(注意,是返回,因為fork函式本身也是一條一條的**,前面的一部分完成複製功能,子程序出現後,就到了返回的那部分**了),而它們的返回結果是不同的(作業系統來控制返回結果):父程序中的fork返回子程序的pid;而子程序中的fork返回0;如果fork失敗,返回的是-1。

fork只是創造出了兩個幾乎一樣的程序,它們執行的是同樣的**,這和一開始說的可不一樣,因為我們創造乙個新程序大多是用來執行新程式**的。這時我們需要exec類函式,當程序呼叫一種exec函式時,該程序的程式**完全被新程式替換,從新程式的啟動例程開始執行。呼叫exec並不建立新程序,所以呼叫exec前後該程序的id並未改變。如果呼叫成功則載入新的程式從啟動**開始執行,不再返回,如果呼叫出錯則返回-1,所以exec函式只有出錯的返回值而沒有成功的返回值。exec 系統呼叫執行新程式時會把命令列引數和環境變數表傳遞給 main 函式。環境變數表是程序所處系統環境的乙個描述,一段**要正常執行必然要使用各種系統資源,環境變數表就是對它的乙個抽象。但是,exec類函式是需要顯式呼叫的,子程序不會主動載入新的程式**!所以,一般是在父程序的**中,根據fork的返回值寫乙個分支,子程序的分支中顯式呼叫exec。程序的終止(參考:linux c一站式程式設計)

乙個程序在終止時會關閉所有檔案描述符,釋放在使用者空間分配的記憶體,但它的pcb還保留著,作業系統在其中儲存了一些資訊:如果是正常終止則儲存著退出狀態,如果是異常終止則儲存著導致該程序終止的訊號是哪個。這個程序的父程序可以呼叫 wait 或 waitpid 獲取這些資訊,然後徹底清除掉這個程序。我們知道乙個程序的退出狀態可以在shell中用特殊變數 $? 檢視,因為shell是它的父程序,當它終止時shell呼叫 wait 或 waitpid 得到它的退出狀態同時徹底清除掉這個程序。

如果乙個程序已經終止,但是它的父程序尚未呼叫 wait 或 waitpid 對它進行清理,這時的程序狀態稱為殭屍(zombie)程序。任何程序在剛終止時都是殭屍程序,正常情況下,殭屍程序都立刻被父程序清理了。

如果乙個父程序終止,而它的子程序還存在(這些子程序或者仍在執行,或者已經是殭屍程序了),則這些子程序的父程序改為 init 程序。 init 是系統中的乙個特殊程序,通常程式檔案是 /sbin/init ,程序id是1,在系統啟動時負責啟動各種系統服務,之後就負責清理子程序,只要有子程序終止, init 就會呼叫 wait 函式清理它。

殭屍程序是不能用 kill 命令清除掉的,因為 kill 命令只是用來終止程序的,而殭屍程序已經終止了。所以一顆可行的辦法是,kill其父程序。

wait 和 waitpid 函式的原型是:

#include 

#include

pid_t wait(int

*status);

pid_t waitpid(pid_t pid, int

*status, int options);

若呼叫成功則返回清理掉的子程序id,若呼叫出錯則返回-1。父程序呼叫 wait 或 waitpid 時可能會:

+ 阻塞(如果它的所有子程序都還在執行)。

+ 帶子程序的終止資訊立即返回(如果乙個子程序已終止,正等待父程序讀取其終止資訊)。

+ 出錯立即返回(如果它沒有任何子程序)。

Linux程序理解

1.1程序分類 linux作業系統包括三種不同型別的程序,每種程序都有自己的特點和屬性。a 互動程序 由乙個shell啟動的程序。互動程序既可以在前台執行,也可以在後台執行。b 批處理程序 這種程序和終端沒有聯絡,是乙個程序序列。c 監控程序 也稱守護程序 linux系統啟動時啟動的程序,並在後台執...

linux下程序的理解

1.關於程序的理解 程序即執行的所有程式和開啟的服務,關掉其程序和服務將有利於釋放記憶體,減輕電腦空間壓力。1 windows的程序如下 2 linux中的程序如下 檢視所有程序 ps命令可以列出系統中當前執行的程序,所列出的程序是在執行ps命令這個時刻正在執行的程序。此外也可以用 2.檢視指定程序...

對Linux程序的理解

在本科期間學習過程序,網上也有很多關於程序的知識,但對於程序到底是什麼一直沒有讓我滿意的解答 以下截圖來自網路,感覺對程序理解有問題,說得也很虛 但今天找到這個博文感覺挺符合我的胃口 程序是linux核心提供的乙個環境 資源分配的基本單位 包括 1 程序控制塊 用於作業系統對程序的管理 2 虛擬記憶...