Heim  >  Artikel  >  Backend-Entwicklung  >  Ein umfassender Überblick über die PHP-Prozesssignalverarbeitung in einem Artikel

Ein umfassender Überblick über die PHP-Prozesssignalverarbeitung in einem Artikel

藏色散人
藏色散人nach vorne
2023-04-01 07:30:031962Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über PHP und stellt vor allem die PHP-Prozesssignalverarbeitung im Detail vor. Ich hoffe, dass er für alle hilfreich ist.

Ein umfassender Überblick über die PHP-Prozesssignalverarbeitung in einem Artikel

Hintergrund

Vor zwei Wochen hat mir mein Chef die Aufgabe zugewiesen, ein Signalüberwachungspaket zu schreiben. Da die Projekte unseres Unternehmens in Containern laufen, müssen sie jedes Mal, wenn sie online gehen, das Image neu verpacken und dann starten. Vor dem Neupacken sendet Dokcer zunächst ein Signal an den Container und wartet dann eine Zeitspanne (Standard 10 Sekunden), bevor es ein SIGKILL-Signal sendet, um den Container zu beenden Die Aufgabe des Prozesses besteht darin, Nachrichten in der Warteschlange kontinuierlich zu verbrauchen. Angenommen, Sie möchten jetzt online gehen und müssen den Container herunterfahren. Docker sendet ein Signal an den im Container ausgeführten Prozess und teilt ihm mit, dass ich Sie in 10 Sekunden herunterfahren werde Der Prozess wurde gerade aus der Warteschlange genommen, bevor die nachfolgende Logik innerhalb von 1 Sekunde ausgeführt wurde. Zu diesem Zeitpunkt geht die Nachricht verloren und es können fehlerhafte Daten generiert werden Der Hintergrund dieser Aufgabe, die durch das Signal überwacht werden muss, entscheidet, was als nächstes zu tun ist. Wenn in der oben genannten Situation der residente Prozess das von Docker gesendete Shutdown-Signal empfängt, kann der Prozess blockiert werden und in den Ruhezustand versetzt werden, bis der Container beendet wird. OK, nachdem wir den Hintergrund geklärt haben, stellen wir die Signale in PHP vor (ich werde später einen Artikel darüber zusammenstellen, wie man dieses Paket schreibt, und das Paket auf https://packagist.org/ veröffentlichen, damit es von Freunden verwendet werden kann, die es benötigen) [ Empfohlenes Lernen:

PHP-Video-Tutorial

1. Welche Signale gibt es im Linux-Betriebssystem

1. Eine kurze Einführung in Signale

Signale sind Benachrichtigungsmechanismen für Prozesse, wenn Ereignisse auftreten, manchmal auch „Software-Interrupt“ genannt. Ein Prozess kann beispielsweise ein Signal an einen anderen Prozess senden, wenn er endet, sendet er ein SIGCHLD (Signal Nr. 17) an den übergeordneten Prozess, um den übergeordneten Prozess zu benachrichtigen. Daher werden Signale manchmal auch als Schnittstelle verwendet. Prozesskommunikationsmechanismus. In Linux-Systemen verwenden wir normalerweise kill -9 XXPID, um einen Prozess zu beenden. Tatsächlich besteht der Kern dieses Befehls darin, SIGKILL (Signal Nr. 9) an einen Prozess zu senden Strg + C-Tastenkombination zum Beenden. Die Essenz dieser Tastenkombination besteht darin, SIGINT (Signal Nr. 2) an den aktuellen Prozess zu senden, und das Standardverhalten des Prozesses beim Empfang dieses Signals besteht darin, den Vorgang zu beenden

2. Häufige Signale

Die folgenden Signale können zur Überprüfung verwendet werden. Hier sind einige wichtige und häufig verwendete Signale🔜 normal Wird normalerweise und am Ende ausgegeben, normalerweise, wenn der Steuerungsprozess des Terminals endet, und benachrichtigt jeden Job in derselben Sitzung. Zu diesem Zeitpunkt sind sie nicht mehr mit dem Steuerungsterminal verbundenSIGQUITSIGFPESIGKILLBeenden Sie den Prozess (Timer läuft ab)SIGALRM-Uhrzeitsignal, das die tatsächliche Zeit oder den Uhrzeitalarm berechnet. Die Funktion verwendet dieses Signal SIGTERM15, um den Prozess zu beenden (Software-Beendigungssignal) SIGTERM Programmende (Beenden, Signal, im Gegensatz zu SIGKILL kann dieses Signal blockiert und verarbeitet werden. Es wird normalerweise verwendet, um das Programm selbst anzufordern. Beenden Sie es normal. Der Shell-Befehl kill generiert dieses Signal standardmäßigSIGCHLD17Ignorieren Sie das Signal (benachrichtigen Sie den übergeordneten Prozess, wenn der untergeordnete Prozess stoppt oder beendet wird)SIGCHLD Wenn der untergeordnete Prozess endet, empfängt der übergeordnete Prozess dieses Signal. SIGVTALRM26
SIGQUIT 2 Beenden den Prozess (den Prozess unterbrechen) Programmbeendigung (Unterbrechung, Signal, wird ausgegeben, wenn der Benutzer INTR-Zeichen eingibt (normalerweise Strg-C,
3 Erstellen Sie eine CORE-Datei, um den Prozess zu beenden, und generieren Sie Eine CORE-Datei Prozess und Generieren einer CORE-Datei SIGQUIT ähnelt SIGINT, wird jedoch durch das QUIT-Zeichen gesteuert (normalerweise Strg-,). Der Prozess generiert beim Beenden aufgrund des Empfangs von SIGQUIT eine Kerndatei. Es ähnelt einem Programmfehlersignal
8 CORE-Datei erstellen (Gleitkomma-Ausnahme) SIGFPE wird ausgegeben, wenn ein schwerwiegender Rechenoperationsfehler auftritt, sondern auch alle anderen arithmetischen Fehler wie Überlauf und Division durch 0
9 Beenden Sie den Prozess (Töten Sie den Prozess) SIGKILL wird verwendet, um die Ausführung des Programms sofort zu beenden. Dieses Signal kann nicht blockiert oder verarbeitet werden und ignoriert

Beenden Sie den Prozess (der virtuelle Timer läuft ab). )
SIGVTALRM virtuelles Taktsignal Ähnlich wie SIGALRM, berechnet jedoch die vom Prozess belegte CPU-Zeit ist bereit und Ein-/Ausgabevorgänge können beginnen
2. Funktionen für die Signalverarbeitung in PHP Erweiterung)

Das Folgende ist eine detaillierte Einführung in mehrere Methoden, die ich in dieser Aufgabe verwendet habe:declare

Die Declare-Struktur wird verwendet, um die Ausführungsanweisungen eines Codeabschnitts festzulegen. Die Syntax von „declare“ ähnelt anderen Flusskontrollstrukturen. Mit dem Direktiventeil können Sie das Verhalten des „declare“-Codesegments festlegen. Derzeit werden nur zwei Befehle erkannt: Ticks und Encoding

. Der Anweisungsteil im Deklarationscodesegment wird ausgeführt – wie er ausgeführt wird und welche Nebenwirkungen während der Ausführung auftreten, hängt von den in der Direktive festgelegten Anweisungen ab.

TicksTick (Taktzyklus) ist ein Interpreter im Deklarationscode segment Der Wert des Ereignisses N, das jedes Mal auftritt, wenn N zeitgesteuerte Low-Level-Anweisungen ausgeführt werden, wird mit ticks=N im Direktiventeil der Deklaration angegeben. Nicht alle Anweisungen können zeitlich festgelegt werden. Im Allgemeinen sind sowohl bedingte Ausdrücke

als auch

Parameterausdrücke

nicht zeitgesteuert. Die Ereignisse, die in jedem Tick erscheinen, werden durch register_tick_function() angegeben. Beachten Sie, dass in jedem Tick mehrere Ereignisse erscheinen können. Ausführlichere Informationen finden Sie in der offiziellen Dokumentation: https://www.php.net/manual/zh/control-structures.declare.php

declare (directive)
    statement

pcntl_signal

pcntl_signal, installieren Sie einen Signalprozessor

<?php
declare(ticks=1);//每执行一条时,触发register_tick_function()注册的函数
$a=1;//在注册之前,不算
function test(){//定义一个函数
    echo "执行\n";
}
register_tick_function(&#39;test&#39;);//该条注册函数会被当成低级语句被执行
for($i=0;$i<=2;$i++){//for算一条低级语句
    $i=$i;//赋值算一条
}
输出:六个“执行”
Die Funktion pcntl_signal() installiert einen neuen Signalprozessor für das durch signo angegebene Signal. und der erste Parameter ist die Prozess-ID. Die beiden Parameter sind das Signal, das Sie senden möchten.

pcntl_signal_dispatch Der von jedem Wartesignal über pcntl_signal()

pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls = true ] ) : bool
pcntl_async_signals()

Asynchrone Signalverarbeitung installierte Prozessor wird verwendet, um eine asynchrone Signalverarbeitung ohne Ticks zu ermöglichen (was viel zusätzlichen Overhead mit sich bringt). (PHP>=7.1)

declare(ticks = 1);
pcntl_signal(SIGINT,function(){
    echo "你按了Ctrl+C".PHP_EOL;
});
while(1){
    sleep(1);//死循环运行低级语句
}
输出:当按Ctrl+C之后,会输出“你按了Ctrl+C”

3. Wie man mit Semaphoren in PHP umgeht

Wir wissen vorher, dass wir das Signal durch die Kombination von „declare(ticks=1)“ und „pcntl_signal“ überwachen können, d. h. Jede PHP-Anweisung auf niedriger Ebene prüft, ob im aktuellen Prozess nicht verarbeitete Signale vorhanden sind, was tatsächlich sehr leistungsintensiv ist.

Das Implementierungsprinzip von pcntl_signal besteht darin, das Signal nach dem Auslösen des Signals zunächst einer Warteschlange hinzuzufügen. Überprüfen Sie dann kontinuierlich, ob in der Ticks-Callback-Funktion ein Signal vorhanden ist. Führen Sie die in PHP angegebene Callback-Funktion aus. Wenn nicht, verlassen Sie die Funktion.

posix_kill ( int $pid , int $sig ) : bool

Nach PHP5.3 gibt es die Funktion pcntl_signal_dispatch. Zu diesem Zeitpunkt ist die Deklaration nicht mehr erforderlich. Sie müssen nur die Funktion in die Schleife einfügen, um das Signal aufzurufen und Folgendes zu übergeben:

a.php
<?php
declare(ticks = 1);
echo getmypid();//获取当前进程id
pcntl_signal(SIGINT,function(){
    echo "你给我发了SIGINT信号";
});
while(1){
    sleep(1);
}

b.php
<?php
posix_kill(执行1.php时输出的进程id, SIGINT);
Jeder weiß, dass PHPs ticks=1 bedeutet, dass diese Funktion jedes Mal zurückgerufen wird, wenn eine Zeile von PHP-Code wird ausgeführt. Tatsächlich wird die meiste Zeit kein Signal generiert, aber die Ticks-Funktion wird immer ausgeführt. Wenn ein Serverprogramm in einer Sekunde 1.000 Anfragen empfängt, führt jede Anfrage durchschnittlich 1.000 Zeilen PHP-Code aus. Dann bringt PHPs pcntl_signal zusätzliche 1000 * 1000, also 1 Million leere Funktionsaufrufe. Dadurch werden viele CPU-Ressourcen verschwendet. Ein besserer Ansatz besteht darin, Häkchen zu entfernen und stattdessen pcntl_signal_dispatch zu verwenden, um das Signal selbst in der Codeschleife zu verarbeiten. Implementierung der Funktion pcntl_signal_dispatch:
pcntl_signal_dispatch ( void ) : bool
Aber das Ekelhafte an der obigen Funktion ist, dass sie in eine Endlosschleife gestellt werden muss. Nach PHP7.1 kam eine Funktion heraus, die den Empfang und die Verarbeitung asynchroner Signale abschließt: pcntl_async_signals
<?php
echo "安装信号处理器...\n";
pcntl_signal(SIGHUP,  function($signo) {
     echo "信号处理器被调用\n";
});
echo "为自己生成SIGHUP信号...\n";
posix_kill(posix_getpid(), SIGHUP);
echo "分发...\n";
pcntl_signal_dispatch();
echo "完成\n";
?>

输出:
安装信号处理器...
为自己生成SIGHUP信号...
分发...
信号处理器被调用
完成
Durch die Methode pcntl_async_signals ist es nicht erforderlich, eine Endlosschleife zu schreiben.

监听信号的包:

https://github.com/Rain-Life/monitorSignal

Das obige ist der detaillierte Inhalt vonEin umfassender Überblick über die PHP-Prozesssignalverarbeitung in einem Artikel. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen