久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

如何編寫一個可靠的linux守護進程

 SamBookshelf 2014-02-25
    linux服務端程序都需要提供7 * 24不間斷的服務,,如何保證工作進程一直不退出或者不被kill掉,,常見的方法就是啟動一個守護進程來檢測工作進程的狀態(tài),如果發(fā)現(xiàn)工作進程退出,,就再fork一個出來,。一般的實現(xiàn)見下面一段代碼:
C代碼  收藏代碼
  1. // 守護進程(父進程)  
  2. int status;  
  3. for ( ; ; )  {  
  4.     if ( 0 == ( pid = fork()) ) {  
  5.         // 工作進程(子進程)  
  6.         run();  
  7.     }  
  8.     waitpid(-1, &status, 0);  
  9.     if (WIFEXITED(status))  
  10.             if (WEXITSTATUS(status) == 0)  
  11.                 exit(0);  
  12.         if (WIFSIGNALED(status)) {  
  13.             switch (WTERMSIG(status)) {  
  14.             case SIGKILL:  
  15.                 exit(0);  
  16.                 break;  
  17.             case SIGINT:  
  18.             case SIGTERM:  
  19.                 exit(1);  
  20.             default:  
  21.                 break;  
  22.             }  
  23.         }  
  24. }  
    守護進程fork出工作進程之后,就阻塞在waitpid系統(tǒng)調(diào)用,,等待工作進程的退出,,waitpid返回之后,根據(jù)status選擇繼續(xù)fork工作進程還是退出守護進程,。status為int型變量,,但只用到了低16位(見struct wait),0-6位表示使子進程退出的信號(可以通過 $kill -l 查看信號的值),,8-15位表示子進程退出時的返回碼(exit或者return的值),。
C代碼  收藏代碼
  1. struct wait{  
  2. # if    __BYTE_ORDER == __LITTLE_ENDIAN  
  3.     unsigned int __w_termsig:7; /* Terminating signal.  */  
  4.     unsigned int __w_coredump:1; /* Set if dumped core.  */  
  5.     unsigned int __w_retcode:8; /* Return code if exited normally.  */  
  6.     unsigned int:16;  
  7. # endif             /* Little endian.  */  
  8. };  
     判斷status的狀態(tài)可以通過下面的宏完成:
C代碼  收藏代碼
  1. WIFEXITED(status)               //子進程調(diào)用exit()或者從main return退出時為true,;  
  2. WEXITSTATUS(status)        //在WIFEXITED為true時,表示exit()或return的返回碼,;  
  3. WIFSIGNALED(status)        //子進程被信號終止時為true,;  
  4. WTERMSIG(status)            //在WIFSIGNALED為true時,表示終止子進程信號的值,;  
    宏的定義如下:
C代碼  收藏代碼
  1. /* If WIFEXITED(STATUS), the low-order 8 bits of the status.  */  
  2. #define __WEXITSTATUS(status)   (((status) & 0xff00) >> 8)  
  3. /* If WIFSIGNALED(STATUS), the terminating signal.  */  
  4. #define __WTERMSIG(status)  ((status) & 0x7f)  
  5. /* Nonzero if STATUS indicates normal termination.  */  
  6. #define __WIFEXITED(status) (__WTERMSIG(status) == 0)  
  7. /* Nonzero if STATUS indicates termination by a signal.  */  
  8. #define __WIFSIGNALED(status) \  
  9.   (((signed char) (((status) & 0x7f) + 1) >> 1) > 0)  
    所以根據(jù)waitpid返回的status,,守護進程可以清楚地知道工作進程的死因,但上面的程序有兩個問題:
    1. 對SIGKILL, SIGINT, SIGTERM信號,,守護進程直接退出了,,沒有fork工作進程出來;
    2. 守護進程被kill掉了,,工作進程就只能裸奔了,。
    對于第一個問題:SIGKILL有可能是人為($kill -9 pid)發(fā)出的,也有可能是工作進程占用內(nèi)存過多,,被OOM掉了(關(guān)于OOM參見這里),,都不是我們想要的結(jié)果,所以工作進程被SIGKILL掉,,守護進程一定要將其重啟,。SIGINT是 CTRL+C 發(fā)出的(非daemon模式下),SIGTERM是 $killall servicename(或者 $kill pid)發(fā)出的,,這兩個信號都是在結(jié)束進程的時候用到,,這個時候工作進程應該捕獲被處理這兩個信號,正常地退出(return 0;),。而守護進程只有在工作進程正常退出的情況下才完成自己的使命,,否則(工作進程被其他信號結(jié)束掉,如SIGABRT, SIGKILL, SIGSEGV)重啟工作進程,。所以守護進程和工作進程的實現(xiàn)應該是下面的代碼邏輯:
C代碼  收藏代碼
  1. // 守護進程(父進程)  
  2. int status;  
  3. for ( ; ; )  {  
  4.     if ( 0 == ( pid = fork()) ) {  
  5.         // 工作進程(子進程)  
  6.         run();  
  7.         //信號處理函數(shù)signal_handler  
  8.         if (sig == SIGTERM || sig == SIGINT) {  
  9.            destroy();  
  10.            return 0;  
  11.         }  
  12.     }  
  13.     waitpid(-1, &status, 0);  
  14.     if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)) exit(0);  
  15. }  
     對于第二個問題:守護進程的監(jiān)控可以用daemontools工具集中的supervise來監(jiān)控,,也可以自己實現(xiàn),但是不能只是通過另外一個應用程序去做,,因為做守護的進程自身也需要被守護,,如此循環(huán)解決不了問題。這個時候就要借助于linux系統(tǒng)的init進程了,,因為init進程是不能被信號kill掉的(強大到無視SIGKILL),。
C代碼  收藏代碼
  1. The  only  signals  that can be sent task number one, the init process, are those for which init has explicitly installed signal handlers.  This is done to assure the system is not brought down accidentally.  
    所以讓init進程來守護我們的應用程序是最可靠的,看看supervise的作法:
    在/etc/inittab中添加如下一行:
C代碼  收藏代碼
  1. SV1:23:respawn:/usr/local/bin/svscanboot  
    每行用“:”分隔開為4個部分:
        id - 該行的標識,,自定義的名稱SV1。
        runlevels - 該行為應該發(fā)生的運行級的列表,,這里在level 2和level 3下運行,。
        action - 應發(fā)生的行為,respawn表示init應該監(jiān)視這個進程,即使其結(jié)束后也應該被重新啟動,。
        process - 應由init啟動的程序的路徑,。
    修改完成后,可以通過$kill -HUP 1 來立刻生效,。
    解決了上面兩個問題,,守護進程和工作進程提供7 * 24小時的運行才是有保證的。Have fun!    

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多