7程序環境

2021-05-25 03:00:39 字數 4922 閱讀 8413

8忠方式使程序終止

五種正常終止

1,從main返回

2,呼叫exit

3,呼叫_exit或_exit

4,最後乙個執行緒從其啟動例程返回。

5,最後乙個執行緒呼叫pthread_exit。

異常終止有3種方式

6,呼叫abort

7,接到乙個訊號並終止

8,最後乙個執行緒對取消請求做出響應。

exit函式

#include

void exit(int status)

void _exit(int status)

#include

void _exit(int status)

exit函式總是執行乙個標準i/o庫的清理關閉操作:為所有開啟流呼叫fclose函式。這會造成所有緩衝的輸出資料都被沖洗。

三個exit函式都帶乙個整型引數,稱為終止狀態。大多數unix shell都提供檢查程序終止狀態的方法。如果a若呼叫這些函式時不帶終止狀態,或b main函式執行了乙個無返回值的return語句,或c main沒有宣告返回型別為整數,則該程序的終止狀態是未定義的。但是,若main的返回型別是整型,並且main執行到最後乙個語句時返回,那麼該程序的終止狀態是0.

exit(0)等價於return (0)

atexit函式

乙個程序可以登記多達32個函式,這些函式將由exit自動呼叫。稱這些函式為終止處理程式,並呼叫atexit函式來登記這些函式。呼叫順序與登記順序相反。統一函式如若登記多次,也會被呼叫多次。

環境表每個程式都會接收到一張環境表。環境表釋義個字元指標陣列,每個指標包含乙個以null結束的c字串的位址。全域性變數environ則包含了該指標陣列的位址

extern char **environ

environ:環境指標->環境表

項1-> home=/home/sar/0

項2-> path=:/bin:/usr/bin/0

null

c程式的儲存空間分布

1,正文段,由cpu執行的機器指令部分。

2,初始化資料段,資料段,包含了程式中需明確地賦初值的變數。c程式中出現在任何函式之外的宣告:

int maxcount =99;

3,非初始化資料段,稱為bss段,在程式開始執行之前,核心將此段中的資料初始化為0或空指標。由符號開始的塊.出現在任何函式外的c宣告

long sum[1000]

4,棧,自動變數以及每次函式呼叫時所需儲存的資訊都存放在此段中。每次呼叫函式時,其返回位址以及呼叫者的環境資訊都存放在棧中。然後,最近被呼叫的函式在棧上為其自動和臨時變數分配儲存空間。

5,堆。

對x86處理器上的linux,正文段從0x08048000開始,棧底則在0xc0000000之下開始,棧從高位址向低位址方向增長。

高位址      ----------------------------

|命令列引數和環境變數   |

|         棧底                  |

|            堆                  |

|   未初始化的資料         |由exec初始化為0

| 初始化的資料              |由exec從程式檔案中讀入

低位址  | 正文                          |由exec從程式檔案中讀入

未初始化的資料段的內容並不存放在磁碟的程式檔案中。其原因是,核心在程式開始執行前將它們都設定為0。需要存放在程式檔案中的段只有正文段和初始化資料段。

size命令可以用來檢視

共享庫使得可執行檔案中不在需要包含共用的庫例程,而只需要在所有程序都可引用的儲存區中維護這種庫例程的乙個副本。程式第一次執行或者第一次呼叫某個庫函式時,用動態鏈結方法將程式與共享庫函式相鏈結。減少了每個可執行檔案的長度,增加了一些執行時間開銷。這種事間開銷發生在該程式第一次被執行時,或者每個共享庫函式第一次被呼叫時。

儲存器分配

void malloc(size_t size)

void calloc(size_t nobj, size_t size)

void realloc(void *ptr, size_t newsize)

void free(void * ptr)

大多數實現所分配的儲存空間比所要氣度額要稍大一些,額外的空間用來記錄管理資訊--分配塊的長度,指向下乙個分配塊的指標等等。這就意味著如果超過乙個已分配區的尾端進行寫操作,則會重寫後乙個塊的管理記錄。

在動態分配的緩衝區前或後進行寫操作,破壞的可能不僅僅是該區的管理記錄資訊。在動態分配的緩衝區前後的儲存區很可能用於其他動態分配的物件。

環境變數

環境字串形式

name=value

unix核心並不檢視這些字串,他們的解釋完全取決於各個應用程式。

#include

char * getenv(const char *name)返回值:指向與name關聯的value的指標,若未找到則返回null。

應當使用getenv而不是直接訪問environ

#include

int putenv(char*str)

取形式為name=value的字串,將其放到環境表中,如果name已經存在,則先刪除其原來的定義。

實現將傳送給它的字串位址作為引數直接放入環境表中。

int setenv(const char *name, const char*value, int rewrite)

將name設定為value。如果環境中name已經存在,那麼(a)若rewrite非0,則首先刪除其現有的定義;(b)若rewrite為0,則不刪除其現有定義。

int unsetenv(const char *name)

刪除name的定義。

