Próbuję zrozumieć niższe szczegóły dotyczące serwerów sieciowych. Zastanawiam się, czy serwer, powiedzmy Apache, ciągle odpytuje o nowe żądania, czy też działa przez jakiś rodzaj systemu przerwań. Jeśli jest to przerwanie, co powoduje przerwanie, czy to sterownik karty sieciowej?
networking
webserver
embedded
użytkownik2202911
źródło
źródło
Odpowiedzi:
Krótka odpowiedź brzmi: jakiś system przerwań. Zasadniczo używają blokujących We / Wy, co oznacza, że śpią (blokują) podczas oczekiwania na nowe dane.
Serwer tworzy gniazdo nasłuchujące, a następnie blokuje się podczas oczekiwania na nowe połączenia. W tym czasie jądro przełącza proces w przerywany stan uśpienia i uruchamia inne procesy. To ważna kwestia: ciągłe sondowanie procesu zmarnowałoby procesor. Jądro jest w stanie efektywniej wykorzystywać zasoby systemowe, blokując proces, dopóki nie będzie pracy.
Gdy nowe dane docierają do sieci, karta sieciowa wydaje przerwanie.
Widząc, że nastąpiła przerwa w karcie sieciowej, jądro, poprzez sterownik karty sieciowej, odczytuje nowe dane z karty sieciowej i zapisuje je w pamięci. (Musi to zostać wykonane szybko i zwykle jest obsługiwane w module obsługi przerwań.)
Jądro przetwarza nowo przybyłe dane i kojarzy je z gniazdem. Proces blokujący na tym gnieździe zostanie oznaczony jako uruchamialny, co oznacza, że można go teraz uruchomić. Nie musi działać natychmiast (jądro może zdecydować o uruchomieniu innych procesów).
W wolnym czasie jądro obudzi zablokowany proces serwera WWW. (Ponieważ można go teraz uruchomić).
Proces serwera kontynuuje działanie, jakby nie upłynęło czasu. Blokuje wywołanie systemowe i zwraca wszelkie nowe dane. Następnie ... przejdź do kroku 1.
źródło
accept
. Są (na szczęście, albo całkowicie by to było do kitu) niezależnymi, asynchronicznie działającymi zadaniami. Gdy nadchodzą połączenia, są one umieszczane w kolejce, z której sąaccept
pobierane. Tylko jeśli nie ma, blokuje.Istnieje wiele „niższych” szczegółów.
Po pierwsze, rozważ, że jądro ma listę procesów, aw dowolnym momencie niektóre z nich są uruchomione, a niektóre nie. Jądro pozwala każdemu działającemu procesowi na wycinek czasu procesora, a następnie przerywa go i przechodzi do następnego. Jeśli nie ma żadnych uruchomialnych procesów, jądro prawdopodobnie wyda instrukcję taką jak HLT do CPU, która zawiesza procesor, dopóki nie nastąpi przerwanie sprzętowe.
Gdzieś na serwerze jest wywołanie systemowe, które mówi „daj mi coś do zrobienia”. Można to zrobić na dwie szerokie kategorie. W przypadku Apache wywołuje
accept
gniazdo, które Apache wcześniej otworzył, prawdopodobnie nasłuchując na porcie 80. Jądro utrzymuje kolejkę prób połączenia i dodaje do tej kolejki za każdym razem, gdy odbierany jest TCP SYN . To, jak jądro wie, że odebrano TCP SYN, zależy od sterownika urządzenia; w przypadku wielu kart sieciowych prawdopodobnie nastąpiło przerwanie sprzętowe podczas odbierania danych sieciowych.accept
prosi jądro o zwrócenie mi następnej inicjacji połączenia. Jeśli kolejka nie była pusta,accept
natychmiast wraca. Jeśli kolejka jest pusta, proces (Apache) jest usuwany z listy uruchomionych procesów. Gdy połączenie zostanie później zainicjowane, proces zostanie wznowiony. Nazywa się to „blokowaniem”, ponieważ wywołujący go procesaccept()
wygląda jak funkcja, która nie powraca, dopóki nie uzyska wyniku, co może potrwać jakiś czas. W tym czasie proces nie może zrobić nic więcej.Po
accept
powrocie Apache wie, że ktoś próbuje nawiązać połączenie. Następnie wywołuje funkcję fork, aby podzielić proces Apache na dwa identyczne procesy. Jeden z tych procesów kontynuuje przetwarzanie żądania HTTP, a drugi wywołujeaccept
ponownie, aby uzyskać następne połączenie. Dlatego zawsze istnieje proces główny, który nie robi nic poza wywoływaniemaccept
i spawaniem podprocesów, a następnie jest jeden podproces dla każdego żądania.Jest to uproszczenie: można to zrobić za pomocą wątków zamiast procesów, a także z
fork
wyprzedzeniem, aby proces roboczy był gotowy do działania po otrzymaniu żądania, zmniejszając w ten sposób narzut związany z uruchamianiem. W zależności od konfiguracji Apache może wykonać jedną z tych czynności.To pierwsza szeroka kategoria, jak to zrobić, i to się nazywa blokowanie IO ponieważ system nazywa jak
accept
iread
iwrite
które działają na gniazdach zawiesi proces, dopóki mają coś do powrotu.Innym szerokim sposobem na to jest nazywanie nieblokującego lub opartego na zdarzeniach lub asynchronicznego We / Wy . Jest to realizowane za pomocą wywołań systemowych, takich jak
select
lubepoll
. Każdy z nich robi to samo: dajesz im listę gniazd (lub ogólnie deskryptorów plików) i co chcesz z nimi zrobić, a jądro blokuje się, dopóki nie będzie gotowe do zrobienia jednej z tych rzeczy.Za pomocą tego modelu możesz powiedzieć kernelowi (za pomocą
epoll
): „Powiedz mi, kiedy pojawi się nowe połączenie na porcie 80 lub nowe dane do odczytania na każdym z 9471 innych połączeń, które mam otwarte”.epoll
blokuje, dopóki jedna z tych rzeczy nie będzie gotowa, to robicie to. Potem powtarzasz. Wywołań systemowych jakaccept
iread
iwrite
nigdy blok, po części dlatego, kiedy ich nazwać,epoll
po prostu powiedział, że są gotowe, więc nie byłoby powodu do blokowania, a także dlatego, że po otwarciu gniazda lub plik określić, że chcesz je w trybie nieblokującym, więc te połączenia zakończą się niepowodzeniemEWOULDBLOCK
zamiast blokowania.Zaletą tego modelu jest to, że potrzebujesz tylko jednego procesu. Oznacza to, że nie musisz przydzielać stosu i struktur jądra dla każdego żądania. Nginx i HAProxy używają tego modelu i jest to duży powód, dla którego mogą one obsługiwać o wiele więcej połączeń niż Apache na podobnym sprzęcie.
źródło