日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > php >内容正文

php

php 多进程 常驻内存,PHP 多进程与信号中断实现多任务常驻内存管理 [Master/Worker 模型]...

發(fā)布時(shí)間:2023/12/20 php 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php 多进程 常驻内存,PHP 多进程与信号中断实现多任务常驻内存管理 [Master/Worker 模型]... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文章基于pcntl擴(kuò)展做的多進(jìn)程測試。

進(jìn)程調(diào)度策略

父子進(jìn)程的調(diào)度由操作系統(tǒng)來負(fù)責(zé),具體先調(diào)度子進(jìn)程還是父進(jìn)程由系統(tǒng)的調(diào)度算法決定,當(dāng)然可以在父進(jìn)程加上延時(shí)或是調(diào)用進(jìn)程回收函數(shù)pcntl_wait可以先讓子進(jìn)程先運(yùn)行,進(jìn)程回收的目的是釋放進(jìn)程創(chuàng)建時(shí)占用的內(nèi)存空間,防止變成僵尸進(jìn)程。

信號:

信號稱為軟中斷系統(tǒng)或是叫軟中斷,功能是向進(jìn)程發(fā)送異步事件通知。

信號編號: 【源碼基于SIGINT,SIGTERM,SIGUSR1信號,含義請自行查看kill命令手冊,不在描述】

linux支持64個(gè),有一半為實(shí)時(shí)信號,一半為非時(shí)實(shí)信號,這些信號都有自己的編號和對應(yīng)的整數(shù)值。每個(gè)信號的編號含義讀者可以參閱linux相關(guān)手冊【man手冊看看就知道了】

信號處理函數(shù):

信號一般會綁定相應(yīng)的功能,有的是默認(rèn)動作如SIGKILL,SIGTERM,SIGINT操作默認(rèn)操作就是干掉進(jìn)程,當(dāng)然我們可以重寫覆蓋掉,就是通過pcntl_signal來覆蓋掉。

信號的概念:與硬件中斷一個(gè)道理,請讀者自行參考本人前面擼過的文章或是查看芯片硬件中斷原理。

信號的發(fā)送:

kill 信號編號 進(jìn)程 或是按鍵產(chǎn)品的中斷信號或是在源碼里可以使用posix_kill等函數(shù)。

進(jìn)程是相互隔離的,擁有自己的堆??臻g,除了一些公用的正文【代碼區(qū)】,同時(shí)也有自己的可執(zhí)行代碼,進(jìn)程運(yùn)行時(shí),將占用cpu的資源,其它進(jìn)程將無權(quán)運(yùn)行,此時(shí)其它進(jìn)程將為阻塞狀態(tài)【比如前面擼過的tcp服務(wù)】,當(dāng)進(jìn)程運(yùn)行結(jié)束后【運(yùn)行到代碼的最后一句或是遇到return或是遇到exit退出進(jìn)程函數(shù)或是遇到信號事件時(shí)將會退出】讓出權(quán)限并釋放掉內(nèi)存,其它進(jìn)程就有機(jī)會運(yùn)行了。

進(jìn)程擁有的自己進(jìn)程描述符,其中比較常用的是進(jìn)程號PID,進(jìn)程運(yùn)行時(shí)會在系統(tǒng)/proc/PID下生成相應(yīng)的進(jìn)程文件,用戶可以自行查看。

每個(gè)進(jìn)程都擁有所屬的進(jìn)程組【進(jìn)程的集合】,多個(gè)進(jìn)程組集合則是一個(gè)會話,創(chuàng)建一個(gè)會話是通過一個(gè)進(jìn)程進(jìn)行創(chuàng)建的,并且此進(jìn)程不可以為組長進(jìn)程,此進(jìn)程將成為會話期的會話首進(jìn)程,也會成為進(jìn)程組的進(jìn)程組長,同時(shí)將會脫離控制終端,即使之前的進(jìn)程綁定了控制終端也會脫離【守護(hù)進(jìn)程的創(chuàng)建】。

文件描述權(quán)限掩碼【權(quán)限屏蔽字】:

umask() 你可以在linux運(yùn)行這個(gè)命令,然后創(chuàng)建文件,并查看它的權(quán)限【如果你跑完啥也沒有發(fā)現(xiàn),說明你還是訓(xùn)練不夠^_^】

/**

* Created by PhpStorm.

* User: 1655664358@qq.com

* Date: 2018/3/26

* Time: 14:19

*/

namespace Chen\Worker;

class Server

