php萬字碼出完美守護(hù)進(jìn)程詳解_第1頁
php萬字碼出完美守護(hù)進(jìn)程詳解_第2頁
php萬字碼出完美守護(hù)進(jìn)程詳解_第3頁
php萬字碼出完美守護(hù)進(jìn)程詳解_第4頁
php萬字碼出完美守護(hù)進(jìn)程詳解_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第php萬字碼出完美守護(hù)進(jìn)程詳解目錄前事提要基本概念基本特點(diǎn)創(chuàng)建守護(hù)進(jìn)程要求

前事提要

上期我們詳細(xì)學(xué)習(xí)了會話的概念以及用法,會話,進(jìn)程組,終端的理解對本篇講述的守護(hù)進(jìn)程極其重要,如還不理解相關(guān)概念建議翻看我往期關(guān)于會話,進(jìn)程組,終端文章。

基本概念

守護(hù)進(jìn)程(DaemonProcess),也就是通常說的Daemon進(jìn)程(精靈進(jìn)程),是Linux中的后臺服務(wù)進(jìn)程。通常獨(dú)立于控制終端并且周期性地執(zhí)行某種任務(wù)或等待處理某些發(fā)生的事件。并且不跟任何的控制終端關(guān)聯(lián),如果想讓某個(gè)進(jìn)程不因?yàn)橛脩艋蛑袛嗷蚱渌兓绊懀敲淳捅仨毎堰@個(gè)進(jìn)程變成一個(gè)守護(hù)進(jìn)程。

常見的守護(hù)進(jìn)程包括系統(tǒng)日志進(jìn)程syslogd、web服務(wù)器httpd、任務(wù)規(guī)劃守護(hù)進(jìn)程crond,數(shù)據(jù)庫服務(wù)器mysqld等。一般采用以d結(jié)尾的名字。

查看系統(tǒng)守護(hù)進(jìn)程命令ps-efj

基本特點(diǎn)

生存周期長[非必須],一般操作系統(tǒng)啟動的時(shí)候就啟動,關(guān)閉的時(shí)候關(guān)閉。

守護(hù)進(jìn)程和終端無關(guān)聯(lián),也就是他們沒有控制終端,所以當(dāng)控制終端退出,也不會導(dǎo)致守護(hù)進(jìn)程退出。

守護(hù)進(jìn)程是在后臺運(yùn)行,不會占著終端,終端可以執(zhí)行其他命令

守護(hù)進(jìn)程的父進(jìn)程是1號進(jìn)程,也就是init進(jìn)程;

在Linux中,大概有三種方式實(shí)現(xiàn)腳本后臺化:

1.在命令后添加一個(gè)符號,比如phptask.php.這個(gè)方法的缺點(diǎn)在于如果terminal終端關(guān)閉,無論是正常關(guān)閉還是非正常關(guān)閉,這個(gè)php進(jìn)程都會隨著終端關(guān)閉而關(guān)閉,其次是代碼中如果有echo或者print_r之類的輸出文本,會被輸出到當(dāng)前的終端窗口中.

2.使用nohup命令,比如nohupphptask.php.默認(rèn)情況下,代碼中echo或者print_r之類輸出的文本會被輸出到php代碼同級目錄的nohup.out文件中.如果你用exit命令或者關(guān)閉按鈕等正常手段關(guān)閉終端,該進(jìn)程不會被關(guān)閉,依然會在后臺持續(xù)運(yùn)行.但是如果終端遇到異常退出或者終止,該php進(jìn)程也會隨即退出.本質(zhì)上,也并非穩(wěn)定可靠的daemon方案.

3.使用fork和setsid,我暫且稱之為:*nix解決方案

創(chuàng)建守護(hù)進(jìn)程要求

1.設(shè)置文件創(chuàng)建屏蔽字umask(0)

文件創(chuàng)建屏蔽字是指屏蔽掉文件創(chuàng)建時(shí)的對應(yīng)位(umask()控制系統(tǒng)文件和目錄默認(rèn)權(quán)限)。由于使用fork系統(tǒng)調(diào)用新建的子進(jìn)程繼承了父進(jìn)程的文件創(chuàng)建掩碼,這就給該子進(jìn)程使用文件帶來了諸多的不便。因此,把文件創(chuàng)建掩碼設(shè)置為0,可以大大增強(qiáng)該守護(hù)進(jìn)程的靈活性。

