Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 進程等待&程序替換

進程等待&程序替換

編輯:關於Android編程

進程等待

一個進程在終止時會關閉所有的文件描述符,釋放在用戶空間分配出來的內存,但它的PCB還保留著,而且內核中還保存著一些信息,如果是正常終止,則保存著退出狀態,如果是異常終止,則保存著導致該進程終止信號是哪個,。這個進程的父進程可以調用wait和waitpid獲取這些信息,然後徹底清除這個進程。

一個進程的父進程是shell進程,當它終止時shell就會調用wait或者waitpid得到它的退出狀態,然後清除這個進程。當一個進程正常或者異常終止的時候,內核就會向父進程發送SIGCHLD信號,對於這種信號,系統默認動作是忽略它。

 

【調用wait或者waitpid的進程會發生什麼情況?】

(1)如果這個進程的所有子進程都還在運行,則這個進程就會阻塞。

(2)如果一個子進程已終止,正等待父進程獲取其終止狀態,則取得該子進程的終止狀態後立即返回。

(3)如果這個進程它沒有任何子進程,則立即出錯返回。

 

頭文件:

#include

#include

 

1)pid_t wait(int *status);

返回值:成功返回被等待進程pid,失敗返回-1

參數:輸出型參數,獲取進程退出狀態,不關心則可以設置為NULL

如果進程由於接收到SIGCHLD而調用wait,則可期望wait會立即返回;但如果在任意時刻調用wait,則進程可能阻塞。

在一個子進程終止前, wait使其調用者堵塞,而waitpid有一個選項,可使調用者不堵塞。如果status不是空指針,則終止進程的終止狀態就存放在它所指的單元內。如果不關心終止狀態,則可將參數設置為空指針(waitpid同樣適用)。

例:

\

運行結果:

\

 

2)pid_t waitpid(pid_t pid, int *status, int options);

返回值:

a、當正常返回的時候waitpid返回收集到的子進程的進程id

b、如果設置了選項WNOHANG,而調用中waipid發現沒有已退出的子進程可收集,則返回0

c、如果調用中出錯,則返回-1,這時errno會被設置成相應的值以指示錯誤所在

d、當pid所指示的子進程不存在,或此進程存在,但不是調用進程的子進程,waitpid就會出錯返回,這時errno被設置為ECHILD

參數:

a、pid(進程id)

pid=-1;等待任一個子進程,與wait等效。

pid >0;等待其進程ID與pid相等的子進程。

pid == 0;等待其組id等於進程組id的任一個子進程。

pid <-1;等待其組ID等於pid絕對值的任一個子進程。

b、status(int型)

status的高8位(WIFEXITED(status)) :若為正常終止子進程返回的狀態,則為真。(查看進程是否是正常退出)
status的低8位 (WEXITSTATUS(status)) : 若WIFEXITED非零,提取子進程退出碼。(查看進程的退出碼)

例:

\

運行結果:

正常:

\

異常:exit(257);

\

 

3)檢查wait和waitpid所返回的終止狀態:

a、利用按位與,得到static的前8位和後8位

b、利用系統中的宏

WIFEXITED(status) : 若為正常終止子進程返回的狀態,則為真。

WEXITSTATUS(status) : 若WIFEXITED非零,返回子進程退出碼,提取進程退出返回值,如果子進程調exit(7),WEXITSTATUS(status就會返 回7。請注意,如果進程不是正常退出的,也就是說,WIFEXITED返回0,這個值就毫無意義。

說明:status 並不簡簡單單是一個整形變量,父進程和子進程之間所有的狀態交互都要通過這個int來表示,所以這個int的若干bit位都是有特殊的含義的,那麼這個“int”如何編碼就比較重要了,和IP地址一樣,它是比較緊湊的,或者說是比較擁擠的。

status指出了子進程是正常退出還是被非正常結束的(一個進程也可以被其他進程用信號結束),以及正常結束時的返回值,或被哪一個信號結束或進程的退出碼是多少等信息,這些信息都被放在整數的不同二進制位中,所以用常規的方法讀取會非常麻煩,所以開發者就設計了一套專門的宏(macro)來完成這項工作。

4)wait和waitpid的作用:

a、等待目的:子進程讀取到子進程退出的一個狀態信息

b、讓系統釋放掉子進程占有的僵屍狀態的資源

c、運行時不保證父子進程誰先運行,可保證子進程先退出,等待使父子進程的退出同步起來(即退出產生一定的順序)

5)waitpid提供了wait沒有提供的功能:

 

a、waitpid可等待一個特定的進程

b、waitpid提供了一個wait的非阻塞版本

c、waitpid支持作業控制

 

 

程序替換

用fork創建子進程後執行的是和父進程相同的程序,子進程往往要調用一種exec函數來執行另一個程序。當進程調用一種exec函數時,該進程的用戶空間代碼和數據完全被新程序進行替換,從新程序的啟動例程開始執行,調用exec並不創建新的進程,所以調用exec前後該進程的id並未改變。

1)6種以exec開頭的函數:

#incldue

int execl(const char* path,const char* arg,....);

int execlp(const char* file,const char* arg,....);

int execle(const char* path,const char* arg,..., char* const emp[]);

int execv(const char* path,char* const argv[]);

int execp(const char* file,char* const argv[]);

int execve(const char* path,char* const argv[],char* const emp[]);

這些函數如果調用成功,則加載新的程序從啟動代碼開始執行,不再返回。如果調用出錯則返回-1,所以exec函數只有出錯的返回值而沒有成功的返回值。

 

2)這些函數的規則:

不帶字母p(表示path)的exec函數 第一個參數必須是程序的相對路徑或絕對路徑,例如"/bin/ls"或"./a.out",而不能 是"ls"或"a.out"。對於帶字母p的函數: 如果參數中包含/,則將其視為路徑名。 否則視為不帶路徑的程序名,在PATH環境變量的目錄列表中搜索這個程序。
帶有字母l( 表示list)的exec函數要求將新程序的每個命令行參數都當作一個參數傳給它,命令行參數的個數是可變的,因此函數原型中有...,...中的最後一個可變參數應該是NULL, 起sentinel的作用。
帶有字母v( 表示vector)的函數,則應該先構造一個指向各參數的指針數 組,然後將該數組的首地址當作參數傳給它,數組中的最後一個指針也應該是NULL,就像main函數的argv參數或者環境變量表一樣。
對於以e (表示environment)結尾的exec函數,可以把一份新的環境變量表傳給它,其他exec函數仍使用當前的環境變量表執行新程序。

 

例:

\

運行結果:

\

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved