進程的終止函數
C程序的啓動函數是main,也是進程代碼的入口點;
main(int argc, char *argv[]);
argc:參數個數
argv[]:傳入的參數表
當內核啓動C程序時,會調用main函數前調用特殊的啓動函數來獲取main函數的地址和傳遞main函數的參數,並且將這些信息填寫到進程控制塊中。
正常終止:
(1)從main函數中返回
(2)在任意代碼中調用
終止程序的2個exit函數:
(1)頭文件stlib.h,函數定義:void exit(int status)
(2)頭文件unistd.h,函數定義:void _exit(int status)
相同點:
調用這兩個函數都會正常地終止一個進程
不同點:
_exit函數:調用_exit函數將會立即返回內核
exit函數:調用exit函數,會執行下面3個操作:
1)執行預先註冊地終止處理函數
2)執行文件I/0操作地善後工作,使得所有緩衝地輸出數據被更新到相應地設備
3)返回內核
return 與 exit地區別:
(1)reuan 是C語言地關鍵字,exit是POSIX API函數
(2)在main函數中,執行return和調用exit函數會產生相同地效果
(3)在子函數中,執行return僅僅從子函數中返回,而調用exit函數將會退出當前進程。
執行exit函數後地一些效應:
(1)當進程終止時,程序可能需要進行一些自身地清理工作,如日誌登記、資源釋放等;
(2)通過atexit函數或on_exit函數允許進程註冊若干終止處理函數,當進程終止時,這些終止處理函數將會被自動調用。
註冊終止處理函數:
(1)頭文件stdlib.h
- int atexit(void(*func)(void));
- int on_exit(void(func)(int, void), void *arg)
(2)ABSI C規定一個進程最多隻能註冊32個終止處理函數
(3)當顯示調用或隱含調用exit函數終止進程(從main中返回、最後一個線程退出等)將會回調這些註冊終止處理函數(最先註冊地函數最後被回調)
(4)顯示調用_exit函數終止進程時將不會回調這些註冊地終止函數
atexit例子:
void func1() {
printf("func1 is called\n");
}
void func2() {
printf("func2 is called\n");
}
void fun3() {
printf("func3 is called\n");
}
int main(int argc, char **argv) {
atexit(func1);
atexit(func2);
atexit(func3);
printf("process exit\n");
return 0;
}
程序運行效果:(感覺有點像棧)
on_exit列子:
void func1(int status, void *arg) {
printf("func1 exit status is %d\n", status);
printf("func1 arg is %d\n", *((int *)arg));
}
void func2(int status, void *arg) {
printf("func2 exit status is %d\n", status);
printf("func2 arg is %d\n", *((int *)arg));
}
void func3(int status, void *arg) {
printf("func3 exit status is %d\n", status);
printf("func3 arg is %d\n", *((int *)arg));
}
int i, j, k;
int main(int argc, char **argv) {
i = 3;
on_exit(func1, (void *)&i);
j = 4;
on_exit(func2, (void *)&j);
k = 5;
on_exit(func3, (void *)&k);
printf("process exit\n");
return 0;
}
運行效果:
進程的環境
進程內存空間佈局
這裏有兩個,一個是進程的內核空間資源,一個是用戶空間資源;’
用戶空間:
正文:CPU執行的代碼部分,正文段通常是共享、可讀的。
數據段:
- 初始化的數據段:保研程序中需明確賦初值的變量,如全局變量int maxcount=99;
- 未初始化的數據段:程序執行之前,將此段中的數據初始化未0,如全局變量long sum[1000];
棧:主要用於支撐函數調用存放參數、局部變量等等
命令行參數:
- ls[參數]<路徑或文件名>
- mkdir
- copy
例子:
#include <stdio.h>
int main(int argc, char ** argv) {
int i;
for(i = 0; i < argc; i ++)
printf("Argument %d is %s.\n", i, argv[i]);
return 0;
}
運行效果:
環境變量表:
環境變量是Linux系統所特有的;
-
每個進程都會自己的環境變量表
-
通過全局的環境執指針(environ)可以直接訪問環境變量表(字符傳數組)
1)頭文件:unistd.h
2)extern char **environ; -
環境變量字符串形式爲"name = value",name是環境變量名稱,value爲環境變量賦值
-
獲取環境變量的方法
1)直接通過environ變量訪問環境表
2)使用getenv函數 -
getenv函數用於獲取環境變量值
1)頭文件:stdlib.h
2)char* getenv(const char *name)
3)指定環境變量的名稱,返回環境變量字符串指針,若未找到則返回空之指針 -
設置環境變量的三種方法
1)putenv
2)setenv
3)unsetenv -
putenv函數將環境變量字符串放入環境變量表中;若該字符串已經存在,則覆蓋
1)頭文件:stdlib.h
2)int putenv(char *str); -
setenv
1)頭文件:stdlib.h
2)int setenv(const char* name, const char* value, int rewrite);
3)setenv將指定環境變量的值設置爲參數指定值(更改環境變量字符串)
4)若是name已經存在, rewrite不等於0,則刪除其原先的定義;rewrite等於0,則不刪除其原先的定義 -
unsetenv
1)頭文件:stdlib.h
2)int unsetenv(const char* name)- 刪除指定的環境變量字符串