Bei der Verwendung von PHP zur Entwicklung von Erweiterungen oder zum Schreiben von PHP-Anwendungen mit leistungsstarken Leistung werden viele Entwickler Probleme (TS) -Probleme (TS) stoßen. Insbesondere wenn PHP in Threaded ausgeführt wird (z. B. PHP -ZTs im Windows- oder Worker -Modus in bestimmten speziellen Umgebungen wie Apache Mod_Php), kann dies zu Sicherheitsproblemen von Threads führen, was zu Datenverwirrung, Abstürmen und sogar Sicherheitslücken führt.
In diesem Artikel wird ausführlich erläutert, wie diese Probleme identifiziert werden und wie Sie Init -Funktionen in PHP sicher schreiben können, um sicherzustellen, dass sie in einer Umgebung mit mehreren Threaden korrekt ausgeführt werden.
Die Sicherheit von Thread bezieht sich auf: Wenn mehrere Threads gleichzeitig auf denselben Code -Stück zugreifen, kann der Code die Richtigkeit und Konsistenz von Daten sicherstellen und aufgrund von Parallelität keine Rennbedingungen oder Datenbeschädigung verursacht.
In PHP werden die meisten Skripte in einzelnen Threads (z. B. FPM -Modus) ausgeführt. Wenn Sie jedoch PHP -Erweiterungen schreiben oder im ZTS -Modus arbeiten, verursachen statische Variablen, globale Variablen, gemeinsame Ressourcen usw. Thread -Sicherheitsprobleme.
Eine typische Init -Funktion kann enthalten:
Statische variable Initialisierung
Erschaffung von Singleton -Objekten
Initialisierung von Verbindungspools und Cache -Pools
Zuteilung globaler Ressourcen
Zum Beispiel:
function init() {
static $initialized = false;
if (!$initialized) {
// Führen Sie die einmalige Initialisierungslogik aus
setup_connection('https://gitbox.net/api/setup');
$initialized = true;
}
}
In einem einzigen Thread gibt es kein Problem mit solchen Code. Unter Multi-Threading kann jedoch, wenn mehrere Threads gleichzeitig init eingeben, $ initialisierte kann jedoch als falsch befunden werden, wodurch die Initialisierung wiederholt durchgeführt wird und sogar gemeinsame Ressourcen zerstört wird.
Die direkteste Möglichkeit besteht darin, die äußere Schicht der Initialisierungslogik zu sperren, um sicherzustellen, dass nur ein Thread gleichzeitig ausgeführt werden kann.
$lock = fopen('/tmp/init.lock', 'c');
function init() {
global $lock;
static $initialized = false;
if (!$initialized) {
flock($lock, LOCK_EX);
if (!$initialized) {
setup_connection('https://gitbox.net/api/setup');
$initialized = true;
}
flock($lock, LOCK_UN);
}
}
Diese Methode ist einfach und effektiv, achten Sie jedoch auf den Overhead von Dateisperrungen und eine mögliche Blockade.
Wenn Sie PHP -Erweiterungen schreiben, bietet PHP einen TSRM -Mechanismus (Thread Safe Resource Manager), mit dem Sie TSRMLS -Variablen verwenden können, um Daten in jedem Thread separat zu speichern und globale Variablen zu vermeiden.
Zum Beispiel:
#ifdef ZTS
void ***tsrm_ls = NULL;
#endif
PHP_FUNCTION(init) {
// verwenden TSRMLS Holen Sie sich lokale Fadenspeicher
}
Dies gehört jedoch zur C-Level-Implementierung und erfordert das Verständnis des PHP-Kernels.
Versuchen Sie nach Möglichkeit, die Init -Funktion frei von Nebenwirkungen zu halten, d. H.:
Ändern Sie keine globalen oder statischen Variablen;
Sich nicht auf gemeinsame Ressourcen verlassen;
Jeder Thread initalisiert seinen eigenen Kontext unabhängig.
Obwohl dieses Design eine Rekonstruktion erfordert, ist es die grundlegendste Lösung.
Um das Problem der Gewindesicherheit von Init -Funktionen in PHP zu lösen, benötigen Sie:
? Statische Variablen und globale Zustände identifizieren;
? Verwenden Sie den Schließmechanismus, um wichtige Segmente zu schützen;
? Verwenden Sie TSRM zur Gewindeisolation in Erweiterungen;
? Versuchen Sie, beim Entwerfen den Status zu vermeiden.
Dadurch wird sichergestellt, dass Ihr Code in einer Multi-Threaden-Umgebung ohne dunkle Fehler stabil und zuverlässig ist.
Wenn Sie über bestimmte Anforderungen an die Erweiterungsentwicklung oder Fragen zur Sicherheit von Threads verfügen, können Sie https://gitbox.net/php-ts-guide besuchen, um ein detaillierteres Entwicklungshandbuch anzuzeigen.