摘要:主進(jìn)程退出子進(jìn)程繼續(xù)執(zhí)行給進(jìn)程重新起個名字加入我們出個子進(jìn)程就可以搞定這些任務(wù),那么出個子進(jìn)程,同時父進(jìn)程要負(fù)責(zé)這個子進(jìn)程的狀態(tài)等。
[原文地址:https://blog.ti-node.com/blog...]
干巴巴地叨逼叨了這么久,時候表演真正的技術(shù)了!
做個高端點兒的玩意吧,加入我們要做一個任務(wù)系統(tǒng),這個系統(tǒng)可以在后臺幫我們完成一大波(注意是一大波)數(shù)據(jù)的處理,那么我們自然想到,多開幾個進(jìn)程分開處理這些數(shù)據(jù),同時我們不能執(zhí)行了php task.php后終端掛起,萬一一不小心關(guān)閉了終端都會導(dǎo)致任務(wù)失敗,所以我們還要實現(xiàn)程序的daemon化。好啦,開始了!
首先,我們第一步就得將程序daemon化了!
// 設(shè)置umask為0,這樣,當(dāng)前進(jìn)程創(chuàng)建的文件權(quán)限則為777 umask( 0 ); $pid = pcntl_fork(); if( $pid < 0 ){ exit("fork error."); } else if( $pid > 0 ) { // 主進(jìn)程退出 exit(); } // 子進(jìn)程繼續(xù)執(zhí)行 // 最關(guān)鍵的一步來了,執(zhí)行setsid函數(shù)! if( !posix_setsid() ){ exit("setsid error."); } // 理論上一次fork就可以了 // 但是,二次fork,這里的歷史淵源是這樣的:在基于system V的系統(tǒng)中,通過再次fork,父進(jìn)程退出,子進(jìn)程繼續(xù) // 保證形成的daemon進(jìn)程絕對不會成為會話首進(jìn)程,不會擁有控制終端。 $pid = pcntl_fork(); if( $pid < 0 ){ exit("fork error"); } else if( $pid > 0 ) { // 主進(jìn)程退出 exit; } // 子進(jìn)程繼續(xù)執(zhí)行 // 給進(jìn)程重新起個名字 cli_set_process_title("php master process");
加入我們fork出5個子進(jìn)程就可以搞定這些任務(wù),那么fork出5個子進(jìn)程,同時父進(jìn)程要負(fù)責(zé)這5個子進(jìn)程的狀態(tài)等。
// 由于*NIX好像并沒有(如果有,請告知)可以獲取父進(jìn)程fork出所有的子進(jìn)程的ID們的功能,所以這個需要我們自己來保存 $child_pid = []; // 父進(jìn)程安裝SIGCHLD信號處理器并分發(fā) pcntl_signal( SIGCHLD, function(){ // 這里注意要使用global將child_pid全局化,不然讀到去數(shù)組將為空,具體原因可以自己思考下 global $child_pid; // 如果子進(jìn)程的數(shù)量大于0,也就說如果還有子進(jìn)程存活未 退出,那么執(zhí)行回收 $child_pid_num = count( $child_pid ); if( $child_pid_num > 0 ){ // 循環(huán)子進(jìn)程數(shù)組 foreach( $child_pid as $pid_key => $pid_item ){ $wait_result = pcntl_waitpid( $pid_item, $status, WNOHANG ); // 如果子進(jìn)程被成功回收了,那么一定要將其進(jìn)程ID從child_pid中移除掉 if( $wait_result == $pid_item || -1 == $wait_result ){ unset( $child_pid[ $pid_key ] ); } } } } ); // fork出5個子進(jìn)程出來,并給每個子進(jìn)程重命名 for( $i = 1; $i <= 5; $i++ ){ $_pid = pcntl_fork(); if( $_pid < 0 ){ exit(); } else if( 0 == $_pid ) { // 重命名子進(jìn)程 cli_set_process_title("php worker process"); // 啦啦啦啦啦啦啦啦啦啦,請在此處編寫你的業(yè)務(wù)代碼 // do something ... // 啦啦啦啦啦啦啦啦啦啦,請在此處編寫你的業(yè)務(wù)代碼 // 子進(jìn)程退出執(zhí)行,一定要exit,不然就不會fork出5個而是多于5個任務(wù)進(jìn)程了 exit(); } else if( $_pid > 0 ) { // 將fork出的任務(wù)進(jìn)程的進(jìn)程ID保存到數(shù)組中 $child_pid[] = $_pid; } } // 主進(jìn)程繼續(xù)循環(huán)不斷派遣信號 while( true ){ pcntl_signal_dispatch(); // 每派遣一次休眠一秒鐘 sleep( 1 ); }
[原文地址:https://blog.ti-node.com/blog...]
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/29349.html
摘要:所以我們只說的多進(jìn)程,至于多線程就暫時放到一邊兒。出來新進(jìn)程則成為子進(jìn)程,原進(jìn)程則成為父進(jìn)程,子進(jìn)程擁有父進(jìn)程的副本。在父進(jìn)程中返回子進(jìn)程的進(jìn)程,在子進(jìn)程內(nèi)部本身返回數(shù)字。 [原文地址:https://blog.ti-node.com/blog...] 實際上PHP是有多線程的,只是很多人不常用。使用PHP的多線程首先需要下載安裝一個線程安全版本(ZTS版本)的PHP,然后再安裝pec...
摘要:因為子進(jìn)程一定不會是組長進(jìn)程,所以子進(jìn)程可以調(diào)用。主進(jìn)程退出子進(jìn)程繼續(xù)執(zhí)行啦啦啦,啦啦啦,啦啦啦,已經(jīng)變成啦,開心一般服務(wù)器軟件都有寫配置項,比如以模式運行還是以模式運行。 [原文地址:https://blog.ti-node.com/blog...] 其實前面是談過一次daemon進(jìn)程的,但是并涉及過多原理,但是并不影響使用。今天打算說說關(guān)于daemon進(jìn)程更多的二三事,本質(zhì)上說,如...
摘要:原文前面可以說是弄了一系列的和多進(jìn)程的一大坨內(nèi)容,知識淺顯代碼粗暴風(fēng)格簡陋,總的說來,還是差了一些細(xì)節(jié)。今天,就一些漏掉的細(xì)節(jié)補(bǔ)充一下。最后,我補(bǔ)充一句是同步的,而不是異步。 原文:https://t.ti-node.com/thread/... 前面可以說是弄了一系列的php socket和多進(jìn)程的一大坨內(nèi)容,知識淺顯、代碼粗暴、風(fēng)格簡陋,總的說來,還是差了一些細(xì)節(jié)。今天,就一些漏...
摘要:原文地址在初探先從一個簡單的服務(wù)器開始中依次講解了三個逐漸進(jìn)步的服務(wù)器只能服務(wù)于一個客戶端的服務(wù)器利用可以服務(wù)于多個客戶端的額服務(wù)器利用預(yù)派生進(jìn)程服務(wù)于多個客戶端的服務(wù)器最后一種服務(wù)器的進(jìn)程模型基本上的大概原理其實跟我們常用的是非常 [原文地址:https://blog.ti-node.com/blog...] 在<PHP socket初探 --- 先從一個簡單的socket服務(wù)器開始...
閱讀 1046·2021-09-26 09:55
閱讀 3619·2021-09-24 10:30
閱讀 1409·2021-09-08 09:36
閱讀 2584·2021-09-07 09:58
閱讀 626·2019-08-30 15:56
閱讀 797·2019-08-29 18:32
閱讀 3688·2019-08-29 15:13
閱讀 1865·2019-08-29 13:49