每個程序都有乙個非負整型表示的唯一程序id。雖然該id是唯一的,但是程序id是可復用的。當乙個程序終止後,其程序id就成為復用的候選者。
系統中有一些專用程序,但是具體細節隨實現而不同。id為0的程序通常是排程程序,常常被稱為交換程序。該程序是核心的一部分,它並不執行任何磁碟上的程式,因此也被成為系統程序。程序id 1通常是init程序,在自舉過程結束時有核心呼叫。init程序絕不會終止,他是乙個普通使用者的使用者程序(與交換程序不同,他不是核心中的系統程序),但是它以超級使用者許可權執行。
每個unix系統實現都有它自己的一套提供作業系統服務的核心程序,比如,在某些unix的虛擬儲存器中,程序id 2是頁守護程序(page daemnon),此程序負責支援虛擬儲存系統的分頁操作。
附:程序相關函式
1 #include 2 #include 3 pid_t getpid(void); 返回:呼叫程序的程序 i d4 pid_t getppid(void); 返回:呼叫程序的父程序 i d
5 uid_t getuid(void); 返回:呼叫程序的實際使用者 i d
6 uid_t geteuid(void); 返回:呼叫程序的有效使用者 i d
7 gid_t getgid(void); 返回:呼叫程序的實際組 i d
8 gid_t getegid(void); 返回:呼叫程序的有效組 i d
#includepid_t fork(void);解釋:有fork函式建立的新程序成為子程序,fork函式被呼叫一次,但返回兩次,兩次返回的區別是子程序返回值是0,父程序的返回值則是新建子程序的程序id。子程序和父程序繼續執行fork呼叫之後的指令,子程序是父程序的副本。例如,子程序獲取父程序資料空間、堆和棧的副本。注意,這是子程序所擁有的副本,父程序和子程序並不共享這些儲存空間部分。該部分執行寫時複製。
可以看到子程序對變數所做的改變並不影響父程序中該變數的值。
一般來講,在fork之後是父程序還是子程序先執行是不確定的,這取決於核心所使用的排程演算法,如果要求父程序和子程序之間相互同步,則要求某種形式的程序間通訊。
檔案共享
在fork之後處理檔案描述符有以下兩種常見的情況:
(1)父程序等待子程序 完成。(2)父程序和子程序各自執行不同的程式段。
除了開啟檔案之外,父程序的很多其他屬性也有子程序繼承,包括:
實際使用者i d、實際組i d、有效使用者i d、有效組i d。
• 新增組i d。
• 程序組i d。
• 對話期i d。
• 控制終端。
• 設定-使用者- i d標誌和設定-組- i d標誌。
• 當前工作目錄。
• 根目錄。
• 檔案方式建立遮蔽字。
• 訊號遮蔽和排列。
• 對任一開啟檔案描述符的在執行時關閉標誌。
• 環境。
• 連線的共享儲存段。
• 資源限制。
父、子程序之間的區別是:
• fork的返回值。
• 程序i d。
• 不同的父程序i d。
• 子程序的t m s _ u t i m e , t m s _ s t i m e , t m s _ c u t i m e以及t m s _ u s t i m e設定為0。
• 父程序設定的鎖,子程序不繼承。
• 子程序的未決告警被清除。
• 子程序的未決訊號集設定為空集。
fork失敗的兩個原因:
(a)系統中已經有了太多的程序(通常意味著某個方面出了問題)
(b)該實際使用者id的程序總數超過了系統限制。
fork的用法:
(1)乙個父程序希望賦值自己,是父程序和子程序同時執行不同的**段。
(2)乙個程序要執行乙個不同的程式。
(1)vfork函式用於建立乙個新的程序,而該程序的目的是exec乙個新程式。vfork與fork的區別:(1)v f o r k與f o r k一樣都建立乙個子程序,但是它並不將父程序的位址空間完全複製到子程序中,因為子程序會立即呼叫 e x e c (或e x i t ),於是也就不會存訪該位址空間。不過在子程序呼叫 e x e c或e x i t之前,它在父程序的空間中執行。這種工作方式在某些 u n i x的頁式虛存實現中提高了效率(與上節中提及的,在 f o r k之後跟隨e x e c,並採用在寫時複製技術相類似)。
(2)v f o r k保證子程序先執行,在它呼叫 e x e c或e x i t之後父程序才可能被排程執行。(如果在呼叫這兩個函式之前子程序依賴於父程序的進一步動作,則會導致死鎖。)
函式exit
程序有5種正常終止和3種異常終止方式
5種正常終止方式為:
在main函式內執行return語句,呼叫exit函式,呼叫_exit函式或者_exit函式,程序的最後乙個執行緒在其啟動例程中執行return語句,程序的最後乙個執行緒呼叫pthread_exit函式。
3種異常終止方式如下:
呼叫abort,當程序接收到某些訊號時,最後乙個執行緒對「取消」請求做出響應。
在任意一種終止情況下,該終止程序的父程序都可以用wait或waitpid函式取得其終止狀態。
對於父程序已經終止的所有程序,它們的父程序都改變為init程序,我們稱這些程序由init程序收養。
僵死程序:乙個已經終止、但是其父程序尚未對其進行善後處理的程序成為僵死程序。
#includepid_t wait(int *statloc);呼叫wait和waitpid的程序會發生什麼pid_t waitpid(pid_t pid,int *statloc,int options);
• 阻塞(如果其所有子程序都還在執行)。
• 帶子程序的終止狀態立即返回(如果乙個子程序已終止,正等待父程序訪問其終止狀態 )。
• 出錯立即返回(如果它沒有任何子程序)。
這兩個函式的區別是:
• 在乙個子程序終止前, wait 使其呼叫者阻塞,而 waitpid 有一選擇項,可使呼叫者不阻
塞。• waitpid並不等待第乙個終止的子程序—它有若干個選擇項,可以控制它所等待的程序。
檢查w a i t和w a i t p i d所返回的終止狀態的巨集
對於waitpid函式中pid引數的作用的解釋如下:
• pid == -1 等待任一子程序。於是在這一功能方面 w a i t p i d與w a i t等效。
• pid > 0 等待其程序i d與p i d相等的子程序。
• pid == 0 等待其組i d等於呼叫程序的組i d的任一子程序。
• pid
< -1 等待其組i d等於p i d的絕對值的任一子程序。
對於waitpid函式中options引數的作用的解釋如下:
options或者是0或者是表中常量按位或者運算的結果。
waitpid函式提供了wait函式沒有提供的三個功能:
(1) waitpid等待乙個特定的程序 (而wait則返回任一終止子程序的狀態 )。
(2) waitpid提供了乙個wait的非阻塞版本。有時希望取得乙個子程序的狀態,但不想阻塞。
(3) waitpid支援作業控制(以wuntraced選擇項)。
以上程式實現的功能是:乙個程序fork乙個子程序,但不要它等待子程序終止,也不希望子程序處於僵死狀態知道父程序終止,通過呼叫fork兩次來實現。
在第二個子程序中呼叫 sleep以保證在列印父程序 id時第乙個子程序已終止。在 fork之後,父、子程序都可繼續執行——我們無法預知哪乙個會先執行。如果不使第二個子程序睡眠,則在fork之後,它可能比其父程序先執行,於是它列印的父程序 id將是建立它的父程序,而不是init程序。
linux程式設計之程序控制
一 fork include pid t fork void 返回值 有兩個,乙個是子程序的id,另乙個為零。當返回值為0時,進入子程序,大於0進入父程序,返回 1時建立程序錯誤。子程序與父程序的比較 1 子程序與父程序的程序id不同。且父程序id不同。2 記憶體布局 子程序是父程序的副本,其中子程...
Linux程序控制程式設計之fork wait
本文將記錄我在學習fork和wait waitpid 這兩個函式的過程。1.fork 在linux中,建立乙個新程序常用fork函式,它非常特別,執行一次,居然返回兩個值,這與一般的函式是大大的不一樣的,這點引起了我高度的注意。prototype pid t fork void return 0 子...
linux程序控制程式設計
一 程序與程式 程式是放到磁碟的可執行檔案 程序是指程式執行的例項 程序是動態的,程式是靜態的 程式是有序 的集合 程序是程式的執行。通常程序不可在計算機之間遷移 而程式通常對應著檔案 靜態和可以複製。程序是暫時的,程式使長久的 程序是乙個狀態變化的過程,程式可長久儲存。程序與程式組成不同 程序的組...