2.調(diào)用fork,父進(jìn)程退出(exit);

如果該守護(hù)進(jìn)程是作為一條簡單的shell命令啟動的,那么父進(jìn)程終止使得shell認(rèn)為該命令已經(jīng)執(zhí)行完畢;保證子進(jìn)程不是一個(gè)進(jìn)程組的組長進(jìn)程,為什么要保證不是進(jìn)程組組長呢?因?yàn)檫M(jìn)程組組長調(diào)用setsid創(chuàng)建會話會報(bào)錯(cuò);

3.子進(jìn)程調(diào)用setsid函數(shù)來創(chuàng)建會話

先介紹一下Linux中的進(jìn)程與控制終端,登錄會話和進(jìn)程組之間的關(guān)系:進(jìn)程屬于一個(gè)進(jìn)程組,進(jìn)程組號(GID)就是進(jìn)程組長的進(jìn)程號(PID)。登錄會話可以包含多個(gè)進(jìn)程組。這些進(jìn)程組共享一個(gè)控制終端。這個(gè)控制終端通常是創(chuàng)建進(jìn)程的登錄終端。

控制終端,登錄會話和進(jìn)程組通常是從父進(jìn)程繼承下來的。我們的目的就是要擺脫它們,使之不受它們的影響。方法是在第2點(diǎn)的基礎(chǔ)上,調(diào)用setsid()使進(jìn)程成為會話組長:

setsid()調(diào)用成功后,進(jìn)程成為新的會話組長和新的進(jìn)程組長,并與原來的登錄會話和進(jìn)程組脫離。由于會話過程對控制終端的獨(dú)占性,進(jìn)程同時(shí)與控制終端脫離。

調(diào)用setsid有3個(gè)作用:

讓進(jìn)程擺脫原會話的控制;

讓進(jìn)程擺脫原進(jìn)程組的控制;

讓進(jìn)程擺脫原控制終端的控制

4.把守護(hù)進(jìn)程工作目錄設(shè)置為根目錄chdir(/);

從父進(jìn)程繼承過來的工作目錄可能在一個(gè)掛載的文件系統(tǒng)中。由于守護(hù)進(jìn)程通常在系統(tǒng)再引導(dǎo)之前是一直存在的,所以如果守護(hù)進(jìn)程的當(dāng)前工作目錄在一個(gè)掛載的文件系統(tǒng)中,會導(dǎo)致該文件系統(tǒng)不能被卸載。

5.把一些文件描述符關(guān)閉【標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯(cuò)誤】

文件描述符:用來標(biāo)識一個(gè)文件。當(dāng)你打開一個(gè)存在的文件或者創(chuàng)建一個(gè)新文件,操作系統(tǒng)都會返回這個(gè)文件描述符。后續(xù)對這個(gè)文件的操作的一些函數(shù),都會用到這個(gè)文件描述符作為參數(shù)。

Linux中三個(gè)特殊的文件描述符,數(shù)字分別為0,1,2:

0:標(biāo)準(zhǔn)輸入[鍵盤],對應(yīng)的符號常量叫STDIN_FILENO

1:標(biāo)準(zhǔn)輸出[屏幕],對應(yīng)的符號常量叫STDOUT_FILENO

2:標(biāo)準(zhǔn)錯(cuò)誤[屏幕],對應(yīng)的符號常量叫STDERR_FILENO

進(jìn)程從創(chuàng)建它的父進(jìn)程那里繼承了打開的文件描述符。如不關(guān)閉,將會浪費(fèi)系統(tǒng)資源,造成進(jìn)程所在的文件系統(tǒng)無法卸下以及引起無法預(yù)料的錯(cuò)誤。

6.當(dāng)調(diào)用setsid函數(shù)后,一般會在創(chuàng)建一個(gè)子進(jìn)程,讓會話首進(jìn)程退出,確保該進(jìn)程不會再獲得控制終端

(1)調(diào)用一次fork的作用:

