<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        atexit函數和exit函數的理解

        作者:huqin   來源:本站原創   點擊數:  更新時間:2014年03月13日   【字體:

          工作找完了,老板逼著寫各種亂七八糟的本子,偷著寫點自己的理解,就當是對自己興趣愛好的補償吧。

           按照ISO C的規定,一個進程可以登記多達32個函數,這些函數將由exit自動調用,通常這32個函數被稱為終止處理程序,并調用atexit函數來登記這些函數。

           我們通常認為C語言的起始函數是main函數,實質上一個程序的啟動函數并不一定是main函數,這個可以采用鏈接器來設置,但是gcc中默認main就是C語言的入口函數,在main函數啟動之前,內核會調用一個特殊的啟動例程,這個啟動例程從內核中取得命令行參數值和環境變量值,為調用main函數做好準備,因此對應程序而言main函數并不是起始,但是對應C 語言而言,main函數就是入口地址,其他的鏈接器幫助我們完成,實際上mian函數的執行是使用了exec函數,這是一個函數族,這也是內核執行一個程序的唯一方法,這在進程控制部分將進行分析。
           
           記得在面試題中有一道關于在main函數退出之后,是否還可以執行程序的問題,這時候就要使用到前面提到的atexit函數。

             #include<stdlib.h>
             int atexit(void(*func)(void));

            其中,atexit的參數是一個函數地址,當調用此函數時無須傳遞任何參數,該函數也不能返回值,atexit函數稱為終止處理程序注冊程序,注冊完成以后,當函數終止是exit()函數會主動的調用前面注冊的各個函數,但是exit函數調用這些函數的順序于這些函數登記的順序是相反的,我認為這實質上是參數壓棧造成的,參數由于壓棧順序而先入后出。同時如果一個函數被多次登記,那么該函數也將多次的執行。
          
           我們知道exit是在main函數調用結束以后調用,因此這些函數的執行肯定在main函數之后,這也是上面面試題的解決方法。即采用atexit函數登記相關的執行函數即可。

           在exit函數的介紹中我們知道,exit()和_exit()以及_Exit()函數的本質區別是是否立即進入內核,_exit()以及_Exit()函數都是在調用后立即進入內核,而不會執行一些清理處理,但是exit()則會執行一些清理處理,這也是為什么會存在atexit()函數的原因,因為exit()函數需要執行清理處理,需要執行一系列的操作,這些終止處理函數實際上就是完成各種所謂的清除操作的實際執行體。atexit函數的定義也給了程序員一種運用exit執行一些清除操作的方法,比如有一些程序需要額外的操作,具體的清除操作可以采用這種方法對特殊操作進行清除等。

            #include<stdio.h>
            #include<stdlib.h>

            void func1(void)
            {
                    printf("in func1\n");
            }

            void func2(void)
            {
                    printf("in func2\n");
            }

            void func3(void)
            {
                    printf("in func3\n");
            }

            int main()
            {
                    atexit(func3);
                    atexit(func2);
                    atexit(func1);

                    printf("In main\n");

                    return 0;
            }

           具體的執行結果如下所示:

            [gong@Gong-Computer APUE]$ ./atexit
            In main
            in func1
            in func2
            in func3

           根據exit的執行過此可知,exit首先會調用各個終止處理程序,然后按需多次調用fclose(),關閉所有打開流,也就是說exit函數會執行一個標準I/O庫的清理關閉操作:對所有打開的流調用fclose(),這樣就會造成所有緩沖的輸出數據都被沖洗即寫入文件中。

           內核使程序執行的唯一方法是調用一個exec函數,進程自愿終止哦的唯一方法是顯式或者隱式調用(通過exit函數)_exit()或者_Exit()函數。因此exit函數中實質是對_exit()或者_Exit()函數的封裝。exit會先執行自定義的終止處理函數,然后執行I/O庫函數清理函數fclose(),這也是為什么可以在終止處理函數中可以繼續運用printf之類函數的原因,因為I/O庫函數的流對象還沒有被清除,當然可以繼續運用。執行完了所有的fclose()以后,可以執行真正意義上的終止函數_exit()或者_Exit()函數。

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