天天看點

UNIX進階程式設計:第7章 程序環境

請移步到這:

http://note.youdao.com/noteshare?id=7896d7e621203ead98bac87831143a84&sub=B28BAAE5F8AF40348692BF1B708FFBB6

7.2 main函數

7.3 程序中止

有8種方式使程序終止(termination),

其中5種為正常終止,它們是:

(1)從main傳回;

(2)調用exit:

(3)調用exit或_Exit;

(4)最後一個線程從其啟動例程傳回(11.5節);

(5)從最後一個線程調用pthread_exit (11.5節),

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

(6)調用abort (10.17節);

(7)接到一個信号(10.2節);

(8)最後一個線程對取消請求做出響應(11.5節和12.7節)。

1.退出函數

3個退出函數都帶一個整型參數,稱為終止狀态(或退出狀态, exit status),大多數UNIX系,統shell都提供檢查程序終止狀态的方法。

如果

(a)調用這些函數時不帶終止狀态

(b) main執行了一個無傳回值的return語句

(c) main沒有聲明傳回類型為整型,則該程序的終止狀态是未定義的。

但是,若main的傳回類型是整型,并且main執行到最後一條語句時傳回(隐式傳回),那麼該程序的終止狀态是0.

不做任何傳回的現象:

2. 函數atexit

用sysconf(_SC_ATEXIT_MAX)可以得到最大值

注意:

核心使程式執行的唯一方法是調用一個exec函數。

程序自願終止的唯一方法是顯式或 ,隐式地(通過調用exit)調用exit或Exit.程序也可非自願地由一個信号使其終止(圖7-21中沒有顯示),

7.4 指令行參數

7.5 環境表

geten,putenv——》通路特定

第三參數,environ——》通路全部

7.6 c程式的存儲空間布局

•曆史沿襲至今, C程式一直由下列幾部分組成:

正文段。

這是由CPU執行的機器指令部分。通常,正文段是可共享的,是以即使是頻繁執行的程式(如文本編輯器、C編譯器和shell等)在存儲器中也隻需有一個副本,另外,正文段常常是隻讀的,以防止程式由于意外而修改其指令。

初始化資料段。

通常将此段稱為資料段,它包含了程式中需明确地賦初值的變量。例如,C程式中任何函數之外的聲明:

int maxcount = 99:

使此變量以其初值存放在初始化資料段中。

未初始化資料段。

通常将此段稱為bss段,這一名稱來源于早期彙程式設計式一個操作符,意思是“由符号開始的塊” (block started by symbol),在程式開始執行之前,核心将此段中的資料初始化為0或空指針。函數外的聲明:

long sum [10001];

使此變量存放在非初始化資料段中。

棧。

自動變量以及每次函數調用時所需儲存的資訊都存放在此段中。每次函數調用時,其傳回位址以及調用者的環境資訊(如某些機器寄存器的,值)都存放在棧中。然後,最近被調用的函數在棧上為其自動和臨時變量配置設定存儲空間。通過以 ,這種方式使用棧, C遞歸函數可以工作。遞歸函數每次調用自身時,就用一個新的棧幀,是以一次函數調用執行個體中的變量集不會影響另一次函數調用執行個體中的變量。

堆。

通常在堆中進行動态存儲配置設定。由于曆史上形成的慣例,堆位于未初始化資料段和棧之間。

7.7 共享庫

7.8 存儲空間配置設定

參考:https://blog.csdn.net/david_xtd/article/details/7311204

擴充(或縮小)程序的堆——>>通常用sbrk(2)系統調用實作。

大多數實作所配置設定的存儲空間比所要求的要稍大一些,額外的空間用來記錄管理資訊-配置設定塊的長度、指向下一個配置設定塊的指針等。

這就意味着,如果超過一個已配置設定區的尾端或者在已,配置設定區起始位置之前進行寫操作,則會改寫另一塊的管理記錄資訊。這種類型的錯誤是災難性的,但是因為這種錯誤不會很快就暴露出來,是以也就很難發現。

在動态配置設定的緩沖區前或後進行寫操作,破壞的可能不僅僅是該區的管理記錄資訊。在動态配置設定的緩沖區前後的存儲空間很可能用于其他動态配置設定的對象。這些對象與破壞它們的代碼可能無關,這造成尋求資訊破壞的源頭更加困難。

其他可能産生的緻命性的錯誤是:

1.釋放一個已經釋放了的塊

2.調用free時所用的指針不是3個alloc函數的傳回值等。

如若一個程序調用malloc函數,但卻忘記調用free函數,那麼,該程序占用的存儲空間就會連續增加,這被稱為洩漏(leakage),如果不調用free函數釋放不再使用的空間,那麼程序位址空間長度就會慢慢增加,直至不再有空閑空間。此時,由于過度的換頁開銷,會造成性能下降。

解決上面的問題:

因為存儲空間配置設定出錯很難跟蹤,是以某些系統提供了這些函數的另一種實作版本。

1.每次調用這3個配置設定函數中的任意一個或free時,它們都進行附加的檢錯。

2.在調用連接配接編輯器時指定,一個專用庫,在程式中就可使用這種版本的函數。

3.此外還有公共可用的資源,在對其進行編譯時使用一個特殊标志就會使附加的運作時檢查生效。

這些函數要另外下載下傳

7.9 環境變量

輸出環境變量:

設定環境變量:

我們可能希望改變現有變量的值,或者是,增加新的環境變量。

我們說改變的環境變量,隻是目前程序及其後生成和調用的任何子程序的環境

我們的改變是不能影響父程序的環境,這通常是一個shell程序。

盡管如此,修改環境表的"能力仍然是很有用的。)遺憾的是,并不是所有系統都支援這種能力。圖7-8列出了由不同的标準,及實作支援的各種函數。

修改環境表的原理

7.10 函數setjmp和longjmp

參考這個部落格啥都了解:

https://blog.csdn.net/smstong/article/details/50728022

非局部跳轉語句---setjmp和longjmp函數。

這不是由普通C語言goto,goto語句隻能在一個函數内實施的跳轉

而setjmp和longjmp是在棧上跳過若幹調用幀,傳回到目前函數調用路徑上的某一個函數中。

自己總結:

這個機制就是解決,在多層嵌套函數中,當發生異常後,函數要先一層一層傳回,最後到main函數中去執行出錯,這樣效率太低。

于是改為直接跳轉到main函數的棧中去執行,這樣更快

注意:

全局變量、靜态變量和易失變量不受優化的影響,在ongimp之後,它們的值是最近所呈現的值。在某個系統的setjmp(3)手冊頁上說明,存放在存儲器中的變量将具有lngjmp時的值,而在CPU和浮點寄存器中的變量則恢複為調用setimp時的值。這确實就是運作圖7-13程,序時所觀察到的值。

不進行優化時,所有這5個變量都存放在存儲器中(即忽略了對regival變量的register存儲類說明),

而進行了優化後, autoval和reqival都存放在寄存器中(即使 autoval并未說明為register), volatile變量則仍存放在存儲器中。

總結:

通過這一執行個體我們可以了解到,如果要編寫一個使用非局部跳轉的可移植程式,則必須使用volatile屬性。進而讓一些變量不要優化,因為有些變量我們需要得到改變後的值,而不是優化後的值。但是從一個系統移植到另一個系統,其他任何事情都可能改變。

沒讀懂?

7.11 函數getrlimit和setrlimit

結構體在這

繼續閱讀