1. exit用於結束正在運行的整個程序,它將參數返回給OS,把控制權交給操作系統;而return 是退出當前函數,返回函數值,把控制權交給調用函數。
2. exit是系統調用級別,它表示一個進程的結束;而return 是語言級別的,它表示調用堆棧的返回。
3. 在main函數結束時,會隱式地調用exit函數,所以一般程序執行到main()結尾時,則結束主進程。exit將刪除進程使用的內存空間,同時把錯誤信息返回給父進程。
4. void exit(int status); 一般status爲0,表示正常退出,非0表示非正常退出。
1、exit函數和return函數的主要區別是:
1)exit用於在程序運行的過程中隨時結束程序,其參數是返回給OS的。也可以這麼講:exit函數是退出應用程序,並將應用程序的一個狀態返回給OS,這個狀態標識了應用程序的一些運行信息。
main函數結束時也會隱式地調用exit函數,exit函數運行時首先會執行由atexit()函數登記的函數,然後會做一些自身的清理工作,同時刷新所有輸出流、關閉所有打開的流並且關閉通過標準I/O函數tmpfile()創建的臨時文件。
exit是系統調用級別的,它表示了一個進程的結束,它將刪除進程使用的內存空間,同時把錯誤信息返回父進程。通常情況:exit(0)表示程序正常, exit(1)和exit(-1)表示程序異常退出,exit(2)表示系統找不到指定的文件。在整個程序中,只要調用exit就結束。
2)return是語言級別的,它表示了調用堆棧的返回;return是返回函數值並退出函數,通常0爲正常退出,非0爲非正常退出,請注意,如果是在主函數main, 自然也就結束當前進程了(也就是說,在main()裏面,你可以用return n,也能夠直接用exit(n)來做),如果不是在main函數中,那就是退回上一層調用。在多個進程時,如果有時要檢測上個進程是否正常退出,就要用到上個進程的返回值。
2、進程環境與進程控制
exit(int n)其實就是直接退出程序,因爲默認的標準程序入口爲 int main(int argc, char** argv),返回值是int型的。一般在shell下面,運行一個程序,然後使用命令echo $?就能得到該程序的返回值,也就是退出值。
理論上exit可以返回小於256的任何整數,返回的不同數值主要是給調用者作不同處理的。
對於單獨的進程exit的返回值是返回給操作系統的,但如果是多進程,則是返回給父進程的。父進程裏面調用waitpid()等函數得到子進程退出的狀態,以便作不同處理。根據相應的返回值來讓調用者作出相應的處理。
總的說來,exit()就是當前進程把其控制權返回給調用該子程序的主程序, 括號裏的是返回值,告訴調用程序該程序的運行狀態。
1)進程的開始:
C程序是從main函數開始執行, 原型如下: int main(int argc, char *argv[]); 通常main的返回值是int型, 正確返回0。
2)進程終止:
C程序的終止分爲兩種: 正常終止和異常終止。正常終止分爲: return, exit, _exit, _Exit, pthreade_exit。異常中指分爲: abort, SIGNAL, 線程響應取消。
主要說一下正常終止的前4種, 即exit系列函數.
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
以上3個函數的區別是: exit()(或return 0)會調用終止處理程序和用戶空間的標準I/O清理程序(如fclose), _exit和_Exit不調用而直接由內核接管進行清理。因此, 在main函數中exit(0)等價於return 0.
3)atexit終止處理程序:
ISO C規定, 一個進程最多可登記32個終止處理函數, 這些函數由exit按登記相反的順序自動調用。如果同一函數登記多次, 也會被調用多次。
原型如下:
#include <stdlib.h>
int atexit(void (*func)(void));
其中參數是一個函數指針, 指向終止處理函數, 該函數無參無返回值。atexit函數本身成功調用後返回0。
以下面的程序爲例:
#include <stdlib.h>
static void myexit1()
{
printf("first exit handler\n");
}
static void myexit2()
{
printf("second exit handler\n");
}
int main()
{
atexit(my_exit2);
atexit(my_exit1);
atexit(my_exit1);
printf("main is done\n");
return 0;
}
運行結果:
$ ./a.out
main is done
first exit handler
first exit handler
second exit handler
注意上面的結果,可以發現這些函數由exit按登記相反的順序自動調用(先myexit1後myexit2)。如果同一函數登記多次, 也會被調用多次(如這裏的myexit1)。而這些處理函數都是在程序退出的時候利用atexit函數調用了這些處理函數。但是如果用_exit()退出程序,則它不關閉任何文件,不清除任何緩衝器、也不調用任何終止函數!
exit函數在頭文件stdlib.h中。
exit(0):正常運行程序並退出程序;
exit(1):非正常運行導致退出程序;
return():返回函數,若在main主函數中,則會退出函數並返回一值,可以寫爲return(0),或return 0。
詳細說:
1. return返回函數值,是關鍵字;exit是一個函數。
2. return是語言級別的,它表示了調用堆棧的返回;而exit是系統調用級別的,它表示了一個進程的結束。
3. return是函數的退出(返回);exit是進程的退出。
4. return是C語言提供的,exit是操作系統提供的(或者函數庫中給出的)。
5. return用於結束一個函數的執行,將函數的執行信息傳出個其他調用函數使用;exit函數是退出應用程序,刪除進程使用的內存空間,並將應用程序的一個狀態返回給OS,這個狀態標識了應用程序的一些運行信息,這個信息和機器和操作系統有關,一般是 0 爲正常退出,非0 爲非正常退出。
6. 非主函數中調用return和exit效果很明顯,但是在main函數中調用return和exit的現象就很模糊,多數情況下現象都是一致的。
下面是幾個例子:
1.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int
main( void )
{
pid_t pid;
int
count=0; pid=vfork();
if (pid==0)
{
printf ( "child: count=%d\n" ,count);
printf ( "child: getpid=%d\n" ,getpid());
count=1;
printf ( "child: count=%d\n" ,count);
// return 0;//會出現段錯誤
exit (0);
//ok }
else {
printf ( "\nfather: pid=%d\n" ,pid);
printf ( "father: count=%d\n" ,count);
}
return (0);
} |
運行結果
[root@localhost part1_linux]# gcc fork2.c
[root@localhost part1_linux]# ./a.out
child: count=0
child: getpid=9911
child: count=1
father: pid=9911
father: count=1 |
運行結果說明:vfrok時父、子進程共享數據段,fork時是進行拷貝。如果,vfork子進程中,使用return返回時,出現段錯誤,結果如下:
[root@localhost part1_linux]# gcc fork2.c
[root@localhost part1_linux]# ./a.out
child: count=0
child: getpid=10864
child: count=1
father: pid=10864
father: count=0
段錯誤 |
2. 爲什麼執行結果子進程打印出來 我的父親是id:1,與父進程id不同
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main() {
int
i=0; pid_t pid;
printf ( "還沒創建子進程\n" );
i++;
pid = fork();
if (pid==-1)
{
printf ( "fork error!\n" );
}
else
if (pid==0) {
i++;
printf ( "我是子進程,id%d\n" ,getpid());
printf ( "我的父親是id:%d\n" ,getppid());
printf ( "-----i=%d-----\n" ,i);
}
else {
i++;
printf ( "我是父進程,id:%d\n" ,getpid());
printf ( "-----i=%d-----\n" ,i);
}
exit (0);
} |
3. 用vfork()創建子進程,執行後程序一直不斷地重複運行,不斷創建子進程,結尾用exit(0)代替return(0)後問題就能解決
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main() {
int
i=0; pid_t pid;
printf ( "還沒創建子進程\n" );
i++;
pid = vfork();
if (pid==-1)
{
printf ( "fork error!\n" );
}
else
if (pid==0) {
i++;
printf ( "我是子進程,id%d\n" ,getpid());
printf ( "我的父親是id:%d\n" ,getppid());
printf ( "-----i=%d-----\n" ,i);
}
else {
i++;
printf ( "我是父進程,id:%d\n" ,getpid());
printf ( "-----i=%d-----\n" ,i);
}
return (0); |