成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

使用PHP腳本來寫Daemon程序

開發 后端 前端
為什么一定要使用daemon進程呢?Linux中每一個系統與用戶進行交流的界面稱為終端(terminal),每一個從此終端開始運行的進程都會依附于這個終端,這個終端就稱為這些進程的控制終端(Controlling terminal),當控制終端被關閉時,相應的進程都會被自動關閉。

這又是一個有趣的概念,daemon在英語中是"精靈"的意思,就像我們經常在迪斯尼動畫里見到的那些,有些會飛,有些不會,經常圍著動畫片的主人公轉來轉去,啰里啰唆地提一些忠告,時不時倒霉地撞在柱子上,有時候還會想出一些小小的花招,把主人公從敵人手中救出來,正因如此,daemon有時也被譯作"守護神"。所以,daemon進程在國內也有兩種譯法,有些人譯作"精靈進程",有些人譯作"守護進程",這兩種稱呼的出現頻率都很高。

與真正的daemon相似,daemon進程也習慣于把自己隱藏在人們的視線之外,默默為系統做出貢獻,有時人們也把它們稱作"后臺服務進程"。daemon進程的壽命很長,一般來說,從它們一被執行開始,直到整個系統關閉,它們才會退出。幾乎所有的服務器程序,包括我們熟知的Apache和wu-FTP,都用daemon進程的形式實現。很多Linux下常見的命令如inetd和ftpd,末尾的字母d就是指daemon。

為什么一定要使用daemon進程呢?Linux中每一個系統與用戶進行交流的界面稱為終端(terminal),每一個從此終端開始運行的進程都會依附于這個終端,這個終端就稱為這些進程的控制終端(Controlling terminal),當控制終端被關閉時,相應的進程都會被自動關閉。關于這點,讀者可以用X-Window中的XTerm試驗一下,(每一個XTerm就是一個打開的終端,)我們可以通過鍵入命令啟動應用程序,比如:$netscape 然后我們關閉XTerm窗口,剛剛啟動的netscape窗口也會隨之一同突然蒸發。但是daemon進程卻能夠突破這種限制,即使對應的終端關閉,它也能在系統中長久地存在下去,如果我們想讓某個進程長命百歲,不因為用戶或終端或其他的變化而受到影響,就必須把這個進程變成一個daemon進程。

1. Daemon進程的編程規則

如果想把自己的進程變成daemon進程,我們必須嚴格按照以下步驟進行:

1、調用fork產生一個子進程,同時父進程退出。我們所有后續工作都在子進程中完成。這樣做我們可以:

1.1 如果我們是從命令行執行的該程序,這可以造成程序執行完畢的假象,shell會回去等待下一條命令;

1.2 剛剛通過fork產生的新進程一定不會是一個進程組的組長,這為第2步的執行提供了前提保障。

這樣做還會出現一種很有趣的現象:由于父進程已經先于子進程退出,會造成子進程沒有父進程,變成一個孤兒進程(orphan)。每當系統發現一個孤兒進程,就會自動由1號進程收養它,這樣,原先的子進程就會變成1號進程的子進程。

2、調用setsid系統調用。

這是整個過程中最重要的一步。setsid的介紹見附錄2,它的作用是創建一個新的會話(session),并自任該會話的組長(session leader)。如果調用進程是一個進程組的組長,調用就會失敗,但這已經在第1步得到了保證。調用setsid有3個作用:

2.1 讓進程擺脫原會話的控制;

2.2 讓進程擺脫原進程組的控制;

2.3 讓進程擺脫原控制終端的控制;

總之,就是讓調用進程完全獨立出來,脫離所有其他進程的控制。

3、把當前工作目錄切換到根目錄。

如果我們是在一個臨時加載的文件系統上執行這個進程的,比如:/mnt/floppy/,該進程的當前工作目錄就會是/mnt/floppy/。在整個進程運行期間該文件系統都無法被卸下(umount),而無論我們是否在使用這個文件系統,這會給我們帶來很多不便。解決的方法是使用chdir系統調用把當前工作目錄變為根目錄,應該不會有人想把根目錄卸下吧。

關于chdir的用法,參見附錄1。

當然,在這一步里,如果有特殊的需要,我們也可以把當前工作目錄換成其他的路徑,比如/tmp。

4、將文件權限掩碼設為0。