第一次fork的作用是讓shell認(rèn)為這條命令已經(jīng)終止,不用掛在終端輸入上,還有就是為了后面的setsid服務(wù),因?yàn)檎{(diào)用setsid函數(shù)的進(jìn)程不能是進(jìn)程組組長,如果不fork出子進(jìn)程,則此時(shí)的父進(jìn)程是進(jìn)程組組長,就無法調(diào)用setsid。當(dāng)子進(jìn)程調(diào)用完setsid函數(shù)之后,子進(jìn)程是會話組長也是進(jìn)程組組長,并且脫離了控制終端,此時(shí),不管控制終端如何操作,新的進(jìn)程都不會收到一些信號使得進(jìn)程退出。

(2)第二次fork的作用:

雖然當(dāng)前關(guān)閉了和終端的聯(lián)系,但是后期可能會誤操作打開了終端。

只有會話首進(jìn)程能打開終端設(shè)備,也就是再fork一次,再把父進(jìn)程退出,再次fork的子進(jìn)程作為守護(hù)進(jìn)程繼續(xù)運(yùn)行,保證了該守護(hù)進(jìn)程不再是會話的首進(jìn)程。

第二次不是必須的,是可選的。

7.編寫一個(gè)守護(hù)進(jìn)程

php

//1.設(shè)置文件創(chuàng)建屏蔽字

umask(0);

//2.fork子進(jìn)程

$pid=pcntl_fork();

if($pid0){

print("父進(jìn)程退出\n");

exit(0);

//3.設(shè)置當(dāng)前子進(jìn)程為會話首進(jìn)程,進(jìn)程組長,斷開與終端的連接,成為后臺進(jìn)程

if(-1===posix_setsid()){

print("siderr\n");

//4.把守護(hù)進(jìn)程工作目錄設(shè)置為根目錄

chdir("/");

//已經(jīng)成為守護(hù)進(jìn)程~\(≧▽≦)/~啦

while(1){

echo"test".PHP_EOL;

sleep(2);

}

將文件保存為daemon.php,然后phpdaemon.php執(zhí)行文件,嗯,執(zhí)行結(jié)果卻有些奇怪,大概類似于下圖:

即便你按Ctrl+C都沒用,終端在不斷輸出test,唯一辦法就是關(guān)閉當(dāng)前終端窗口然后重新開一個(gè),為什么會這樣,這就涉及到我們上面提到的第5點(diǎn),需要關(guān)閉繼承過來的標(biāo)準(zhǔn)輸出,輸入,錯(cuò)誤,這樣我們的daemon程序不可以再將終端窗口當(dāng)作默認(rèn)的標(biāo)準(zhǔn)輸出了。

php

//設(shè)置文件創(chuàng)建屏蔽字

umask(0);

//第一次fork子進(jìn)程

$pid=pcntl_fork();

if($pid0){

print("父進(jìn)程退出\n");

exit(0);

//設(shè)置當(dāng)前子進(jìn)程為會話首進(jìn)程,進(jìn)程組長,斷開與終端的連接,成為后臺進(jìn)程

if(-1===posix_setsid()){

print("siderr\n");

//第二次fork徹底斷開控制終端

$pid=pcntl_fork();

if($pid0){

exit(0);//讓會話首進(jìn)程退出

//把守護(hù)進(jìn)程工作目錄設(shè)置為根目錄

chdir("/");

//關(guān)閉標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯(cuò)誤,linux中使用數(shù)字表示文件描述符也就是0,1,2

fclose(STDIN);//0

fclose(STDOUT);//1

fclose(STDERR);//2

//當(dāng)關(guān)掉以上標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)錯(cuò)誤之后,如果后面要對文件操作(比如打開一個(gè)文件,寫入,創(chuàng)建)它返回的文件描述符從0開始,這樣可能造成未知異常

//為了避免問題,我們使用輸出從定向到/dev/null空設(shè)備文件解決這個(gè)問題,重新設(shè)置0,1,2文件描述符用來代替標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯(cuò)誤,往/dev/null寫入數(shù)據(jù)會被丟棄,這樣就不會向終端輸出數(shù)據(jù)了。

$stdin=fopen("/dev/null",'a');

$stdout=fopen("/dev/null",'a');

$stderr=fopen("/dev/null",'a');

//已經(jīng)成為守護(hù)進(jìn)程~\(≧▽≦)/~啦

while(1){

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論