Heim > Artikel > PHP-Framework > PHP-Multiprozess- und Signal-Interrupt realisieren eine Multitasking-Residentspeicherverwaltung [Master/Worker-Modell]
Dieser Artikel basiert auf Multiprozesstests, die mit der Erweiterung pcntl durchgeführt wurden.
Prozessplanungsstrategie
Das Betriebssystem ist für die Planung von übergeordneten und untergeordneten Prozessen verantwortlich. Ob der untergeordnete Prozess oder der übergeordnete Prozess zuerst geplant wird, wird durch das bestimmt Der Planungsalgorithmus des Systems kann natürlich zuerst geplant werden, indem dem Prozess eine Verzögerung hinzugefügt oder die Prozessrecyclingfunktion aufgerufen wird. Der Zweck des Prozessrecyclings besteht darin, den belegten Speicherplatz freizugeben Der Prozess wird erstellt, um zu verhindern, dass er zu einem Zombie-Prozess wird.
Signal:
Signal wird als Soft-Interrupt-System oder Soft-Interrupt bezeichnet und hat die Funktion, asynchrone Ereignisbenachrichtigungen an den Prozess zu senden.
Signalnummer: [Der Quellcode basiert auf den Signalen SIGINT, SIGTERM, SIGUSR1. Bitte überprüfen Sie die Bedeutung des Kill-Befehls, der nicht beschrieben wird]
Linux unterstützt 64, von denen die Hälfte der Echtzeitsignale Nicht-Echtzeitsignale sind. Diese Signale haben ihre eigenen Nummern und entsprechenden ganzzahligen Werte. Informationen zur Bedeutung der Nummer jedes Signals finden Sie im entsprechenden Linux-Handbuch [Man-Handbuch, um es herauszufinden]
Signalverarbeitungsfunktion:
Signale sind im Allgemeinen Einige sind an die entsprechenden Funktionen gebunden und verfügen über Standardaktionen wie SIGKILL, SIGTERM und SIGINT. Natürlich können wir sie überschreiben, indem wir sie über pcntl_signal überschreiben.
Das Konzept des Signals: Es ist dasselbe wie ein Hardware-Interrupt. Bitte lesen Sie meine vorherigen Artikel oder überprüfen Sie das Chip-Hardware-Interrupt-Prinzip.
Signalübertragung:
Kill-Signal-Nummer-Prozess oder das Interrupt-Signal des Schlüsselprodukts oder Sie können posix_kill und andere Funktionen im Quellcode verwenden.
Prozesse sind voneinander isoliert und verfügen zusätzlich zu einem gemeinsamen Textbereich über einen eigenen ausführbaren Code. Wenn der Prozess ausgeführt wird, belegt er CPU-Ressourcen Andere Prozesse haben keinen Zugriff darauf. Zu diesem Zeitpunkt befinden sich andere Prozesse in einem blockierten Zustand [wie der zuvor erwähnte TCP-Dienst]. oder beenden, die Prozessfunktion verlassen oder auf sie stoßen Es wird beendet, wenn ein Signalereignis auftritt] Geben Sie Berechtigungen auf und geben Sie Speicher frei, und andere Prozesse haben die Möglichkeit, ausgeführt zu werden.
Der Prozess verfügt über einen eigenen Prozessdeskriptor, dessen Prozessnummer PID häufiger verwendet wird. Wenn der Prozess ausgeführt wird, wird die entsprechende Prozessdatei unter dem System /proc/PID generiert, und der Benutzer kann dies tun schau es Dir selbst an.
Jeder Prozess hat seine eigene Prozessgruppe [Ansammlung von Prozessen]. Eine Sitzung wird durch einen Prozess erstellt, und dieser Prozess kann nicht der Gruppenleiterprozess sein Der Prozess wird zum ersten Prozess der Sitzung und zum Prozessleiter der Prozessgruppe. Gleichzeitig verlässt er das Kontrollterminal. Auch wenn der vorherige Prozess an das Kontrollterminal gebunden ist, wird er [Erstellung des Daemon-Prozesses] verlassen ].
Dateibeschreibungs-Berechtigungsmaske [Berechtigungsmaskenwort]:
umask () Sie können diesen Befehl unter Linux ausführen, dann die Datei erstellen und ihre Berechtigungen anzeigen [ Wenn Sie Wenn Sie nach dem Laufen nichts finden, bedeutet das, dass Sie nicht genug trainiert haben^_^]
<?php /** * 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("服务未运行\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进程失败\n"); }else if ($pid >0){ exit(0); }else{ umask(0); $sid = posix_setsid(); if ($sid<0){ exit("创建会话失败\n"); } $pid = pcntl_fork(); if ($pid<0){ exit("进程创建失败\n"); }else if ($pid >0){ exit(0); } //可以关闭标准输入输出错误文件描述符【守护进程不需要】 } } function worker() { if (count($this->workerJob)==0)exit("没有工作任务\n"); foreach($this->workerJob as $job){ $pid = pcntl_fork(); if ($pid<0){ exit("工作进程创建失败\n"); }else if ($pid==0){ /***************子进程工作范围**********************/ //给子进程安装信号处理程序 $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);//子进程运行完成后退出 /***************子进程工作范围**********************/ }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()."接受了父进程发来的自定义信号\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: //主进程接受到中断信号ctrl+c foreach ($this->workerPids as $pid=>$worker){ posix_kill($pid,SIGINT);//向所有的子进程发出 } exit("服务平滑停止\n"); break; case SIGTERM://ctrl+z foreach ($this->workerPids as $pid=>$worker){ posix_kill($pid,SIGKILL);//向所有的子进程发出 } exit("服务停止\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; } } } <?php /**\ * 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"; } } <?php /** * 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"; } } <?php /** * 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();
Weitere technische Artikel zu Laravel finden Sie unter Laravel Framework Spalte „Erste Schritte Tutorial“ zum Lernen!
Das obige ist der detaillierte Inhalt vonPHP-Multiprozess- und Signal-Interrupt realisieren eine Multitasking-Residentspeicherverwaltung [Master/Worker-Modell]. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!