這需要調用系統調用umask,參見附錄3。每個進程都會從父進程那里繼承一個文件權限掩碼,當創建新文件時,這個掩碼被用于設定文件的默認訪問權限,屏蔽掉某些權限,如一般用戶的寫權限。當另一個進程用exec調用我們編寫的daemon程序時,由于我們不知道那個進程的文件權限掩碼是什么,這樣在我們創建新文件時,就會帶來一些麻煩。所以,我們應該重新設置文件權限掩碼,我們可以設成任何我們想要的值,但一般情況下,大家都把它設為0,這樣,它就不會屏蔽用戶的任何操作。

如果你的應用程序根本就不涉及創建新文件或是文件訪問權限的設定,你也完全可以把文件權限掩碼一腳踢開,跳過這一步。

5、關閉所有不需要的文件。

同文件權限掩碼一樣,我們的新進程會從父進程那里繼承一些已經打開了的文件。這些被打開的文件可能永遠不被我們的daemon進程讀或寫,但它們一樣消耗系統資源,而且可能導致所在的文件系統無法卸下。需要指出的是,文件描述符為0、1和2的三個文件(文件描述符的概念將在下一章介紹),也就是我們常說的輸入、輸出和報錯這三個文件也需要被關閉。很可能不少讀者會對此感到奇怪,難道我們不需要輸入輸出嗎?但事實是,在上面的第2步后,我們的daemon進程已經與所屬的控制終端失去了聯系,我們從終端輸入的字符不可能達到daemon進程,daemon進程用常規的方法(如printf)輸出的字符也不可能在我們的終端上顯示出來。所以這三個文件已經失去了存在的價值,也應該被關閉。

使用PHP編寫Gearman的Worker守護進程

在我之前的文章中,介紹過Gearman的使用。在我的項目中,我使用了PHP來編寫一直運行的Worker。如果按照Gearman官方推薦的例子,只是簡單的一個循環來等待任務,會有一些問題,包括:1、當代碼進行過修改之后,如何讓代碼的修改生效;2、重啟Worker的時候,如何保證當前的任務處理完成才重啟。

針對這個問題,我考慮了以下的解決方法:

1、每次修改完代碼后,Worker需要手工重啟(先殺死然后啟動)。這個只能解決重新加載配置文件的問題。

2、在Worker中設置,單次任務循環完成后,就對Worker進行重啟。這個方案的問題在于消耗比較大。

3、在Worker中添加一個退出函數,如果需要Worker退出的時候,在Client端發送一個優先級比較高的退出調用。這個需要客戶端配合,在使用后臺類任務時,不太適合。

4、在Worker中檢查文件是否發生變化,如果發生了變化,退出并重啟自身。

5、為Worker編寫信號控制,接受重啟指令,類似于 http restart graceful 指令。

***,結合4和5兩種方法,可以實現這樣一個Daemon,如果配置文件發生了變化,他就會自動重啟;如果接受到了用戶的 kill -1 pid 信號,也會重新啟動。