環境表和環境字串通常存放在程序儲存空間的頂部(棧之上)。刪除乙個字串很簡單,只要先在環境表中找到該指標,然後將所有後續指標都向環境表首部順次移動乙個位置。環境表和環境字串通常占用的是程序位址空間的頂部,所以它不可能再向高位址方向(向上)擴充套件,同時也不能移動在它之下的各棧幀,所以它也不能向低位址方向(向下)擴充套件。

1)如果修改乙個現有name:

a)如果短,直接修改

b)如果長,必須呼叫malloc分配空間,然後將新字串複製到該空間中,調整環境表指標。

2)增加乙個name

a)第一次增加乙個新name,呼叫malloc為新的指標表分配空間,將原來的環境表複製到新分配區。並將指向新name=value字串的指標存放在該指標表的表尾,然後又將乙個空指標存放在其後。最後使environ指向新指標表。

b)用realloc分配空間,類似於a)

setjmp和longjmp

可以跨越函式。對於處理發生在深層巢狀函式呼叫中的出錯情況是非常有用的。

不是由普通c語言goto語句在乙個函式內實施的跳轉,而是在棧上跳過若干呼叫幀,返回到當前函式呼叫路徑上的某乙個函式中。

#include

int setjmp(jmp_buf env);

void longjmp(jmp_buf env, int val);

在希望返回到的位置呼叫setjmp,引數env是乙個特殊型別jmp_buf。這一資料型別是某種形式的陣列,其中存放在呼叫longjmp時能用來恢復棧狀態的所有資訊。因為需要在另乙個函式中引用env變數,所以規範處理方式是將env定義為全域性。以兩個引數呼叫longjmp函式。第乙個就是在呼叫setjmp時所用的env,第二個引數是具有非0值的val,它將成為從setjmp處返回的值。對於乙個setjmp可以有多個longjmp。通過返回值,可以判斷返回發生在那個函式中。

自動,暫存器和易失變數。

當longjmp返回到main函式時,這些變數的值是否能恢復到以前呼叫setjmp時的值?這個要看情況。大多數實現並不會滾這些自動變數和暫存器變數的值,而所有標準則說它們的值是不確定的。如果有乙個自動變數,而又不想使其值回滾,則可定義其為具有volatile屬性。宣告為全域性或靜態變數的值在執行longjmp時保持不變。

參考volatile

自動變數的潛在問題

file * open_data(void)

file *fp;

char databuf[bufsiz];

if((fp = fopen(datafile, "r")) == null)

return(null);

if(setvbuf(fp, databuf, _iolbf, bufsiz) != 0)

return(null);

return (fp);

當open_data返回時,它在棧上所使用的空間將由下乙個被呼叫函式的棧幀使用,但是,標準i/o庫函式仍將使用其流緩衝區的儲存空間。這就產生了衝突。應在全域性儲存空間靜態地或者動態地為陣列databuf分配空間。

#include

int getrlimit(int resource, struct rlimit *rlptr);

int setrlimit(int resource, const struct rlimit *rlptr);

程序的資源限制通常實在系統初始化時由程序0建立的,然後由每個後續程序繼承。

對這兩個函式的每一次呼叫都會指定乙個資源以及乙個指向下列結構的指標。

struct rlimit{

rlim_t rlim_cur; /*soft limit:current limit */

rlim_t rlim_max; /*hard limit:maximum value for rlim_cur*/

更改的三條規則:

1)任何乙個程序都可將乙個軟限制值更改為小於或等於其硬限制值

2)任何乙個程序都可降低其硬限制值,但它必須大於或等於其軟限制值。這種降低對普通使用者而言是不可逆的。

3)只有超級使用者程序可以提高硬限制值。

常量rlim_infinity指定了乙個無限量的限制。

資源限制影響到呼叫程序並由其子程序繼承。這就意味著為了影響乙個使用者的所有後續程序,需將資源限制的設定構造在shell之中。

cha7 程序環境

一 main 函式 1.函式原型int main int argc,char ar 2.引數 argc 命令列引數的數目 ar 指向引數的各個指標構成的陣列 二 程序終止 1.有8種程序終止方式,5種正常終止,3種異常終止 1 正常 a.從main 函式返回 b.呼叫exit 先執行清理處理 標準i...

Unix環境高階程式設計筆記 7 程序環境

1 程序終止 a 程序終止的8種方式 從main返回 呼叫exit 呼叫 exit或 exit 最後乙個執行緒從其啟動程序返回 最後乙個執行緒呼叫pthread exit 呼叫abort 接到乙個訊號並終止 最後乙個執行緒對取消請求做出響應 b exit函式 exit和 exit立即進入核心,exi...

第7章 程序環境

main函式之前會有乙個特殊的啟動程式,啟動例程從核心取得命令列引數和環境變數。正常終止 從main函式返回 呼叫exit 呼叫 exit或 exit 最後乙個執行緒從啟動例程返回 最後乙個執行緒呼叫pthread exit 異常終止 呼叫abort 接到乙個訊號終止 最後乙個執行緒對取消請求作出相...