Es gibt ziemlich viele "niedrigere" Details.
Stellen Sie sich zunächst vor, der Kernel verfügt über eine Liste von Prozessen. Einige dieser Prozesse werden zu einem bestimmten Zeitpunkt ausgeführt, andere nicht. Der Kernel lässt jedem laufenden Prozess einen Teil der CPU-Zeit zu, unterbricht ihn dann und wechselt zum nächsten. Wenn es keine ausführbaren Prozesse gibt, gibt der Kernel wahrscheinlich eine Anweisung wie HLT an die CPU aus, die die CPU anhält, bis ein Hardware-Interrupt auftritt.
Irgendwo auf dem Server befindet sich ein Systemaufruf mit der Aufschrift "Gib mir etwas zu tun". Es gibt zwei Kategorien von Möglichkeiten, wie dies durchgeführt werden kann. Im Fall von Apache ruft es accepteinen Socket auf, den Apache zuvor geöffnet hat, und überwacht wahrscheinlich Port 80. Der Kernel verwaltet eine Warteschlange mit Verbindungsversuchen und fügt diese Warteschlange jedes Mal hinzu, wenn ein TCP-SYN empfangen wird. Wie der Kernel weiß, dass eine TCP-SYN empfangen wurde, hängt vom Gerätetreiber ab. Bei vielen Netzwerkkarten liegt wahrscheinlich ein Hardware-Interrupt vor, wenn Netzwerkdaten empfangen werden.
acceptbittet den Kernel, mir den nächsten Verbindungsaufbau zurückzugeben. Wenn die Warteschlange nicht leer war, acceptkehrt sie sofort zurück. Wenn die Warteschlange leer ist, wird der Prozess (Apache) aus der Liste der ausgeführten Prozesse entfernt. Wenn später eine Verbindung hergestellt wird, wird der Vorgang fortgesetzt. Dies wird als "Blockieren" bezeichnet, da der aufrufende Prozess accept()wie eine Funktion aussieht, die erst zurückkehrt, wenn ein Ergebnis vorliegt, das in einiger Zeit vorliegen könnte. Während dieser Zeit kann der Prozess nichts anderes tun.
Nach der acceptRückkehr weiß Apache, dass jemand versucht, eine Verbindung herzustellen. Anschließend wird fork aufgerufen , um den Apache-Prozess in zwei identische Prozesse aufzuteilen. Einer dieser Prozesse verarbeitet die HTTP-Anforderung, der andere ruft accepterneut auf, um die nächste Verbindung herzustellen. Daher gibt es immer einen Master-Prozess, der nur acceptUnterprozesse aufruft und erzeugt, und dann gibt es für jede Anforderung einen Unterprozess.
Dies ist eine Vereinfachung: Es ist möglich, dies mit Threads anstelle von Prozessen zu tun, und es ist auch möglich, dies forkvorher zu tun, damit ein Arbeitsprozess bereit ist, wenn eine Anforderung empfangen wird, wodurch der Startaufwand verringert wird. Abhängig davon, wie Apache konfiguriert ist, kann es eines dieser Dinge tun.
Dies ist die erste allgemeine Kategorie, und sie wird als E / A- Blockierung bezeichnet, da Systemaufrufe wie acceptund readund write, die auf Sockets ausgeführt werden, den Prozess anhalten, bis sie etwas zurückgeben können.
Der andere breite Weg, dies zu tun, wird als nicht blockierende oder ereignisbasierte oder asynchrone E / A bezeichnet . Dies wird mit Systemaufrufen wie selectoder implementiert epoll. Diese tun jeweils dasselbe: Sie geben ihnen eine Liste von Sockets (oder allgemein Dateideskriptoren) und was Sie damit tun möchten, und der Kernel blockiert, bis er bereit ist, eines dieser Dinge zu tun.
Bei diesem Modell können Sie dem Kernel (mit epoll) mitteilen : "Sagen Sie mir, wenn eine neue Verbindung an Port 80 besteht oder wenn neue Daten auf einer dieser 9471 anderen Verbindungen gelesen werden sollen, die ich geöffnet habe". epollblockiert, bis eines dieser Dinge fertig ist, dann machst du es. Dann wiederholst du. Systemaufrufe mögen acceptund readund werden writeniemals blockiert, zum Teil, weil Sie bei jedem Aufruf epollnur erfahren haben, dass sie bereit sind, sodass es keinen Grund zum Blockieren gibt, und weil Sie beim Öffnen des Sockets oder der von Ihnen angegebenen Datei angeben, dass Sie sie möchten Im nicht blockierenden Modus schlagen diese Anrufe fehl, EWOULDBLOCKanstatt zu blockieren.
Der Vorteil dieses Modells ist, dass Sie nur einen Prozess benötigen. Dies bedeutet, dass Sie nicht für jede Anforderung eine Stapel- und Kernelstruktur zuweisen müssen. Nginx und HAProxy verwenden dieses Modell und es ist ein großer Grund, warum sie mit so viel mehr Verbindungen als Apache auf ähnlicher Hardware umgehen können.