深入理解PHP高性能框架中Workerman守護(hù)進(jìn)程原理

深入理解php高性能框架中workerman守護(hù)進(jìn)程原理

在我們?nèi)粘>幊讨校R姷睦颖热?php think 需要不斷執(zhí)行的任務(wù),比如 php arts… 和 php yii…,都會(huì)通過 nohup 掛載到后臺(tái),以保持長(zhǎng)期運(yùn)行狀態(tài)。同樣,在workerman中,使用類似php index.php start的命令來(lái)啟動(dòng)進(jìn)程,但不同的是,它不需要使用nohup來(lái)掛載并在后臺(tái)運(yùn)行。有的朋友可能會(huì)好奇是如何實(shí)現(xiàn)的呢?為了解決小伙伴們關(guān)心的問題,今天我們重點(diǎn)深入分析workerman守護(hù)進(jìn)程的實(shí)現(xiàn)原理。

我們先來(lái)了解一些流程相關(guān)的知識(shí):

父進(jìn)程:父進(jìn)程是生成其他進(jìn)程的進(jìn)程。當(dāng)一個(gè)進(jìn)程創(chuàng)建另一個(gè)進(jìn)程時(shí),創(chuàng)建者稱為父進(jìn)程,創(chuàng)建的進(jìn)程成為子進(jìn)程。父進(jìn)程可以通過進(jìn)程標(biāo)識(shí)符(pid)來(lái)識(shí)別它創(chuàng)建的子進(jìn)程。
子進(jìn)程:子進(jìn)程是父進(jìn)程創(chuàng)建的新進(jìn)程。子進(jìn)程繼承了父進(jìn)程的一些屬性,比如環(huán)境變量、文件描述符等。子進(jìn)程獨(dú)立于父進(jìn)程運(yùn)行,可以執(zhí)行自己的代碼,擁有自己的資源和內(nèi)存空間。
進(jìn)程組:進(jìn)程組是關(guān)聯(lián)進(jìn)程的集合。每個(gè)進(jìn)程組都有一個(gè)唯一的進(jìn)程組 id (pgid),用于標(biāo)識(shí)該進(jìn)程組。進(jìn)程組通常由父進(jìn)程創(chuàng)建,并包括與父進(jìn)程具有相同會(huì)話 id (sid) 的所有子進(jìn)程。
會(huì)話:會(huì)話是相關(guān)進(jìn)程的集合,通常在用戶登錄系統(tǒng)時(shí)開始,在用戶注銷或關(guān)閉終端時(shí)結(jié)束。會(huì)話中的進(jìn)程共享同一個(gè)控制終端。每個(gè)會(huì)話都有一個(gè)唯一的會(huì)話 id (sid),用于標(biāo)識(shí)該會(huì)話。一個(gè)會(huì)話通常包含一個(gè)或多個(gè)進(jìn)程組,第一個(gè)進(jìn)程組成為會(huì)話的主進(jìn)程組。

這些概念俗稱八足文,從來(lái)都不容易理解。讓我們看一個(gè)例子。執(zhí)行命令“php index.html”后php’,生成了進(jìn)程61052。該進(jìn)程的父進(jìn)程是bash進(jìn)程8243,所以這里無(wú)需擔(dān)心。然后,通過fork創(chuàng)建了一個(gè)子進(jìn)程61053,其父進(jìn)程為61052。這兩個(gè)進(jìn)程有共同的進(jìn)程組61052和會(huì)話8243。調(diào)用posix_setsid函數(shù)會(huì)為子進(jìn)程打開一個(gè)新的進(jìn)程組61053和一個(gè)新的會(huì)話61053進(jìn)程61053,其中的會(huì)話可以理解為新的命令窗口終端。最后,子進(jìn)程61053通過fork創(chuàng)建了子進(jìn)程61054,進(jìn)程61053升級(jí)為父進(jìn)程。再次fork的原因是為了避免與終端控制的進(jìn)程相關(guān)聯(lián)。這個(gè)進(jìn)程61052是在終端模式下創(chuàng)建的,從此以后,進(jìn)程61054就形成了守護(hù)進(jìn)程。

[ manongsen@root  phpwork]$ php index.php
[parent] process id: 61052, parent process id: 8243, process group id: 61052, session id: 8243
[parent1] process id: 61052, parent process id: 8243, process group id: 61052, session id: 8243 exited the process
[child1] process id: 61053, parent process id: 61052, process group id: 61052, session id: 8243
[child1] process id: 61053, parent process id: 61052, process group id: 61053, session id: 61053
[parent2] process id: 61053, parent process id: 61052, process group id: 61053, session id: 61053 exited the process
[child2] process id: 61054, parent process id: 61053, process group id: 61053, session id: 61053. this process is retained

