《LINUX實操:關于Linux進程環境》要點:
本文介紹了LINUX實操:關于Linux進程環境,希望對您有用。如果有疑問,可以聯系我們。
內核執行c法式時,利用exec函數調用一個特殊的啟動例程,該啟動例程叢內核中獲取命令行參數和環境變量值.
5種正常終止的情況:
(1)從main函數返回;
(2)挪用exit;
(3)挪用_exit和_Exit函數;
(4)最后一個線程挪用pthread_exit;
(5)最后一個線程從其啟動例程返回;
3種異常終止情況
(1)調用abort;
(2)接到一個信號;
(3)最后一個線程對取消哀求做出響應;
一個進程最多可以登記32和函數(例如:signal函數),這些函數由exit函數自動調用.在法式終止時調用這些函數,形成終止處理法式,來進行結束進程前的收尾工作.而exit函數通過atexit函數的登記記錄來判斷調用哪些函數.
此函數由ISO C 定義,其操作包含處理終止處理程序,然后關閉所有標準I/O流.需要注意的是,它不會處理文件描述符、多進程(父子進程)以及作業控制.
無論進程怎樣結束,它都會在內核上執行同一段代碼(由進程啟動和退出圖可知).這段代碼來關閉所有的文件描述符,釋放所有的存儲空間.
程序退出后,利用退出碼告知該進程的父進程.父進程通過wait或waitpid函數來完成該子進程的善后工作(獲取子進程相關信息 釋放子進程占用資源).若父進程沒有處理子進程的退出狀態,則子進程釀成僵死進程.相反的,若父進程在子進程前終止,則子進程釀成孤兒進程.孤兒進程會由1號進程(init進程)接收,大致過程如下:
(1)進程終止時,內核逐個檢查所有活動的進程;
(2)分析查找該終止進程的子進程;
(3)將該進程的子進程的父進程ID改為1;
程序正常或異常終止時,內核都會向父進程發送SIGNAL信號.子進程終止是異步事件,所以該信號也是異步信號.而該信號一般會被父進程默認忽略.或者提供一個信號處理函數來善后.wait和waitpid函數便是其中的信號處理函數的一部分.
wait和waitpid函數區別如下:
(1)wait會阻塞調用者進程期待直至第一個終止的子進程到來;
(2)waitpid可以通過參數設置,來實現調用者進程不阻塞,或選擇要阻
塞期待的子進程;
這里的調用者指的是父進程
和環境變量相關的函數如下:
#include<stdlib.h>
char *getenv(const char *name);
返回值:指向與name關聯的value的指針;若未找到,返回NULL
int putenv(char *str);
返回值:若成功,返回0;若出錯,返回非0
int setenv(const char *name, const char *value,
int rewrite);
int unsetenv(const char *name);
兩個函數返回值:若成功,返回0;若出錯,返回-1
環境表和環境字符串通常存放在內存空間的高地址處(頂部).所以在修改它的值時,內存是不克不及繼續向高地址延伸;但又因為,它之下是各個棧幀,所以也不克不及向下延伸.如何修改它的值的過程如下:
(1)改動環境表
1)新value <= 舊value,直接覆蓋舊value的存儲空間
2)新value >= 舊value,調用malloc函數,在堆區開辟新的存儲空間,
將新value復制到這里,再將這片存儲區首地址寫到環境表相應的地位處.
(2)新增環境表
1)新增一個環境變量,調用malloc函數開辟新的存儲空間,將本來的環
境表復制到該存儲區,其次再添加一個環境變量,然后在尾部賦值為NULL,
最后將environ指向該區域;
2)在 1)過程的基礎上,調用realloc函數,多次添加環境變量;
注意:以這種方式修改的環境變量只在當下程序運行時有效,當程序結束時,相應的存儲區被系統回收,這些修改就會失效.
#include<stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nojy, size_t size);
void *realloc(void *ptr, size_t newsize);
3個函數返回值:若成功,返回非空指針;若出錯,返回NULL
注意:這些動態分配的函數一般在分配存儲空間時,會比要求的大.因為在開辟空間的前后部分存儲記錄管理信息.因此,在使用時,千萬不要越界拜訪,以免造成不可預知的后果.
在c語言中,goto語句是不克不及跨函數跳轉的.尤其是在函數深層調用時的跳轉需求,在出錯處理的情況下非常有用.
#include<setjmp.h>
int setjmp(jmp_buf env);
返回值:若直接調用,返回0;若從longjmp返回,返回非0
void longjmp(jmp_buf env, int val);
變量值回滾問題:自動變量和寄存器變量會存在回滾現象.利用volatile屬性來避免此類情況的產生.(在給變量賦值時,賦的值回首先存儲在內存(存儲器變量)中,然后在由cpu取走,存儲在cpu的寄存器上(寄存器變量).在做系統優化時,那些頻繁使用的變量,會直接存儲到寄存器中而不經過內存.)
在調用setjmp函數時,內核會把當前的棧頂指針保存在env變量中,所以在調用longjmp函數返回該位置時,全局變量、靜態變量、易失變量和自動變量如果在調用setjmp和longjmp函數之間它們的值被修改過,是不會回滾到setjmp函數調用之前的值(當然,編譯器將auto變量優化為寄存器變量除外).因為,這些存儲器變量的值是存儲在內存相應的段中,回到原先棧頂狀態時,同樣拜訪的還是原先的內存空間.
然而,對于寄存器變量來說,首先要明確一點:寄存器變量是用動態存儲的方式.意思是寄存器變量的值可能存在分歧的寄存器中.如果在調setjmp和longjmp函數之間它們的值被修改過,這個值可能不會存到setjmp之前的對其賦值的寄存器中,而在調用longjmp函數后,又回到了調用setjmp函數時的狀態.這個時候再讀取寄存器變量的值時,讀到的是原先那個寄存器中存儲的值而不是修改過的那個寄存器中存儲的值,所以出現的回滾現象.
本文永遠更新鏈接地址:
維易PHP培訓學院每天發布《LINUX實操:關于Linux進程環境》等實戰技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養人才。
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/7683.html