{

public $workerPids = [];

public $workerJob = [];

public $master_pid_file = "master_pid";

public $state_file = "state_file.txt";

function run()

{

$this->daemon();

$this->worker();

$this->setMasterPid();

$this->installSignal();

$this->showState();

$this->wait();

}

function wait()

{

while (1){

pcntl_signal_dispatch();

$pid = pcntl_wait($status);

if ($pid>0){

unset($this->workerPids[$pid]);

}else{

if (count($this->workerPids)==0){

exit();

}

}

usleep(100000);

}

}

function showState()

{

$state = "\nMaster 信息\n";

$state.=str_pad("master pid",25);

$state.=str_pad("worker num",25);

$state.=str_pad("job pid list",10)."\n";

$state.=str_pad($this->getMasterPid(),25);

$state.=str_pad(count($this->workerPids),25);

$state.=str_pad(implode(",",array_keys($this->workerPids)),10);

echo $state.PHP_EOL;

}

function getMasterPid()

{

if (file_exists($this->master_pid_file)){

return file_get_contents($this->master_pid_file);

}else{

exit("服務(wù)未運(yùn)行\(zhòng)n");

}

}

function setMasterPid()

{

$fp = fopen($this->master_pid_file,"w");

@fwrite($fp,posix_getpid());

@fclose($fp);

}

function daemon()

{

$pid = pcntl_fork();

if ($pid<0){

exit("fork進(jìn)程失敗\n");

}else if ($pid >0){

exit(0);

}else{

umask(0);

$sid = posix_setsid();

if ($sid<0){

exit("創(chuàng)建會話失敗\n");

}

$pid = pcntl_fork();

if ($pid<0){

exit("進(jìn)程創(chuàng)建失敗\n");

}else if ($pid >0){

exit(0);

}

//可以關(guān)閉標(biāo)準(zhǔn)輸入輸出錯(cuò)誤文件描述符【守護(hù)進(jìn)程不需要】

}

}

function worker()

{

if (count($this->workerJob)==0)exit("沒有工作任務(wù)\n");

foreach($this->workerJob as $job){

$pid = pcntl_fork();

if ($pid<0){

exit("工作進(jìn)程創(chuàng)建失敗\n");

}else if ($pid==0){

/***************子進(jìn)程工作范圍**********************/

//給子進(jìn)程安裝信號處理程序

$this->workerInstallSignal();

$start_time = time();

while (1){

pcntl_signal_dispatch();

if ((time()-$start_time)>=$job->job_run_time){

break;

}

$job->run(posix_getpid());

}

exit(0);//子進(jìn)程運(yùn)行完成后退出

/***************子進(jìn)程工作范圍**********************/

}else{

$this->workerPids[$pid] = $job;

}

}

}

function workerInstallSignal()

{

pcntl_signal(SIGUSR1,[__CLASS__,'workerHandleSignal'],false);

}

function workerHandleSignal($signal)

{

switch ($signal){

case SIGUSR1:

$state = "worker pid=".posix_getpid()."接受了父進(jìn)程發(fā)來的自定義信號\n";

file_put_contents($this->state_file,$state,FILE_APPEND);

break;

}

}

function installSignal()

{

pcntl_signal(SIGINT,[__CLASS__,'handleMasterSignal'],false);

pcntl_signal(SIGTERM,[__CLASS__,'handleMasterSignal'],false);

pcntl_signal(SIGUSR1,[__CLASS__,'handleMasterSignal'],false);

}

function handleMasterSignal($signal)

{

switch ($signal){

case SIGINT:

//主進(jìn)程接受到中斷信號ctrl+c

foreach ($this->workerPids as $pid=>$worker){

posix_kill($pid,SIGINT);//向所有的子進(jìn)程發(fā)出

}

exit("服務(wù)平滑停止\n");

break;

case SIGTERM://ctrl+z

foreach ($this->workerPids as $pid=>$worker){

posix_kill($pid,SIGKILL);//向所有的子進(jìn)程發(fā)出

}

exit("服務(wù)停止\n");

break;

case SIGUSR1://用戶自定義信號

if (file_exists($this->state_file)){

unlink($this->state_file);

}

foreach ($this->workerPids as $pid=>$worker){

posix_kill($pid,SIGUSR1);

}

$state = "master pid\n".$this->getMasterPid()."\n";

while(!file_exists($this->state_file)){

sleep(1);

}

$state.= file_get_contents($this->state_file);

echo $state.PHP_EOL;

break;

}

}

}

/**\

* Created by PhpStorm.\ * User: 1655664358@qq.com

* Date: 2018/3/26\ * Time: 14:37\ */\namespace Chen\Worker;

class Job

{

public $job_run_time = 3600;

function run($pid)

{\sleep(3);

echo "worker pid = $pid job 沒事干,就在這里job\n";

}

}

/**

* Created by PhpStorm.\ * User: 1655664358@qq.com

* Date: 2018/3/26\ * Time: 14:37\ */\namespace Chen\Worker;

class Talk

{

public $job_run_time = 3600;

function run($pid)

{\sleep(3);

echo "worker pid = $pid job 沒事干,就在這里talk\n";

}

}

/**

* Created by PhpStorm.\ * User: 1655664358@qq.com

* Date: 2018/3/26\ * Time: 15:45\ */

require_once 'vendor/autoload.php';

$process = new \Chen\Worker\Server();

$process->workerJob = [new \Chen\Worker\Talk(),new \Chen\Worker\Job()];

$process->run();

本作品采用《CC 協(xié)議》,轉(zhuǎn)載必須注明作者和本文鏈接

只會php crud的渣渣

總結(jié)

以上是生活随笔為你收集整理的php 多进程 常驻内存,PHP 多进程与信号中断实现多任务常驻内存管理 [Master/Worker 模型]...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。