<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > atexit函數(shù)和exit函數(shù)的理解

          atexit函數(shù)和exit函數(shù)的理解

          作者: 時間:2016-12-01 來源:網(wǎng)絡 收藏
          工作找完了,老板逼著寫各種亂七八糟的本子,偷著寫點自己的理解,就當是對自己興趣愛好的補償吧。

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

          本文引用地址:http://www.ex-cimer.com/article/201612/324502.htm

          我們通常認為C語言的起始函數(shù)是main函數(shù),實質(zhì)上一個程序的啟動函數(shù)并不一定是main函數(shù),這個可以采用鏈接器來設置,但是gcc中默認main就是C語言的入口函數(shù),在main函數(shù)啟動之前,內(nèi)核會調(diào)用一個特殊的啟動例程,這個啟動例程從內(nèi)核中取得命令行參數(shù)值和環(huán)境變量值,為調(diào)用main函數(shù)做好準備,因此對應程序而言main函數(shù)并不是起始,但是對應C 語言而言,main函數(shù)就是入口地址,其他的鏈接器幫助我們完成,實際上mian函數(shù)的執(zhí)行是使用了exec函數(shù),這是一個函數(shù)族,這也是內(nèi)核執(zhí)行一個程序的唯一方法,這在進程控制部分將進行分析。

          記得在面試題中有一道關(guān)于在main函數(shù)退出之后,是否還可以執(zhí)行程序的問題,這時候就要使用到前面提到的atexit函數(shù)。

          #include
          int atexit(void(*func)(void));

          其中,atexit的參數(shù)是一個函數(shù)地址,當調(diào)用此函數(shù)時無須傳遞任何參數(shù),該函數(shù)也不能返回值,atexit函數(shù)稱為終止處理程序注冊程序,注冊完成以后,當函數(shù)終止是exit()函數(shù)會主動的調(diào)用前面注冊的各個函數(shù),但是exit函數(shù)調(diào)用這些函數(shù)的順序于這些函數(shù)登記的順序是相反的,我認為這實質(zhì)上是參數(shù)壓棧造成的,參數(shù)由于壓棧順序而先入后出。同時如果一個函數(shù)被多次登記,那么該函數(shù)也將多次的執(zhí)行。

          我們知道exit是在main函數(shù)調(diào)用結(jié)束以后調(diào)用,因此這些函數(shù)的執(zhí)行肯定在main函數(shù)之后,這也是上面面試題的解決方法。即采用atexit函數(shù)登記相關(guān)的執(zhí)行函數(shù)即可。

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

          #include
          #include

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

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

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

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

          printf("In main");

          return 0;
          }

          具體的執(zhí)行結(jié)果如下所示:

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

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

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



          關(guān)鍵詞: atexit函數(shù)exit函

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();