[ manongsen@root  phpwork]$ ps aux | grep index.php
root 66064 0.0 0.0 408105040 1472 s080 s+10:00 pm 00:00 grep index.php
root 61054 0.0 438073488 280?? s 10:00 pm 00:00 php index.php
關(guān)注:愛掏網(wǎng)

上面提到的進(jìn)程信息就是通過這段代碼的執(zhí)行而生成的。如果你仔細(xì)閱讀這段代碼,你會(huì)發(fā)現(xiàn)為什么 posix_setsid 函數(shù)不是在第一個(gè) fork 之前調(diào)用,而是在第二個(gè) fork 之前調(diào)用。這樣就不用fork兩次了?原因是leader進(jìn)程無(wú)法創(chuàng)建會(huì)話,而進(jìn)程組id 61052與進(jìn)程id 61052相同,即當(dāng)前進(jìn)程是leader進(jìn)程。因此需要一個(gè)子進(jìn)程來(lái)創(chuàng)建新的session,這一點(diǎn)需要特別注意。

 php

function echomsg($prefix, $suffix="") {
//process id
$pid = getmypid(); 
//process group id
$pgid = posix_getpgid($pid);
//session id
$sid = posix_getsid($pid); 
//parent process id
$ppid = posix_getppid();

echo "[{$prefix}] process id: {$pid}, parent process id: {$ppid}, process group id: {$pgid}, session id: {$sd} {$suffix}". php_eol;
}

//[parent] process id: 61052, parent process id: 8243, process group id: 61052, session id: 8243
echomsg("parent");

//the first fork process
$pid = pcntl_fork();
if ( $pid  0 ) {
//[parent1] process id: 61052, parent process id: 8243, process group id: 61052, session id: 8243 exited the process
echoes ("parent1", "exited the process");
exit;
}

//the child process id created is 61053, but the process group, session, and parent process are still the same
//[child1] process id: 61053, parent process id: 61052, process group id: 61052, session id: 8243
echomsg("child1");

//calling the posix_setsid function will create a new session and process group, and set the process group id and session id to that process id
if (-1 === \posix_setsid()) {
throw new exception("setsid fail");
}

//now you will find that both the process group id and session id have changed to 61053, which is equivalent to starting a session window similar to a linux terminal
//[child1] process id: 61053, parent process id: 61052, process group id: 61053, session id: 61053
echomsg("child1");

//second fork process
//the reason for requiring a secondary fork process here is to avoid being associated with terminal controlled processes. this process 61052 was created in terminal mode
//need to detach from process 61052 to ensure the stability of the daemon process
$pid = pcntl_fork();
if ( $pid   0 ) {
//[parent2] process id: 61053, parent process id: 61052, process group id: 61053, session id: 61053 exited the process
echoes ("parent2", "exited the process");
exit;
}

//at this point, the process has broken free from the control of the terminal process and formed a daemon process
//[child2] process id: 61054, parent process id: 61053, process group id: 61053, session id: 61053. this process is retained
echoes ("child2", "this process is reserved");

sleep(100);
關(guān)注:愛掏網(wǎng)

最好有時(shí)間的朋友自己執(zhí)行代碼分析一下,會(huì)有不同的獎(jiǎng)勵(lì)。這里假裝你已經(jīng)實(shí)踐過了,我們看一下workerman的worker.php文件第554行runall方法中的static::daemon()函數(shù)。實(shí)現(xiàn)的流程邏輯與上面的例子幾乎相同。不過這里也用到了umask函數(shù),它的主要作用是給進(jìn)程創(chuàng)建的文件或目錄授予相應(yīng)的權(quán)限,保證有對(duì)文件或目錄進(jìn)行操作的權(quán)限。

// workerman/Worker.php:554
/**
* Run all worker instances.
*Run process
* @return void
*/
public static function runAll()
{
static::checkSapiEnv();
static::init();
static::parseCommand();
static::lock();
//Create a process and form a daemon process
static::daemonize();
static::initWorkers();
static::installSignal();
static::saveMasterPid();
static::lock(\LOCK_UN);
static::displayUI();
static::forkWorkers();
static::resetStd();
static::monitorWorkers();
}

