mian函式
c程式總是從main函式開始執行。main函式的原型是:
int main(int argc, char *argv);
其中,argc是命令列引數的數目,argv是指向引數的各個指標所構成的陣列。
當核心執行c程式時,在呼叫main之前先呼叫乙個特殊的啟動例程。可執行程式檔案將此啟動例程指定為程式的起始位址——這是由鏈結編輯器設定的,而連線編輯器則由c編譯器呼叫。啟動例程從核心取得命令列引數和環境變數值,然後為按上述方式呼叫mian函式做好安排。
程序終止
有8中方式使程序終止,其中5種為正常終止,它們是:
1. 從main返回;
2. 呼叫exit;
3. 呼叫_exit或_exit;
4. 最後乙個執行緒從啟動例程返回;
5. 從最後乙個執行緒呼叫pthread_exit。
異常終止有3種方式,它們是:
6. 呼叫abort;
7. 接到乙個訊號;
8. 最後乙個執行緒對取消請求做出響應。
退出函式
#include
void
exit(int status);
void _exit(int status);
#include
void _exit(int status);
exit函式總是執行乙個標準i/o庫的清理關閉操作。
3個退出函式都帶乙個整型引數,稱為終止狀態。大多數unix系統shell都提供檢查程序終止狀態的方法。
如果(a)呼叫這些函式時不帶終止狀態,或(b)main執行了乙個無返回值的return語句,或(c)main沒有宣告返回型別為整型,則該程序的終止狀態是未定義的。但是,若main的返回型別是整型,並且main執行到最後一條語句時返回,那麼該程序的終止狀態是0;
函式atexit
按照iso c規定,乙個程序可以登記多至32個函式,這些函式將有exit自動呼叫。我們成為這些函式為終止處理程式,並呼叫atexit函式來登記
#include
int atexit(void (*func)(void));
//返回值:若成功,返回0;若出錯,返回非0
其中,atexit的引數是乙個函式位址,當呼叫此函式時無需向它傳遞任何引數,也不期望它會返回乙個值。exit呼叫這些函式的順序與它們登記的順序是相反的。同一函式若被登記多次,也會被呼叫多次。
exit首先呼叫各終止處理程式,然後關閉所有開啟流。
命令列引數
當執行乙個程式時,呼叫exec的程序可以將命令列引數傳遞給該新程式。
環境表我們稱environ為環境指標,指標陣列為環境表,其中各指標指向的字串為環境字串。
c程式的儲存空間布局
歷史沿襲至今,c程式一直由下列幾部分組成:
1. 正文段。這是由cpu執行的機器指令部分。通常正文段是可共享的。
2. 初始化資料段。通常將此段稱為資料段,它包含了程式中需明確地賦初值的變數。
3. 未初始化資料段。通常將此段稱為bss段,這一名稱**於早期匯程式設計序乙個操作符,在程式開始執行之前,核心將此段中的資料初始化為0或空指標。
4. 棧。自動變數以及每次函式呼叫時所需儲存的資訊都存放在此段中。每次函式呼叫時,其返回位址以及呼叫者的環境資訊都存放在棧中。然後,最近被呼叫的函式在棧上為其自動和臨時變數分配儲存空間。通過以這種方式使用棧,c遞迴函式可以工作。
5. 堆。通常在堆中進行動態儲存分配。由於歷史上形成的慣例,堆位於未初始化資料段和棧之間。
儲存空間分配
iso c 說明了3個用於儲存空間動態分配的函式。
1. malloc,分配指定位元組數的儲存區。此儲存區中的初始值不確定。
2. calloc,為指定數量指定長度的物件分配儲存空間。該空間中的每一位都初始化為0
3. realloc,增加或減少以前分配區的長度。
#include
void *malloc(zise_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
//3個函式返回值:若成功,返回非空指標;若出錯,返回null
void
free(void *ptr);
環境變數
iso c定義了乙個函式getenv,可以用其取環境變數值,但是該標準又稱環境的內容是由實現定義的。
#include
char *getenv(const
char *name);
//返回值:指向與name關聯的value的指標;若未找到,返回null
注意,此函式返回乙個指標,它指向name = value 字串中的value。我們應當使用getenv從環境中取乙個指定環境變數的值,而不是直接訪問environ。
除了獲取環境變數值,有時也需要設定環境變數。
#include
int putenv(char *str);
//函式返回值:若成功,返回0;若出錯,返回非0
int setenv(const
char *name, const
char *value, int rewrite);
int unsetenv(const
char *name);
//兩個函式返回值:若成功,返回0;若出錯,返回-1
putenv取形式為name = value的字串,將其放到環境表中。如果name已經存在,則先刪除其原來的定義。
setenv將name設定為value。如果在環境中name已經存在,那麼(a)若rewrite非0,則首先刪除其現有的定義;(b)若rewrite為0,則不刪除現有的定義。
unsetenv刪除name的定義。
函式setjmp和longjmp
跳轉功能函式
#include
int setjmp(jmp_buf env);
//返回值:若直接呼叫,返回0;若從longjmp返回,則為非0
void longjmp(jmp_buf env, int val);
在希望返回到的位置呼叫setjmp。引數env的型別是乙個特殊型別jmp_buf。這一資料型別是某種形式的陣列,其中存放在呼叫longjmp時能用來恢復棧狀態的所有資訊。因為需在另乙個函式中引用env變數,所以通常將env變數定義為全域性變數。
#include "apue.h"
#include
#define tok_add 5
jmp_buf jmpbuffer;
int main(void)
}
函式getrlimit和setrlimit
每個程序都有一組資源限制,其中一些可以用getrlimit和setrlimit函式查詢和更改。
#include
int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const
struct rlimit *rlptr);
//兩個函式返回值:若成功,返回0;若出錯,返回非0
對這兩個函式的每一次呼叫都指定乙個資源以及乙個指向下列結構的指標。
struct rlimit;
在更改資源限制時,須遵守下列3條規則。
1. 任何乙個程序都可將乙個軟限制值更改為小於或等於其硬限制值。
2. 任何乙個程序都可降低其硬限制值,但它必須大於或等於其軟限制值。
3. 只有超級使用者程序可以提高硬限制值。
APUE 程序環境
本文使用golang的syscall,os,golang.org x sys unix包 main是程式的入口,golang中也亦是如此 啟動乙個程式時啟動例程負責從核心獲取命令列引數和環境變數,維護到程式的記憶體布局中 後文描述 import os func exit code int 使程式主動...
APUE 程序環境
本文章介紹程序的環境 1.main函式 c程式總是從main函式開始執行的,其原型是 int main int argc,char argv argc是命令列引數的個數 argv是指向引數的各個指標所構成的陣列 2.程序終止 有8種方式可以讓程序終止,其中前5種為正常終止 1.從main返回 2.呼...
APUE自學筆記 程序環境
c程式執行時,最開始執行的是啟動 啟動 再去呼叫main函式,然後整個c程式都已執行。由編譯器提供的,一般有兩種提供方式 原始碼 二進位制 gcc採用這種 gcc v 檔名 可以檢視gcc編譯鏈結的詳細情況時,可以看到有很多 o,這些 o檔案就是gcc提供的啟動 在程式的記憶體空間結構還沒有布局起來...