国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHP多進程初探 --- 再次談daemon進程

fox_soyoung / 2009人閱讀

摘要:因為子進程一定不會是組長進程,所以子進程可以調(diào)用。主進程退出子進程繼續(xù)執(zhí)行啦啦啦,啦啦啦,啦啦啦,已經(jīng)變成啦,開心一般服務(wù)器軟件都有寫配置項,比如以模式運行還是以模式運行。

[原文地址:https://blog.ti-node.com/blog...]

其實前面是談過一次daemon進程的,但是并涉及過多原理,但是并不影響使用。今天打算說說關(guān)于daemon進程更多的二三事,本質(zhì)上說,如果你僅僅是簡單實現(xiàn)利用一下daemon進程,這個不看也是可以的。

杠真,*NIX真是波大精深,越是深入看越是發(fā)現(xiàn)它的diao。原理往往都是枯燥的,大家都不愛看,但這并不影響我堅持寫自己對這些東西的理解。

三個概念,理(bei)解(song)一下:

進程組。一坨相關(guān)的進程可以組成一個進程組,每個進程組都會有一個組ID(正整數(shù)),每個進程組都會有一個組長進程,組長進程的ID等于進程組ID。組長進程可以創(chuàng)建新的進程組以及該進程組中的其他進程。一個進程組的是有生命周期的,即便是組長進程掛了,只有組里還有其他的活口,那就就算該進程組依然存活,只有到組里最后一個活口也掛了,那真的就是徹底沒了。

會話。一坨相關(guān)的進程組組成了一個會話。在*NIX下,是通過setsid()創(chuàng)建一個新的會話。但是值得注意的是,組長進程不能創(chuàng)建會話,簡單理解就是在組長進程中,執(zhí)行setsid函數(shù)會報錯,這點很重要。所以一般都是組長進程執(zhí)行fork,然后主進程退出,因為子進程的進程ID是新分配的,而子進程的進程組ID是繼承父進程的,所以子進程就注定不可能是組長進程,從而可以確保子進程中一定可以執(zhí)行setsid函數(shù)。在執(zhí)行setsid函數(shù)時候,一般會發(fā)生下面三個比較重要的事情:

該進程會創(chuàng)建一個新的進程組,該進程為進程組組長(或者你可以認為這是一種提升)

該進程會創(chuàng)建一個會話組并成為該會話的會話首進程(會話首進程就是創(chuàng)建該會話的進程)

該進程會失去控制終端。如果該進程本來就沒有控制終端,則罷了(liao)。如果有,那么該進程也將脫離該控制終端,與之失去聯(lián)系。

控制終端。每個會話可能會擁有一個控制終端(看著比較玄學(xué),你可以暫時理解為就一個那種黑乎乎的命令行窗口),建立與控制終端連接的會話首進程叫做控制進程。

結(jié)合Linux命令ps來查看一下上述幾個概念的恩怨情仇,我們看下我們常用的 ps -o pid,ppid,pgid,sid,comm | less 執(zhí)行結(jié)果:

第一行分別是PID,PPID,PGID,SID,COMMAND,依次分別是進程ID,該進程父進程ID,進程組ID,會話ID,命令。

通過最后一列,我們知道第二行就是bash也就是bash shell進程,其進程ID為15793,其父進程為13291,進程組ID為15793,會話ID也會15793,結(jié)合前面的概念,我們可以知道bash shell就是該進程組組長。

第三行則是ps命令的進程,其進程ID為15816,他是由于bash進程fork出來的,所以他的父進程ID為15793,然后是他所屬的組ID為15816,所屬的會話ID依然是15793。

最后一行是less命令的進程,其進程ID為15817,他也是由bash進程fork出來的,所以他的父進程ID也為15793,然后是他所屬的組ID為15816,所屬的會話ID依然是15793。

簡單總結(jié)一下:

上述三個進程一共形成了兩個進程組,bash自己為一組,組ID為15793,組長進程為bash自己 ; ps和less為一組,組ID為15816,組長進程為ps進程

上述三個進程屬于同一個會話,會話ID為15793,會話首進程為bash進程(待定)

控制終端則為打開的terminal窗口,與之關(guān)聯(lián)的控制進程則為bash進程

通過這么一頓分析,是不是感覺可以接受點兒了?然后是,叨逼叨了半天這個,跟daemon進程有啥子關(guān)系?
啦啦啦,下面通過引入代碼直接分析:

$pid = pcntl_fork();
if( $pid < 0 ){
  exit("fork error.");
} else if( $pid > 0 ) {
  // 主進程退出
  exit();
}
// 子進程繼續(xù)執(zhí)行

// 最關(guān)鍵的一步來了,執(zhí)行setsid函數(shù)!
if( !posix_setsid() ){
  exit("setsid error.");
}

// 理論上一次fork就可以了
// 但是,二次fork,這里的歷史淵源是這樣的:在基于system V的系統(tǒng)中,通過再次fork,父進程退出,子進程繼續(xù),保證形成的daemon進程絕對不會成為會話首進程,不會擁有控制終端。

$pid = pcntl_fork();
if( $pid  < 0 ){
  exit("fork error");
} else if( $pid > 0 ) {
  // 主進程退出
  exit;
}

// 子進程繼續(xù)執(zhí)行

// 啦啦啦,啦啦啦,啦啦啦,已經(jīng)變成daemon啦,開心
cli_set_process_title("testtesttest");
// 睡眠1000000,防止進程執(zhí)行完畢掛了
sleep( 1000000 );

將上述文件保存為daemon.php,然后php daemon.php執(zhí)行,使用 ps -aux | grep testte ,如果沒有什么大問題你應(yīng)該就可以看到這個進程在后臺跑了。

所以為什么第一步要先fork呢?因為調(diào)用setsid的進程不可以是組長進程(篇頭的枯燥知識需要了吧?),所以必須fork一次,然后將主進程直接退出,保留子進程。因為子進程一定不會是組長進程,所以子進程可以調(diào)用setsid。調(diào)用setsid則會產(chǎn)生三個現(xiàn)象:創(chuàng)建一個新會話并成為會話首進程,創(chuàng)建一個進程組并成為組長進程,脫離控制終端。

啦啦啦,明白為啥篇頭那一坨枯燥的知識是為了什么吧?

然而,實際上,上述代碼僅僅完成了一個標準daemon的80%,還有20%需要我們進一步完善。那么,需要完善什么呢?我們修改一下上述代碼,讓程序在最終的代碼段中執(zhí)行一些文本輸出:

$pid = pcntl_fork();
if( $pid < 0 ){
  exit("fork error.");
} else if( $pid > 0 ) {
  // 主進程退出
  exit();
}
// 子進程繼續(xù)執(zhí)行

// 最關(guān)鍵的一步來了,執(zhí)行setsid函數(shù)!
if( !posix_setsid() ){
  exit("setsid error.");
}

// 理論上一次fork就可以了
// 但是,二次fork,這里的歷史淵源是這樣的:在基于system V的系統(tǒng)中,通過再次fork,父進程退出,子進程繼續(xù),保證形成的daemon進程絕對不會成為會話首進程,不會擁有控制終端。

$pid = pcntl_fork();
if( $pid  < 0 ){
  exit("fork error");
} else if( $pid > 0 ) {
  // 主進程退出
  exit;
}

// 子進程繼續(xù)執(zhí)行

// 啦啦啦,啦啦啦,啦啦啦,已經(jīng)變成daemon啦,開心
cli_set_process_title("testtesttest");
// 循環(huán)1000次,每次睡眠1s,輸出一個字符test
for( $i = 1; $i <= 1000; $i++ ){
  sleep( 1 );
  echo "test".PHP_EOL;
}

將文件保存為daemon.php,然后php daemon.php執(zhí)行文件,嗯,是不是有怪怪的現(xiàn)象,大概類似于下圖:

即便你按Ctrl+C都沒用,終端在不斷輸出test,唯一辦法就是關(guān)閉當前終端窗口然后重新開一個,然而,這并不符合社會主義主流價值觀。所以,我們還要解決標準輸出和錯誤輸出,我們的daemon程序不可以再將終端窗口當作默認的標準輸出了。

其次是將當前工作目錄修改更改為根目錄。不然可能就會出現(xiàn)下面這樣一個問題,就是如果父進程是的工作目錄是一個掛載的目錄,那么子進程會繼承父進程的工作目錄,當子進程已經(jīng)daemon化后就會出現(xiàn)一個悲劇:那就是雖然原來掛載的目錄已經(jīng)不用了,但是卻無法用umount卸載,非常悲劇。

最后一個問題是,要在第一次fork后設(shè)置umask(0),避免權(quán)限上的一些問題。所以較為完整的代碼如下:
// 設(shè)置umask為0,這樣,當前進程創(chuàng)建的文件權(quán)限則為777
umask( 0 );

$pid = pcntl_fork();
if( $pid < 0 ){
  exit("fork error.");
} else if( $pid > 0 ) {
  // 主進程退出
  exit();
}
// 子進程繼續(xù)執(zhí)行

// 最關(guān)鍵的一步來了,執(zhí)行setsid函數(shù)!
if( !posix_setsid() ){
  exit("setsid error.");
}

// 理論上一次fork就可以了
// 但是,二次fork,這里的歷史淵源是這樣的:在基于system V的系統(tǒng)中,通過再次fork,父進程退出,子進程繼續(xù),保證形成的daemon進程絕對不會成為會話首進程,不會擁有控制終端。

$pid = pcntl_fork();
if( $pid  < 0 ){
  exit("fork error");
} else if( $pid > 0 ) {
  // 主進程退出
  exit;
}

// 子進程繼續(xù)執(zhí)行

// 啦啦啦,啦啦啦,啦啦啦,已經(jīng)變成daemon啦,開心
cli_set_process_title("testtesttest");
// 一般服務(wù)器軟件都有寫配置項,比如以debug模式運行還是以daemon模式運行。如果以debug模式運行,那么標準輸出和錯誤輸出大多數(shù)都是直接輸出到當前終端上,如果是daemon形式運行,那么錯誤輸出和標準輸出可能會被分別輸出到兩個不同的配置文件中去
// 連工作目錄都是一個配置項目,通過php函數(shù)chdir可以修改當前工作目錄
chdir( $dir );

[原文地址:https://blog.ti-node.com/blog...]

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/29350.html

相關(guān)文章

  • PHP進程初探 --- 利用進程開發(fā)點兒東西吧

    摘要:主進程退出子進程繼續(xù)執(zhí)行給進程重新起個名字加入我們出個子進程就可以搞定這些任務(wù),那么出個子進程,同時父進程要負責這個子進程的狀態(tài)等。 [原文地址:https://blog.ti-node.com/blog...] 干巴巴地叨逼叨了這么久,時候表演真正的技術(shù)了! 做個高端點兒的玩意吧,加入我們要做一個任務(wù)系統(tǒng),這個系統(tǒng)可以在后臺幫我們完成一大波(注意是一大波)數(shù)據(jù)的處理,那么我們自然想到...

    huaixiaoz 評論0 收藏0
  • 剖析 Laravel 計劃任務(wù)--初探

    摘要:表示該工作應(yīng)該在每個月日上午運行這里還有一些其他的示例表示工作應(yīng)該在星期三每分鐘運行一次。表示該工作應(yīng)該每天在凌晨點和點運行兩次。方法調(diào)用的實例作為唯一的參數(shù),這是用于記錄您提供的作業(yè)的計劃任務(wù)管理器,并決定每次守護進程應(yīng)該運行什么。 譯文GitHub https://github.com/yuansir/diving-laravel-zh 原文鏈接 https://divinglar...

    mo0n1andin 評論0 收藏0
  • PHP進程初探 --- 開篇

    摘要:所以我們只說的多進程,至于多線程就暫時放到一邊兒。出來新進程則成為子進程,原進程則成為父進程,子進程擁有父進程的副本。在父進程中返回子進程的進程,在子進程內(nèi)部本身返回數(shù)字。 [原文地址:https://blog.ti-node.com/blog...] 實際上PHP是有多線程的,只是很多人不常用。使用PHP的多線程首先需要下載安裝一個線程安全版本(ZTS版本)的PHP,然后再安裝pec...

    wh469012917 評論0 收藏0
  • PHP socket初探 --- select系統(tǒng)調(diào)用

    摘要:原文地址在初探先從一個簡單的服務(wù)器開始中依次講解了三個逐漸進步的服務(wù)器只能服務(wù)于一個客戶端的服務(wù)器利用可以服務(wù)于多個客戶端的額服務(wù)器利用預(yù)派生進程服務(wù)于多個客戶端的服務(wù)器最后一種服務(wù)器的進程模型基本上的大概原理其實跟我們常用的是非常 [原文地址:https://blog.ti-node.com/blog...] 在<PHP socket初探 --- 先從一個簡單的socket服務(wù)器開始...

    springDevBird 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<