代碼如下:

  1. <?php 
  2.  
  3. declare( ticks = 1 );  
  4. // This case will check the config file regularly, if the config file changed, it will restart it self  
  5. // If you want to restart the daemon gracefully, give it a HUP signal  
  6. // by shiqiang<cocowool@gmail.com> at 2011-12-04  
  7.  
  8. $init_md5 = md5_file( 'config.php');  
  9.  
  10. // register signal handler  
  11. pcntl_signal( SIGALRM, "signal_handler", true );  
  12. pcntl_signal( SIGHUP, 'signal_handler', TRUE );  
  13.  
  14. $job_flag = FALSE;    //Job status flag, to justify if the job has been finished  
  15. $signal_flag = FALSE;    //Signal status flag, to justify whether we received the kill -1 signal  
  16.  
  17. while( 1 ){  
  18.     $job_flag = FALSE;    //Job status flag  
  19.     print "Worker start running ... \n";  
  20.     sleep(5);  
  21.     print "Worker's task done ... \n";  
  22.     $flag = TRUE;    //Job status flag  
  23.     AutoStart( $signal_flag );  
  24. }  
  25.  
  26. function signal_handler( $signal ) {  
  27.     global $job_flag;  
  28.     global $signal_flag;  
  29.  
  30.     switch( $signal ){  
  31.         case SIGQUIT:  
  32.             print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGQUIT - No : $signal \n";  
  33.             exit(0);  
  34.             break;  
  35.         case SIGSTOP:  
  36.             print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGSTOP - No : $signal \n";  
  37.             break;  
  38.         case SIGHUP:  
  39.             print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGHUP - No : $signal \n";  
  40.             if( $flag === TRUE ){  
  41.                 AutoStart( TRUE );  
  42.             }else{  
  43.                 $signal_flag = TRUE;  
  44.             }  
  45.             break;  
  46.         case SIGALRM:  
  47.             print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGALRM - No : $signal \n";  
  48.             //pcntl_exec( '/bin/ls' );  
  49.             pcntl_alarm( 5 );  
  50.             break;  
  51.         default:  
  52.             break;  
  53.     }  
  54. }  
  55.  
  56. function AutoStart( $signal = FALSE, $filename = 'config.php' ){  
  57.     global $init_md5;  
  58.  
  59.     if( $signal || md5_file( $filename ) != $init_md5 ){  
  60.         print "The config file has been changed, we are going to restart. \n";  
  61.         $pid = pcntl_fork();  
  62.         if( $pid == -1 ){  
  63.             print "Fork error \n";  
  64.         }else if( $pid > 0 ){  
  65.             print "Parent exit \n";  
  66.             exit(0);  
  67.         }else{  
  68.             $init_md5 = md5_file( $filename );  
  69.             print "Child continue to run \n";  
  70.         }  
  71.     }  

原文:http://www.cnblogs.com/cocowool/archive/2011/12/04/2275497.html

【編輯推薦】

  1. PHP開發組首位中國成員及他的Yaf
  2. 大話PHP之性能
  3. 如果PHP是用英式英語編寫的
  4. PHP集成開發工具PHPStorm 3.0發布
  5. 手把手教你在Ubuntu上安裝Apache、MySql和PHP

 

責任編輯:陳貽新 來源: 小狼的世界
相關推薦

2015-08-10 14:42:40

Explain SheShell 命令

2009-11-18 13:52:30

PHP shell腳本

2021-05-17 15:08:27

PythonWindows背景編程語言

2020-06-16 08:44:23

Shell服務器

2019-05-20 16:21:51

LinuxShell監控磁盤

2016-03-28 10:00:09

Swift命令程序

2011-07-12 17:11:13

PHPSHELL

2009-03-23 13:08:07

PHP擴展PHPJavascript

2011-09-08 14:25:31

2012-11-29 14:44:07

2011-06-22 10:48:35

PHP

2011-11-30 21:56:31

ibmdwXPathPHP

2009-06-15 10:21:07

基于JBossMBean

2009-05-27 14:31:53

NetBeansEclipsPHP

2018-09-19 08:50:45

PySimpleGUIGUIPython

2010-02-26 13:03:31

Python腳本語言

2009-11-30 16:24:24

PHP腳本

2022-10-09 14:50:44

Python腳本

2018-04-22 00:04:04

PHP C 代碼數據

2011-08-30 16:31:23

UbuntuXdebug
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一区二区不卡在线观看 | 午夜视频网站 | www在线视频 | 99成人在线视频 | 91传媒在线观看 | 在线视频日韩精品 | 日韩一区和二区 | 中文字幕高清 | 成人一区二区电影 | 99久久久国产精品 | 嫩草视频入口 | 亚洲永久 | 日韩亚洲一区二区 | 91麻豆精品国产91久久久更新资源速度超快 | 99久久99| 天天射视频 | 久久久日韩精品一区二区三区 | 国产欧美日韩一区二区三区在线观看 | 黄色香蕉视频在线观看 | 亚洲一区中文字幕在线观看 | 日韩一区在线观看视频 | 欧美精品在线免费观看 | 久夜精品 | 色欧美日韩| 日本精品一区二区三区四区 | 久久亚洲二区 | 欧美电影网 | 日韩一区二区在线播放 | 精品一区二区三区在线视频 | 可以免费看的毛片 | 亚洲欧美一区二区在线观看 | 午夜伦理影院 | 高清久久| 国产精品一卡二卡三卡 | 请别相信他免费喜剧电影在线观看 | 综合在线视频 | 欧美日韩在线高清 | 秋霞电影院午夜伦 | 欧美日韩国产精品一区 | 香蕉久久网 | japanhdxxxx裸体 |