程式程式設計1 – Unix環境高階程式設計7章讀書筆記

ATField發表於2007-03-24

Process Environment

1 Process Termination

程式的終止有些下面的方法:

1.     main函式return

2.     呼叫exitexit屬於ISO C標準中定義的函式,會執行清理工作。包括關閉IO庫中所有開啟的檔案流(這會導致所有的檔案buffer都被flush),還會呼叫阿texit所註冊的退出函式。Exit還會。等價於return (0)

3.     呼叫_exit或者_Exit:這兩個函式都不會執行清理工作,直接退出程式。_exitPOSIX.1標準定義的函式,而_Exit則是ISO C標準定義的函式。

4.     最後一個執行緒從其執行緒函式return

5.     最後一個執行緒呼叫pthread_exit

非正常中止包括:

1.     Abort

2.     接收一個signal

3.     最後一個執行緒收到了Cancel請求

Atexit可以用來註冊多達32個退出函式:

#include <stdlib.h>

 

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

 

成功返回0,錯誤返回非0

這些函式以註冊的逆序被呼叫。同一個函式可以被註冊多次,並被呼叫多次。

 

2 Environment List

每個程式都被傳入一個環境列表,定義如下:

extern char **environ;

其實就是一個字串陣列,每個元素都是一個字串,表示一個環境變數,如HOME=/home/sar,以0結尾。而整個字串陣列也以NULL結尾。

 

3 Memory Layout

1.     Text Segment

2.     Initialized Data segment(Data Segment),一般簡稱為data。用來專門存放已經初始化的資料,如int maxcount = 99

3.     Uninitialized data segment,一般簡稱為bss,根據一個很古老的彙編語句BSS(代表Block Started by Symbol)命名。存放未初始化的資料,如long sum[1000]; 由核心自動初始化為0

4.     Stack,一般來說向低地址增長

5.     Heap,一般來說向高低址增長,和Stack共用一塊空間

4 Memory Allocation

1.     一般記憶體分配使用malloc / calloc / realloc,大家應該都很熟悉了,callocmalloc的區別是前者會初始化記憶體為0,而後者不會。這些函式一般用sbrk系統呼叫實現。

2.     除了一般的malloc/free等記憶體分配函式之外,部分系統還提供了一些替代函式。值得一提的是alloca函式,這個函式從Stack上分配記憶體空間,優點是速度快而且不用釋放,但是不是所有系統都支援,並且使用的場合有限。

5 Environment Variables

下列函式可以用來訪問環境變數:

#include <stdlib.h>

 

char *getenv(const char *name);

 

int putenv(char *str);

 

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

 

int unsetenv(const char *name);

 

成功返回0,錯誤返回非0

1.     getenv獲得環境變數的內容,如果沒有此變數則返回NULL

2.     putenv接受用name=value形式定義的引數,設定環境變數的值

3.     setenv設定name的值為value。如果rewrite=0並且name已經有值的話,不會設定name的值。

4.     unsetenv刪除name的值

 

6 setjmp & longjmp

goto可以跳轉到程式的另外的一個地方,但是有在同一個函式的限制。而setjmplongjmp提供了繞過此限制的跳轉功能:

#include <setjmp.h>

 

char *setjmp(jmp_buf env);

 

直接呼叫者返回0,從longjmp返回則返回非0

 

void longjmp(jmp_buf env, int val);

1.     longjmp應該返回的位置呼叫setjmp可以記住當前的函式的棧的相關資訊,並儲存到env之中。如果返回0,則是正常流程。如果返回非0,說明剛從longjmp返回

2.     Longjmp調到之前setjmp所記住的位置

需要注意的是,setjmp主要紀錄棧的相關資訊以保證程式流程可以跳轉到setjmp的位置並繼續執行,因此只能保證棧指標的正確位置,不會導致棧被破壞,但是棧上的變數則無法保證會被恢復,這個和具體實現相關。如果你想保證某個自動變數(棧上的變數)不被恢復的話,可以定義其為volatile

7 getrlimit and setrlimit

getrlimitsetrlimit可以定義程式相關的資源限制:

#include <sys/resource.h>

 

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

 

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

 

成功返回0,錯誤返回非0

 

rlimit結構定義如下:

struct rlimit {

      rlim_t      rlim_cur;   /* 當前limit,稱為soft limit */

      rlim_t      rlim_max;   /* 最大limit,稱為hard limit */

}

1.     程式可以修改soft limit為比hard limit小或者相等的任意值

2.     程式可以降低hard limit的值,但必須比soft limit大或者相等。注意normal user作這個操作是不可逆的

3.     只有super user才可以增加hard limit的值

4.     無限可以用常數RLIM_INFINITY

5.     注意soft limit是實際起作用的limit,而hard limit是一個限制值

Limit

Description

RLIMIT_AS

程式最大可用記憶體,對sbrk系統呼叫有影響

RLIMIT_CORE

Core(記憶體轉儲,用於事後除錯)檔案的最大Size

RLIMIT_CPU

程式佔用CPU的最大時間,超過此限制的時候則傳送SIGXCPU signal

RLIMIT_DATA

資料的最大Size,包括初始化資料,非初始化資料和Heap

RLIMIT_FSIZE

建立檔案的最大Size,如果超過則傳送SIGXFSZ signal

RLIMIT_LOCKS

最大檔案鎖的數量

RLIMIT_MEMLOCK

最大用mlock鎖定記憶體的Size

RLIMIT_NOFILE

開啟檔案的最大數量

RLIMIT_NPROC

每個user id的最大子程式數

RLIMIT_RSS

最大常駐記憶體Size。當記憶體不足時,核心會嘗試從記憶體使用量超過RSS的程式拿走一部分記憶體

RLIMIT_SBSIZE

一個使用者所能使用的Socket緩衝區的最大Size

RLIMIT_STACK

Stack的最大Size

RLIMIT_VMEM

等價於RLIMIT_AS

 

 

Links

程式程式設計1 – UNIX高階環境程式設計7章讀書筆記
UNIX訊號(signal)程式設計 - UNIX高階環境程式設計第10章讀書筆記
使用pthread庫進行多執行緒程式設計1 - UNIX環境高階程式設計第11章讀書筆記
使用pthread庫進行多執行緒程式設計2 - UNIX高階環境程式設計第12章讀書筆記

相關文章