讀書筆記——《UNIX環境高級編程》第七章_ 進程環境

第七章 進程環境

各位觀衆,今天節目的主要內容有:

1、  當執行程序時,其main函數是如何被調用的?

2、  命令行參數是如何傳送給執行程序的?

3、  典型的存儲器而已是什麼樣式?

4、  如何分配另外的存儲空間?

5、  進程如何使用環境變量?

6、  各種不同進程終止方式

另外,本期特別報導:

         longjmpsetjmp函數以及它們與棧的交互作用;進程的資源限制。

請看詳細報導:

1、 main函數

C程序總是從main函數開始執行,當內核執行C程序時,在調用main前先會調用一個特殊的啓動例程,啓動例程從內核取得命令行參數和環境變量值,然後爲按上述方式調用 main函數做好安排。

那麼一個程序啓動了,又是如何終止的呢,請看繼續報導:進程終止。

2、 進程終止

8種方式可使進程終止,其中5種爲正常終止,它們是:

1.       main返回

2.       調用exit

3.       調用_exit_Exit

4.       最後一個線程從其啓動例程返回(第11.5期節目中,將會做詳細報導)

5.       最後一個線程調用pthread_exit(第11.5期節目中,將會做詳細報導)

異常有3種方式,它們是:

1.       調用abort(第10.17期節目中,將會做詳細報導)

2.       接到一個信號並終止(第10.2期節目中,將會做詳細報導)

3.       最後一個線程對取消請求做出響應(第11.512.7期節目中,將會做詳細報導)

 

上一節提到到的啓動例程會使main返回後立即調用exit函數,如果啓動例程以C代碼形式表示(事實上啓動例程是常常使用匯編語言編寫),那麼它調用main函數的形式就可能是如下:

exit(main(argc,argv));

下面來看一看exit函數相關資料:

前面已經看到,exit 和他兩個兄弟 _exit _Exit三種方式可以正常終止程序,那麼這三個兄弟區別在哪裏?請看下面:

_exit_Exit立即進入內核,而exit則先執行一些清理處理(包括調用執行各終止處理程序,送親所以有標準I/O流等),然後進入內核,所以exit要稍微勤快點,乾的事稍微多一點。

exit對於標準I/O庫的清理關閉操作主要是通過爲所有打開流執行fclose函數,回憶5.5期節目中對fclose的介紹,這會造成所有緩衝的輸出數據都被沖洗。

這三個兄弟,工作時都會帶一個整型參數,這個參數將被用於標明程序的終止狀態,也就是說,參數是什麼值,那麼,程序的終止狀態就是什麼值,對將對於我們判斷一處程序問題出在哪裏將非常有用。但是如果進程終止時出現以下三種情況:

1.       調用exit函數時沒有帶終止態

2.       main執行了一個無返回值的return語句

3.       main沒有聲明返回類型爲整型

程序的終止態就是未定義的

 

另外,若main返回類型是整型,且在執行到最後一條語句時返回隱式返回,那麼該進程終止狀態將是0main函數中,返回一整型什與該值調用exit是等價的,於是,main函數中:

         exit(0);

等價於

         return(0);

 

2.1 atexit函數

         進程結束前期我們還可以調用一些函數做一些處理,這些函數被稱爲終止處理程序( exit handler,一個進程最多可以登記32個函數,函數將由exit自動調用,登記是由     atexit完成。定義如下:

         #include <stdlib.h>

         int atexit(void (*func)(void));

需要說明的是,exit調用終止處理程序的順序與它們登記的時候順序相反,同一函數若被登記多次,則也會被多次調用。另,exit執行時,首選調用各終止程序,然後再調用fclose,如果程序調用了exec函數族中任一函數,則將清除所有已安裝的終止處理程序。

注意,內核使程序執行的唯一方法是調用一個exec函數,進程自願終止的唯一方法是顯式或隱式地(通過調用exit)調用_exit_Exit。進程也可以非自願地由一個信號使其終止。

 

3、 命令行參數

當一個程序執行時,調用exec的進程可將命令行參數傳遞給新程序,例子可以參照  main(int argc,char *argv[]),不再過多討論,另外需要說明一點是argv[argc]是一個空指針

 

4、 C程序存儲空間佈局

C程序典型存儲器安排如下圖:

 


           說明:

正文段:CPU執行的機器指令部份,通常是正文段可以共享的且通常是隻讀的,以防止程序由於意外而修改其自身指令。

初始化數據段:通常被稱爲數據段,包含了程序中需明確地賦初值的變量。

非初始化數據段:程序開始前,內核將此段中的數據初始化爲0或空指針。如以下聲明:long  sum[100];將會被放於非初始化數據段。

堆與棧不再細說。

另外,未初始化數據段內容並不放在磁盤上的程序文件中,需要存放的只有正文段和初始化數據段。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章