perror:
#include<stdio.h>
#include<stdlib.h>
void perror(const char *s); perror ("open_port");
perror ( )用 來 將 上 一 個 函 數 發 生 錯 誤 的 原 因 輸 出 到 標 准 錯誤 (stderr) 。參數 s 所指的字符串會先打印出,後面再加上錯誤原因字符串。此錯誤原因依照全局變量error 的值來決定要輸出的字符串。
在庫函數中有個error變量,每個error值對應著以字符串表示的錯誤類型。當你調用"某些"函數出錯時,該函數已經重新設置了error的值。perror函數只是將你輸入的一些信息和現在的error所對應的錯誤一起輸出。
exit:(#include <stdlib.h>)
在C語言的main函數中我們通常使用return (0);這樣的方式返回一個值。但這是限定在非void情況下的,也就是非void main()這樣的形式。 exit()通常是用在子程序中用來終結程序用的,使用後程序自動結束,跳出操作系統。
exit(0) 表示程序正常退出,
exit(1)/exit(-1)表示程序異常退出。
exit() 結束當前進程/當前程序/,在整個程序中,只要調用 exit ,就結束。
但在如果把exit用在main內的時候無論main是否定義成void返回的值都是有效的,並且exit不需要考慮類型,exit(1)等價於return (1) 。
例如:
#include<stdlib.h>
int main()
{
exit (1);//等價於return (1);
}
exit()是一個函數 ,結束一個進程,它將刪除進程使用的內存空間,同時把錯誤信息返回父進程,在父進程中wait系統調用將接受到此返回信息。
進程就好比人一樣有其生命,我們通過fork()函數來創建一個進程,那麼我們又是如何來中止進程呢。
進程退出
1.在Linux中任何讓一個進程退出
進程退出表示進程即將結束。在Linux中進程退出分為了正常退出和異常退出兩種。
1>正常退出
a. 在main()函數中執行return 。
b.調用exit()函數 #include <stdlib.h> void exit(int status)
c.調用_exit()函數 #include <unistd.h> void _exit(int status)
status 是一個整型的參數,可以利用這個參數傳遞進程結束時的狀態。一般來說,
0 表示正常結束;其他的數值表示出現了錯誤,進程非正常結束。
在實際編程時,可以用 wait 系統調用接收子進程的返回值,從而針對不同的情況
進行不同的處理
2>異常退出
a.調用about函數
b.進程收到某個信號,而該信號使程序終止。
Tiger-John說明:
不管 是那種 退出方式,系統最終都會執行內核中的同一代碼。這段代碼用來關閉進程所用已打開的文件描述符,釋放它所占用的內存和其他資源。
3>比較以上幾種退出方式的不同點
(1)exit和return 的區別:
a.exit是一個函數,有參數。exit執行完後把控制權交給系統
b.return是函數執行完後的返回。renturn執行完後把控制權交給調用函數。
(2)exit和abort的區別:
a.exit是正常終止進程
b.about是異常終止。
現在我們重點了解exit()和_exit()函數
2.exit()和_exit()的學習
1>exit和_exit函數都是用來終止進程的。
當程序執行到exit或_exit時,系統無條件的停止剩下所有操作,清除包括PCB在內的各種數據結構,並終止本進程的運行。
2>exit在頭文件stdlib.h中聲明,而_exit()聲明在頭文件unistd.h中聲明。 exit中的參數exit_code為0代表進程正常終止,若為其他值表示程序執行過程中有錯誤發生。
3>exit()和_exit()的區別:
a._exit()執行後立即返回給內核,而exit()要先執行一些清除操作,然後將控制權交給內核。
b. 調用_exit函數時,其會關閉進程所有的文件描述符,清理內存以及其他一些內核清理函數,但不會刷新流(stdin, stdout, stderr ...). exit函數是在_exit函數之上的一個封裝,其會調用_exit,並在調用之前先刷新流。
Tiger-John說明:
exit()函數與_exit()函數最大區別就在於exit()函數在調用exit系統之前要檢查文件的打開情況,把文件緩沖區的內容寫回文件。 由於Linux的標准函數庫中,有一種被稱作“緩沖I/O”的操作,其特征就是對應每一個打開的文件,在內存中都有一片緩沖區。每次讀文件時,會連續的讀 出若干條記錄,這樣在下次讀文件時就可以直接從內存的緩沖區讀取;同樣,每次寫文件的時候也僅僅是寫入內存的緩沖區,等滿足了一定的條件(如達到了一定數 量或遇到特定字符等),再將緩沖區中的內容一次性寫入文件。這種技術大大增加了文件讀寫的速度,但也給編程代來了一點兒麻煩。比如有一些數據,認為已經寫 入了文件,實際上因為沒有滿足特定的條件,它們還只是保存在緩沖區內,這時用_exit()函數直接將進程關閉,緩沖區的數據就會丟失。因此,要想保證數 據的完整性,就一定要使用exit()函數。
c . 通過一個函數實例來看看它們之間的區別:
函數實例1 : exit.c
1 #include<stdio.h>
2 #include<stdlib.h>
3
4 int main()
5 {
6 printf("using exit----\n");
7 printf("This is the content in buffer\n");
8 exit(0);
9 }
函數經過調試後
$ gcc exit.c -o exit
$ ./exit
執行結果為:
using exit----
This is the content in buffer
函數實例2:_exit.c
1 #include<stdio.h>
2 #include<unistd.h>
3
4 int main(void)
5 {
6 printf("using _exit--\n");
7 printf("This is the content in buffer");
8 _exit(0);
9 }
函數經過調試後
$ gcc _exit.c -o _exit
$ ./_exit
執行結果為 :
using _exit--
Tiger-John說明:
1.printf函數就是使用緩沖I/O的方式,該函數在遇到“\n”換行符時自動的從緩沖區中將記錄讀出。所以exit()將緩沖區的數據寫完後才退出,而_exit()函數直接退出。
2.大家也可以把函數實例2中的printf("This is the content in buffer");改為printf("This is the content in buffer\n")(即在printf中最後加一個\n看運行結果是什麼,為什麼會產生這樣的結果呢?)
小知識
在一個進程調用了 exit 之後,該進程並不馬上就完全消失,而是留下一個稱為僵屍進程
(Zombie)的數據結構。僵屍進程是一種非常特殊的進程,它幾乎已經放棄了所有內存空間,
沒有任何可執行代碼,也不能被調度,僅僅在進程列表中保留一個位置,記載該進程的退出
狀態等信息供其他進程收集,除此之外,僵屍進程不再占有任何內存空間。
wait
wait 函數是用於使父進程(也就是調用 wait 的進程)阻塞,直到一個子進程結束或者該進程接到了一個指定的信號為止。
如果該父進程沒有子進程或者他的子進程已經結束, wait則就會立即返回。
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status)
waitpid
waitpid 的作用和 wait 一樣,但它並不一定要等待第一個終止的子進程,它還有若干選項,如可提供一個非阻塞版本的 wait 功能,也能支持作業控制。實際上 wait 函數只是 waitpid 函數的一個特例,在 Linux 內部實現 wait 函數時直接調用的就是 waitpid 函數。
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options)