// workerman/Worker.php:1262
/**
* Run as daemon mode.
*Run in daemon mode
* @throws Exception
*/
protected static function daemonize()
{
//Determine whether it is already in a guarded state and whether the current system is in a Linux environment
if (! static::$daemonize || static::$_OS !== \OS_TYPE_LINUX) {
return;
}

//If umask is set to 0, the file permissions created by the current process will be 777, which has the highest permission
\umask(0);

//The first time creating a process
$pid = \pcntl_fork();
if (-1 === $pid) {
//Process creation failed
throw new Exception('Fork fail');
} elseif ($pid > 0) {
//Main process exits
exit(0);
}

//The child process continues to execute
//By calling the posix_setsid function, a process can detach from its parent process and transform into a daemon process
if (-1 === \posix_setsid()) {
throw new Exception("Setsid fail");
}

//The second creation process, in a System V based system, exits by forking the parent process again
//Ensure that the formed daemon process does not become the first session process and does not have control terminals
$pid = \pcntl_fork();
if (-1 === $pid) {
//Process creation failed
throw new Exception("Fork fail");
} elseif (0 !== $pid) {
//Main process exits
exit(0);
}

//The child process continues to execute
}
關(guān)注:愛掏網(wǎng)

守護(hù)進(jìn)程也是workerman的重要組成部分,保證了workerman進(jìn)程的穩(wěn)定性。與我們通過nohup啟動(dòng)的命令不同,這些命令有時(shí)會(huì)在后臺(tái)掛起而沒有人注意到,朋友們可能已經(jīng)經(jīng)歷過這一點(diǎn)。當(dāng)然,市面上也有一些開源的守護(hù)進(jìn)程管理軟件,比如supervisors,也有人使用screen、tmux等會(huì)話終端來(lái)實(shí)現(xiàn)。事實(shí)上,守護(hù)進(jìn)程的實(shí)現(xiàn)方式有很多種。這里僅介紹一個(gè)php中實(shí)現(xiàn)守護(hù)進(jìn)程模式的例子來(lái)分析workerman中守護(hù)進(jìn)程的實(shí)現(xiàn)原理。希望本內(nèi)容能夠?qū)δ兴鶐椭?/p>

如果您想體驗(yàn)新版本php或者切換php版本,歡迎使用servbay部署php開發(fā)環(huán)境。這是我正在開發(fā)的產(chǎn)品,我會(huì)長(zhǎng)期維護(hù)這個(gè)工具。

立即學(xué)習(xí)“PHP免費(fèi)學(xué)習(xí)筆記(深入)”;

以上就是深入理解PHP高性能框架中Workerman守護(hù)進(jìn)程原理的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注愛掏網(wǎng) - it200.com其它相關(guān)文章!

聲明:所有內(nèi)容來(lái)自互聯(lián)網(wǎng)搜索結(jié)果,不保證100%準(zhǔn)確性,僅供參考。如若本站內(nèi)容侵犯了原著者的合法權(quán)益,可聯(lián)系我們進(jìn)行處理。
發(fā)表評(píng)論
更多 網(wǎng)友評(píng)論0 條評(píng)論)
暫無(wú)評(píng)論

返回頂部

主站蜘蛛池模板: 中文字幕精品一区二区三区视频 | 好紧好爽太大了h视频| 另类小说亚洲色图| a在线免费观看视频| 欧美性生交xxxxx丝袜| 国产精品偷伦视频观看免费| 久久网免费视频| 美女跪下吃j8羞羞漫画| 女人张开大腿让男人桶| 亚洲精品午夜视频| 人人玩人人添人人| 无码综合天天久久综合网| 免费成人黄色大片| 22222色男人的天堂| 日本高清视频色wwwwww色| 午夜时刻免费实验区观看| 99re在线播放视频| 最近更新中文字幕在线| 啊灬啊别停灬用力啊动视频| 99久re热视频这里只有精品6| 最近中文字幕高清2019中文字幕 | 站在镜子前看我怎么c你| 国产韩国精品一区二区三区| 九九久久精品无码专区| 精品福利视频网| 国产精品视频一区二区三区无码| 久久精品国产亚洲一区二区| 精品无码久久久久久久久久| 国产精品美脚玉足脚交欧美| 久久久久久亚洲精品中文字幕| 猴哥影院在线播放视频| 国产男女猛烈无遮挡免费视频| 中文字幕人妻中文AV不卡专区| 正在播放julia女教师| 国产区精品一区二区不卡中文| www.11yinyuan.com| 欧美va天堂va视频va在线| 可播放的欧美男男videos| 2022国产成人福利精品视频| 无码人妻精品一二三区免费| 亚洲第一区二区快射影院|