Linux下常用函式表(未完)
- pid_t getpid(void)
獲取當前程序的pid(processID),程序唯一識別符號
- pid_t fork(void)
用於建立一個程序,在核心中作業系統重新為其申請了一個PCB,複製父程序的所有資料,執行和父程序相同的操作,子程序和父程序唯一區別——pid不同
- fork函式有兩個返回值,如果fork成功,子程序中fork的返回值是0, 父程序中fork的返回值是子程序的pid,通過這樣的方式來區分父子程序。派生子程序的程序,即父程序,其pid不變;
- 對子程序來說,fork返回給它0,但它的pid絕對不會是0;之所以fork返回0給它,是因為它可以呼叫getpid()來獲取自己的pid;
- fork之後父子程序除非採用了同步手段,否則不能確定誰先執行,也不能確定誰先結束。認為子程序結束後父程序才從fork返回的,這是不對的,fork不是這樣的,vfork才這樣。
- pid_t wait(int *stat_loc)
- pid_t waitpid(pid_t pid, int *stat_loc, int options)
wait()函式用於使父程序阻塞,直到一個子程序結束或者該程序接收到了一個指定的訊號為止。如果該父程序沒有子程序或者它的子程序已經結束,則wait()函式就會立即返回
waitpid()的作用和wait()一樣,但它可以指定需要等待終止的子程序,它還有若干選項,如可提供一個非阻塞版本的 wait()功能,也能支援作業控制。實際上,wait()函式只是 waitpid()函式的一個特例,在Linux 內部實現 wait()函式時直接呼叫的就是waitpid()函式。
所需標頭檔案 | #include<sys/wait.h> | |
引數說明 | pid | pid>0:只等待程序ID等於pid的子程序,不管是否已經有其它子程序退出,只要指定的子程序還沒有結束,waitpid()就會一直等待下去 |
pid=-1:等待任何一個子程序退出,此時作用等同於wait() | ||
pid=0:等待其組ID等於呼叫程序組ID的任一子程序 | ||
pid<1:等待其組ID等於pid的絕對值的任一子程式 | ||
stat_loc | 這裡的stat_loc是一個整形指標,是該子程序退出時的狀態。若stat_loc不為空,可以通過它來獲取子程序的退出狀態。子程序的退出狀態可以由Linux中特定的巨集來測定 | |
options | WNOHANG:若由pid指定的子程序沒有結束,則waitpid()不阻塞而立即返回,此時返回值為0 | |
WUNTRACED:為了實現某種操作,由pid指定的的任一子程序已被暫停,且其狀態自暫停以來還未報告過,則返回其狀態 | ||
0:同wait(),阻塞父程序,等待子程序退出 | ||
函式返回值 | 正常:已成功結束執行的子程序程序號 使用選項WNOHANG 且沒有自程序退出:0 失敗:-1 |
- mode_t umask(mode_t mask)
功能 | 設定了使用者建立檔案的預設許可權 |
mask | 格式:XXX |
返回值 | 成功:已成功結束執行的子程序的pid 失敗:-1 |
注:umask設定了使用者建立檔案的預設許可權,它與chmod的效果剛好相反,umask設定的是許可權“補碼”,而chmod設定的是檔案許可權碼,umask是從許可權中“拿走”相應的位,且檔案建立時不能賦予執行許可權;
umask 命令允許你設定檔案建立時的預設模式,對應每一類使用者(檔案屬主、同組使用者、其他使用者)存在一個相應的umask值中的數字。對於檔案來說,這一數字的最大值分別是6。系統不允許你在建立一個文字檔案時就賦予它執行許可權,必須在建立後用chmod命令增加這一許可權。目錄則允許設定執行許可權,這樣針對目錄來說,umask中各個數字最大可以到7;
在使用umask命令之前一定要先計算清楚所需的許可權掩碼。否則可能會得到一些非常奇怪的結果;例如,如果將umask值設定為6 0 0,那麼所建立的檔案/目錄的預設許可權就是0 6 6!
-
exec函式族
exec函式族提供了一個在程序中啟動另一個程式執行的方法。它可以根據指定的檔名或目錄名找到可執行檔案,並用它來取代原呼叫程序的資料段、程式碼段和堆疊段,在執行完之後,原呼叫程序的內容除了程序號外,其他全部被新的程序替換了。另外,這裡的可執行檔案既可以是二進位制檔案,也可以是Linux下任何可執行的指令碼檔案。
使用exec函式族主要有兩種情況:
(1)當程序認為自己不能再為系統和使用者做出任何貢獻時,就可以呼叫exec函式族中的任意一個函式讓自己重生。
(2)如果一個程序想執行另一個程式,那麼它就可以呼叫fork函式新建一個程序,然後呼叫exec函式族中的任意一個函式,這樣看起來就像通過執行應用程式而產生了一個新程序。
exec函式族共有6種不同形式的函式。這6個函式可以劃分為兩組:
- execl、execle和execlp
- execv、execve和execvp
這兩組函式的不同在於exec後的第一個字元,第一組是l,在此稱為execl系列;第二組是v,在此稱為execv系列。這裡的l是list(列表)的意思,表示exec1系列函式需要將每個命令列引數作為函式的引數進行傳遞;而v是vector(向量)的意思,表示execv系列函式將所有函式包裝到一個向量陣列,即就是陣列指標中傳遞即可。
字尾 | 操作能力 |
l | 希望接收以逗號分隔的引數列表,列表以NULL指標作為結束標誌 |
v | 希望接收到一個以NULL結尾的字串陣列的指標 |
p | 是一個以NULL結尾的字串陣列指標,函式可以DOS的PATH變數查詢子程式檔案 |
e | 函式傳遞指定引數envp,允許改變子程序的環境,無後綴e時,子程序使用當前程式的環境 |
exec函式的原型如下:
- int execl(const char *path,const char * arg,…);
- int execle(const char *path,const char * arg,char * const envp[]);
- int execlp(const char * file,const char * arg,…);
- int execv(const char * path,char * const argv[]);
- int execve(const char * path,char * const argv[],char * const envp[]);
- int execvp(const char * file,char * const argv[]);
引數說明:
path:要執行的程式路徑。可以是絕對路徑或者是相對路徑。在execv、execve、execl和execle這4個函式中,使用帶路徑名的檔名作為引數。
file:要執行的程式名稱。如果該引數中包含“/”字元,則視為路徑名直接執行;否則視為單獨的檔名,系統將根據PATH環境變數指定的路徑順序搜尋指定的檔案。
argv:命令列引數的向量陣列。
envp:帶有該引數的exec函式可以在呼叫時指定一個環境變數陣列。其他不帶該引數的exec函式則使用呼叫程序的環境變數。
arg:程式的第0個引數,即程式名自身。相當於argv[0]。
…:命令列引數列表。呼叫相應程式時有多少命令列引數,就需要有多少個輸入引數項。注意:在使用此類函式時,在所有命令列引數的最後應該增加一個空的引數項(NULL),表明命令列引數結束。
返回值:-1表明呼叫exec失敗,無返回表明呼叫成功。
以上函式的功能相同,掌握其中一種即可。
C庫檔案介面函式
標頭檔案:#include<stdio.h>
- FILE *fopen(const char *path, const char *mode)
功能 | 開啟一個檔案 | |
path | 指定開啟的檔案路徑及檔名 | |
mode | r | 以只讀方式開啟檔案,該檔案必須存在 |
r+ | 以讀/寫方式開啟檔案,該檔案必須存在 | |
w | 開啟只寫檔案,若檔案存在則長度清為 0,即該檔案內容消失,若不存在則建立該檔案 | |
w+ | 開啟可讀/寫檔案,若檔案存在則檔案長度清為零,即該檔案內容會消失。若檔案不存在則建立該檔案 | |
a | 以附加的方式開啟只寫檔案。若檔案不存在,則會建立該檔案,如果檔案存在,寫入的資料會被加到檔案尾 | |
a+ | 以附加方式開啟可讀/寫的檔案。若檔案不存在,則會建立該檔案,如果檔案存在,則寫入的資料會被加到檔案尾後 | |
返回值 | 成功:返回檔案指標 失敗:NULL |
- int fclose(FILE *fp);
功能 | 關閉一個檔案 |
fp | 檔案指標 |
返回值 | 成功:0 失敗:返回“-1”並輸出錯誤原因 如果流為NULL,而且程式可以繼續執行,fclose設定error number給EINVAL,並返回EOF |
注:使用fclose()函式就可以把緩衝區內最後剩餘的資料輸出到核心緩衝區,並釋放檔案指標和有關的緩衝區。
- size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
函式釋義:fread函式從stream指向的檔案流中,讀取nmemb個數據元素(nmemb這裡我看成n個memory block 即記憶體塊),每個元素size 位元組長,並將這些資料儲存到ptr指向的地址裡面。
功能 | 從檔案流中讀取資料 |
ptr | 接受資料的地址 |
size | 每次要讀的位元組數,單位是位元組 |
nmemb | 要讀nmemb個數據項,每個資料項size個位元組 |
stream | 輸入流 |
返回值 | 成功:返回實際讀取到的項個數(小於或等於nmemb) 失敗:返回 0(讀到檔案末尾也返回0) |
- size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
函式釋義:fwrite函式從ptr指向的地址裡面獲取nmemb個數據元素,每個size位元組長,將這些資料存到stream指向的檔案流中。
功能 | 向指定的檔案中寫入若干資料塊 |
ptr | 要寫入檔案的資料 |
size | 每次要寫入的位元組數,單位是位元組 |
nmemb | 要寫nmemb個數據項,每個資料項size個位元組 |
stream | 目標檔案指標 |
返回值 | 返回實際寫入的資料項個數nmemb |
注:
- 寫入到檔案的哪裡? 這個與檔案的開啟模式有關,如果是w+,則是從file pointer指向的地址開始寫,替換掉之後的內容,檔案的長度可以不變,stream的位置移動nmemb個數;如果是a+,則從檔案的末尾開始新增,檔案長度加大.
- fread和fwrite返回讀取或寫入的資料元素的個數。只有當size等於1的時候,返回的元素個數才與傳輸的位元組數目相等。 如果發生錯誤,或者到達檔案檔案末尾,這個返回值就會小於nmemb(當最後一次讀取或寫入不夠nmemb個數據元素時)或者甚至是0 fread函式並不區別是發生了錯誤還是到達檔案尾,則這就需要呼叫者feof和ferror來判斷是不是到達檔案尾或者發生了錯誤.
- fseek對此函式有作用,但是fwrite函式寫到使用者空間緩衝區,並未同步到檔案中,所以修改後要將記憶體與檔案同步可以用fflush(FILE *fp)函式同步.
- int fseek(FILE *stream, long offset, int whence)
函式釋義:設定檔案指標stream的位置。如果執行成功,stream將指向以whence為基準,偏移offset個位元組的位置。如果執行失敗(比如offset超過檔案自身大小),則不改變stream指向的位置。
功能 | 設定檔案指標stream的位置 | |
stream | 資料流指標 | |
offset | 偏移量 | |
whence | 檔案頭(SEEK_SET) | |
當前位置(SEEK_CUR) | ||
檔案尾(SEEK_END) | ||
返回值 | 成功:0 失敗:-1 |
注:fseek函式和lseek函式類似,但lseek返回的是一個off_t數值,而fseek返回的是一個整型
- long ftell(FILE *stream)
函式釋義:在隨機方式存取檔案時,由於檔案位置頻繁的前後移動,程式不容易確定檔案的當前位置。所以使用函式 ftell 易於得到檔案位置指標當前位置相對於檔案首的偏移位元組數,從而確定檔案指標當前位置。
功能 | 用於得到檔案位置指標當前位置相對於檔案首的偏移位元組數 |
stream | 資料流指標 |
返回值 | 成功:返回檔案位置指標當前位置相對於檔案首的偏移位元組數 失敗:-1 |
注:因為ftell返回long型,根據long型的取值範圍—,故對大於2.1G的檔案進行操作時出錯。
- void rewind(FILE *stream)
功能 | 將檔案內部的位置指標重新指向一個流的開頭 |
stream | 資料流指標 |
注:不是檔案指標而是檔案內部的位置指標,隨著對檔案的讀寫檔案的位置指標(指向當前讀寫位元組)向後移動。而檔案指標是指向整個檔案,如果不重新賦值檔案指標不會改變。
系統呼叫檔案介面函式
標頭檔案:#include<unistd.h>
- int open(const char *pathname, int flags)
- int open(const char *pathname, int flags, mode_t mode)
功能 | 開啟和建立檔案 | |
pathname | pathname 是待開啟/建立檔案的POSIX(可移植性作業系統介面)路徑名或檔案 | |
flags | O_RDONLY | 以只讀方式開啟檔案 |
O_WRONLY | 以只寫方式開啟檔案 | |
O_RDWR | 以可讀可寫方式開啟檔案 | |
O_CREAT | 如果指定檔案不存在,則建立這個檔案 | |
O_APPEND | 每次寫操作都寫入檔案的末尾(即就是追加寫入) | |
O_TRUNC | 如果檔案存在,並且以只寫/讀寫方式開啟,則清空檔案全部內容 | |
mode | 僅當建立新檔案時(即 使用了O_CREAT 時)才使用,用於指定檔案的訪問許可權位(access permission bits) | |
返回值 | 成功:返回最小的未被使用的描述符 失敗:-1 |
- int close(int fd)
功能 | 關閉檔案 |
fd | 資料流指標 |
返回值 | 成功:0 失敗:-1 |
注:當一個程序終止時,核心對該程序所有尚未關閉的檔案描述符呼叫close關閉,所以即使使用者程式不呼叫close,在終止時核心也會自動關閉它開啟的所有檔案。但是對於一個長年累月執行的程式(比如網路伺服器),開啟的檔案描述符一定要記得關閉,否則隨著開啟的檔案越來越多,會佔用大量檔案描述符和系統資源。
- ssize_t write(int fd, const void *buf, size_t count)
函式釋義:write()會把指標buf所指的記憶體寫入count個位元組到引數fd所指的檔案內。當然,檔案讀寫位置也會隨之移動。
功能 | 向指定檔案寫入資料 |
fd | 資料流指標 |
buf | 讀取資料的地址空間 |
count | 寫入的位元組數 |
返回值 | 成功:實際寫入的位元組數 失敗:-1 |
- ssize_t read(int fd, void *buf, size_t count)
函式釋義:read()會把引數fd 所指的檔案傳送count個位元組到buf指標所指的記憶體中
功能 | 從指定檔案讀取資料 |
fd | 資料流指標 |
buf | 寫入資料的地址空間 |
count | 讀取的位元組數 |
返回值 | 成功:實際讀取的位元組數。若返回的位元組數比要求讀取的位元組數少,則有可能讀到了檔案尾、從管道(pipe)或終端機讀取,或者是read()被訊號中斷了讀取動作。 失敗:-1。錯誤程式碼存入errno中,而檔案讀寫位置則無法預期。 |
- off_t lseek(int fd, off_t offset, int whence)
功能 | 設定檔案的讀寫指標 | |
fd | 資料流指標 | |
offset | 偏移量 | |
whence | 檔案頭(SEEK_SET) 將讀寫位置指向檔案頭後再增加offset個位移量 | |
當前位置(SEEK_CUR) 以當前的讀寫位置往後增加offset個位移量 | ||
檔案尾(SEEK_END) 將讀寫位置指向檔案尾後再增加offset個位移量 | ||
返回值 | 成功:返回當前的讀寫位置 失敗:-1 |
注:對於普通檔案(regular file),cfo(current file offset)是一個非負整數。但對於特殊裝置,cfo 有可能是負數。因此,我們不能簡單地測試 lseek 的返回值是否小於 0 來判斷 lseek 成功與否,而應該測試 lseek 的返回值是否等於 -1 來判斷 lseek 成功與否。
如果 offset 比檔案的當前長度更大,下一個寫操作就會把檔案“撐大(extend)”。這就是所謂的在檔案裡創造“空洞(hole)”。沒有被實際寫入檔案的所有位元組由重複的 0 表示。空洞是否佔用硬碟空間是由檔案系統(file system)決定的。
- int truncate(const char *path, off_t length)
函式釋義:truncate()會將引數path指定的檔案大小改為引數length指定的大小。 如果原來的檔案大小比引數length大,則超過的部分會被刪除
功能 | 修改指定檔案大小 |
path | 要修改的檔案路徑或檔名 |
length | 修改後的檔案大小 |
返回值 | 成功:0 失敗:-1 |
標頭檔案:#include<stdio.h>
- int fileno(FILE *stream)
函式釋義:fileno()用來取得引數stream指定的檔案流所使用的檔案描述符
功能 | 取得引數stream指定的檔案流所使用的檔案描述符 |
stream | 資料流指標 |
返回值 | 成功:資料流的檔案描述符 失敗:-1 |
- void clearerr(FILE *stream)
函式釋義:clearerr的作用是使檔案錯誤標誌和檔案結束標誌置為0.假設在呼叫一個輸入輸出函式時出現了錯誤,ferror函式值為一個非零值。在呼叫clearerr(fp)後,ferror(fp)的值變為0。
功能 | 復位錯誤標誌 |
stream | 資料流指標 |
標頭檔案#include <unistd.h>
- int dup(int oldfd)
- int dup2(int oldfd, int newfd)
功能 | 兩個均為複製一個現存的檔案的描述 |
oldfd | 目標檔案的檔案描述符的值 |
newfd | 指定新的檔案描述符的值 |
返回值 | 成功:資料流的檔案描述符 失敗:-1 |
注:dup()返回的檔案描述的值一定是當前可用檔案描述符當中的最小值;dup2()可以用newfd指定新描述符的值,如果newfd本身已經打開了,則會先將其關閉。如果newfd等於oldfd,則返回newfd,並不關閉它。
程序間通訊相關函式
-
管道(pipe)
標頭檔案:#include <unistd.h>
- int pipe(int pipefd[2])
功能 | 建立一個匿名管道 |
pipefd[0] | 管道的寫入端 |
pipefd[1] | 管道的讀取端 |
返回值 | 成功:0 失敗:-1 |
- int mkfifo(const char *pathname, mode_t mode)
功能 | 建立一個命名管道 |
pathname | 命名管道檔案路徑名 |
mode | 檔案許可權 |
返回值 | 成功:0 失敗:-1 |
注:mkfifo ()會依引數pathname建立特殊的FIFO檔案,該檔案必須不存在,而引數mode為該檔案的許可權,因此 umask值也會影響到FIFO檔案的許可權。
- key_t ftok(const char *pathname, int proj_id)
標頭檔案: #include <sys/ipc.h>
功能 | 系統建立IPC通訊 (訊息佇列、訊號量和共享記憶體)時必須指定一個ID值。通常情況下,該id值通過ftok函式得到。 |
pathname | 檔名 |
proj_id | 子序號。雖然是int型別,但是隻使用8bits(1-255) |
返回值 | 成功:檔案的inode結點號加上子序號(16進位制數) 失敗:-1 |
Linux程序通訊(IPC)之共享記憶體
共享記憶體函式由shmget、shmat、shmdt、shmctl四個函式組成。
- int shmget(key_t key, size_t size, int shmflg)
功能 | 得到一個共享記憶體識別符號或建立一個共享記憶體物件並返回共享記憶體識別符號 |
key | ftok返回的IPC鍵值 |
size | 新建的共享記憶體大小,以位元組為單位 |
shmflg | 共享記憶體許可權標誌。它的作用與open函式的mode引數一樣,如果要想在key標識的共享記憶體不存在時,建立它的話,可以與IPC_CREAT做或操作(例如:IPC_CREAT | 0664). |
返回值 | 成功:返回共享記憶體的識別符號 失敗:-1 |
- void *shmat(int shmid, const void *shmaddr, int shmflg)
功能 | 連線共享記憶體識別符號為shmid的共享記憶體,連線成功後把共享記憶體區物件對映到呼叫程序的地址空間,隨後可像本地空間一樣訪問 |
shmid | 共享記憶體的識別符號 |
size | 指定共享記憶體出現在程序記憶體地址的什麼位置,直接指定為NULL讓核心自己決定一個合適的地址位置 |
shmflg | SHM_RDONLY:為只讀模式,其它為讀寫模式 |
返回值 | 成功:對映首地址 失敗:((void*)-1) |
- int shmdt(const void *shmaddr)
功能 | 與shmat函式相反,是用來斷開與共享記憶體附加點的地址,禁止本程序訪問此片共享記憶體,也就是斷開對映 |
shmaddr | 對映首地址 |
返回值 | 成功:0 失敗:-1 |
- int shmctl(int shmid, int cmd, struct shmid_ds *buf)
功能 | 連線共享記憶體識別符號為shmid的共享記憶體,連線成功後把共享記憶體區物件對映到呼叫程序的地址空間,隨後可像本地空間一樣訪問 |
shmid | 共享記憶體的識別符號 |
cmd | IPC_STAT:得到共享記憶體的狀態,把共享記憶體的shmid_ds結構複製到buf中 |
IPC_SET:改變共享記憶體的狀態,把buf所指的shmid_ds結構中的uid、gid、mode複製到共享記憶體的shmid_ds結構內 | |
IPC_RMID:刪除這片共享記憶體 | |
buf | 共享記憶體管理結構體,用於獲取共享記憶體的狀態資訊 |
返回值 | 成功:0 失敗:-1 |
訊號相關函式
- int kill(pid_t pid, int sig)
- int raise(int sig)
- void abort(void)
功能 | 向程序傳送訊號 | |
kill | pid | 程序識別符號 |
sig | 訊號名稱 | |
可指定程序和傳送的訊號 | ||
raise | sig | 訊號名稱 向當前程序傳送指定訊號 |
可指定傳送的訊號 | ||
abort | 向當前程序傳送SIGABRT訊號 |
- unsigned int alarm(unsigned int seconds)
功能 | 在程序中設定一個定時器,當定時器指定的時間到時,它向程序傳送SIGALRM訊號 |
seconds | 定時時間,單位:秒(S) |
返回值 | 成功:如果呼叫此alarm()前,程序已經設定了鬧鐘時間,則返回上一個鬧鐘時間的剩餘時間,否則返回0 失敗:-1 |
注:可以設定忽略或者不捕獲此訊號,如果採用預設方式其動作是終止呼叫該alarm函式的程序。一個程序只能有一個鬧鐘時間,如果在呼叫alarm之前已設定過鬧鐘時間,則任何以前的鬧鐘時間都被新值所代替。需要注意的是,經過指定的秒數後,訊號由核心產生,由於程序排程的延遲,所以程序得到控制從而能夠處理該訊號還需要一些時間。
- int sigqueue(pid_t pid, int sig, const union sigval value)
功能 | 在佇列中向指定程序傳送一個訊號和資料 |
pid | 程序識別符號 |
sig | 訊號名稱 |
value | 是一個聯合體,表示訊號附帶的資料,附帶資料可以是一個整數也可以是一個指標,即通常所說4位元組值 |
返回值 | 成功:0 失敗:-1 |
- sighandler_t signal(int signum, sighandler_t handler)
功能 | 設定某一訊號的處理動作 | |
signum | 要設定的訊號名稱 | |
handler | 自定義函式 | 此函式必須在signal()被呼叫前申明,handler中為這個函式的名字。當接收到一個型別為signum的訊號時,就執行handler 所指定的函式。這個函式應有如下形式的定義:
|
SIG_IGN | 這個符號表示忽略該訊號,執行了相應的signal()呼叫後,程序會忽略型別為sig的訊號 | |
SIG_DFL | 這個符號表示恢復系統對訊號的預設處理 | |
返回值 | 成功:先前的訊號處理函式指標 失敗:-1 |
注:signum可以為除SIGKILL及SIGSTOP外的任何一 個特定有效的訊號
- int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact)
功能 | 為訊號重新自定義新的行為,並將原有的行為儲存在oldcat中 |
signum | 訊號名稱 |
act | 定義的訊號新行為 |
oldact | 儲存訊號原來的行為 |
返回值 | 成功:0 失敗:-1 |
sigaction結構體定義:
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
- sa_handler訊號處理程式 不接受額外資料
- sa_sigaction訊號處理程式 能接受額外資料,和sigqueue配合使用
- sa_mask 用來設定在處理該訊號時暫時將sa_mask 指定的訊號集擱置
- sa_restorer 此引數沒有使用
- sa_flags 用來設定訊號處理的其他相關操作,下列的數值可用
-
SA_RESETHAND:當呼叫訊號處理函式時,將訊號的處理函式重置為預設值SIG_DFL
SA_RESTART:如果訊號中斷了程序的某個系統呼叫,則系統自動啟動該系統呼叫
SA_NODEFER :一般情況下, 當訊號處理函式執行時,核心將阻塞該給定訊號。但是如果設定了 SA_NODEFER標記, 那麼在該訊號處理函式執行時,核心將不會阻塞該訊號
-
SA_SIGINFO:當SA_SIGINFO設定時與sa_sigaction 搭配出現,sa_sigaction函式的第一個引數與sa_handler一樣表示當前訊號的編號,第二個引數是一個siginfo_t 結構體,第三個引數一般不用
當使用sa_handler時sa_flags設定為0即可。
siginfo_t結構體定義:
siginfo_t {
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal */
void *si_ptr; /* POSIX.1b signal */
int si_overrun; /* Timer overrun count; POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault */
long si_band; /* Band event (was int in
glibc 2.3.2 and earlier) */
int si_fd; /* File descriptor */
short si_addr_lsb; /* Least significant bit of address
(since kernel 2.6.32) */
}
注:signal()可能具有一定的核心版本差異性(只是聽說,並沒有驗證), 根據自己對signal()和sigaction()的使用,sigaction()對訊號處理更加詳細和強大,所以掌握sigaction()是首選。
SIGCHLD:在一個程序終止或者停止時,將SIGCHLD訊號傳送給其父程序,按系統預設將忽略此訊號,如果父程序希望被告知其子系統的這種狀態,則應捕捉此訊號。
執行緒
標頭檔案:#include<pthread.h>
- int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg)
功能 | 建立執行緒(實際上就是確定呼叫該執行緒函式的入口點) |
thread |
指向執行緒id的指標 |
attr | 設定執行緒屬性,通常設定為NULL |
start_rtn | 執行緒執行函式的起始地址 |
arg | 執行函式的引數 |
返回值 | 成功:0 失敗:-1 |
注:因為pthread並非Linux系統的預設庫,而是POSIX執行緒庫。在Linux中將其作為一個庫來使用,因此加上 -lpthread(或-pthread)以顯式連結該庫。函式在執行錯誤時的錯誤資訊將作為返回值返回,並不修改系統全域性變數errno,當然也無法使用perror()列印錯誤資訊。
- pthread_t pthread_self(void)
功能 | 獲得執行緒自身的id |
返回值 | 執行緒id |
pthread_t的型別為unsigned long int,所以在列印的時候要使用%lu方式,否則顯示結果出問題
- int pthread_cancel(pthread_t thread)
功能 | 傳送終止訊號給thread執行緒 |
thread | 執行緒id |
返回值 | 成功:0 失敗:!0 |
注:傳送成功並不意味著thread會終止。若是在整個程式退出時,要終止各個執行緒,應該在成功傳送 CANCEL 指令後,使用 pthread_join 函式,等待指定的執行緒已經完全退出以後,再繼續執行。
- int pthread_join(pthread_t thread, void **retval)
函式釋義:pthread_join()函式,以阻塞的方式等待thread指定的執行緒結束。當函式返回時,被等待執行緒的資源被收回。如果執行緒已經結束,那麼該函式會立即返回。並且thread指定的執行緒必須是joinable的。
功能 | 傳送終止訊號給thread執行緒 |
thread | 執行緒id |
retval | 使用者定義的指標,用來儲存被等待執行緒的返回值 |
返回值 | 成功:0 失敗:錯誤碼 |
- int pthread_detach(pthread_t thread)
函式釋義:
建立一個執行緒預設的狀態是joinable, 如果一個執行緒結束執行但沒有被join,則它的狀態類似於程序中的Zombie Process,即還有一部分資源沒有被回收,所以建立執行緒者應該pthread_join來等待執行緒執行結束,並可得到執行緒的退出程式碼,回收其資源。
但是呼叫pthread_join(pthread_id)後,如果該執行緒沒有執行結束,呼叫者會被阻塞,在有些情況下我們並不希望如此,比如在Web伺服器中當主執行緒為每個新來的連結建立一個子執行緒進行處理的時候,主執行緒並不希望因為呼叫pthread_join而阻塞(因為還要繼續處理之後到來的連結),這時可以在子執行緒中加入程式碼pthread_detach(pthread_self)或者父執行緒呼叫pthread_detach(thread_id)(非阻塞,可立即返回)這將該子執行緒的狀態設定為detached,則該執行緒執行結束後會自動釋放所有資源。這裡需要注意的是,該執行緒的狀態為detached時,就不需要再使用pthread_join函式來等待執行緒的退出了,因為這時系統會自動地回收資源;否則pthread_join函式將會返回錯誤碼。
功能 | 分離執行緒 |
thread | 執行緒id |
返回值 | 成功:0 失敗:錯誤碼 |
注:線上程設定為joinable後,可以呼叫pthread_detach()使之成為detached。但是相反的操作則不可以。還
有,如果執行緒已經呼叫pthread_join()後,則再呼叫pthread_detach()則不會有任何效果
- void pthread_exit(void *retval)
功能 | 終止呼叫它的執行緒 |
retval | 返回某個物件的指標 |