2010-03-30 6 views
10

Ich habe gelesen, was passiert, nachdem Pakete von NICs erfasst wurden, und je mehr ich lese, desto mehr bin ich verwirrt.Was passiert, nachdem ein Paket erfasst wurde?

Erstens, ich habe gelesen, dass traditionell, nachdem ein Paket von der NIC erfasst wurde, wird es in einen Speicherblock im Kernelraum kopiert, dann in den Benutzerraum für jede Anwendung, die dann mit den Paketdaten arbeitet . Dann lese ich über DMA, wo die NIC das Paket direkt in den Speicher kopiert und die CPU umgeht. Also ist der NIC -> Kernel-Speicher -> User Space Memory Flow noch gültig? Verwenden auch die meisten NICs (z. B. Myricom) DMA, um die Paketerfassungsraten zu verbessern?

Zweitens funktioniert RSS (Receive Side Scaling) in Windows- und Linux-Systemen ähnlich? Ich kann nur detaillierte Erklärungen finden, wie RSS in MSDN-Artikeln funktioniert, wo sie darüber sprechen, wie RSS (und MSI-X) unter Windows Server 2008 funktioniert. Aber das gleiche Konzept von RSS und MSI-X sollte immer noch für Linux-Systeme gelten ?

Vielen Dank.

Grüße, Rayne

+1

Google für Zero Copy Networking ... sehr wenige High-Speed-Geräte können Double-Copy zu Kernel dann Benutzer in diesen Tagen tolerieren. IANANG (Ich bin kein Netzwerk-Guru), aber ich glaube, dass DMA aggressiv verwendet wird –

+0

Also, sobald eine NIC ein Paket erfasst, wird es direkt in den (Benutzer-) Speicher kopiert? – Rayne

+3

@Rayne ja; Die NIC verwendet DMA, um Daten direkt in den physischen Speicher zu übertragen, der in den Adressraum Ihres Prozesses (Benutzerbereichs) abgebildet wird. – vladr

Antwort

12

helfen könnte, wie dieser Prozess heraus spielt, ist meist bis zum Fahrer Autor und der Hardware , aber für die Fahrer habe ich bei oder geschrieben sah und die Hardware, die ich gearbeitet habe, ist dies in der Regel so, wie es funktioniert:

  1. bei Treiberinitialisierung wird es einige Anzahl der Puffer zuweisen und geben diese an das NIC.
  2. Wenn ein Paket von der NIC empfangen wird, zieht es die nächste Adresse aus seiner Liste von Puffern, DMAs die Daten direkt in es, und benachrichtigt den Treiber über einen Interrupt.
  3. Der Treiber erhält den Interrupt und kann entweder den Puffer an den Kernel übergeben oder er wird einen neuen Kernel-Buffer zuweisen und die Daten kopieren. "Zero Copy Networking" ist Ersteres und benötigt offensichtlich Unterstützung vom Betriebssystem. (dazu weiter unten)
  4. Der Treiber muss entweder einen neuen Puffer (im Fall von Nullkopie) zuweisen oder den Puffer erneut verwenden. In jedem Fall wird der Puffer für zukünftige Pakete an den NIC zurückgegeben.

Zero-Copy-Vernetzung innerhalb des Kernels ist nicht so schlecht. Zero-Copy bis hinunter zum Userland ist viel härter. Userland erhält Daten, aber Netzwerkpakete bestehen aus Header und Daten. Zumindest erfordert eine echte Nullkopie bis hin zum Benutzerland Unterstützung von Ihrer NIC, so dass DMA-Pakete in separate Header-/Datenpuffer übertragen werden können. Die Header werden wiederverwendet, sobald der Kernel das Paket an seinen Zielort routet und die Prüfsumme überprüft (für TCP entweder in Hardware, wenn die NIC dies unterstützt oder in Software, falls nicht; wenn der Kernel die Prüfsumme selbst berechnen muss kann auch die Daten kopieren: Beim Betrachten der Daten entstehen Cache-Fehler und das Kopieren an anderer Stelle kann kostenlos mit abgestimmtem Code erfolgen).

Selbst wenn alle Sterne ausgerichtet sind, befinden sich die Daten nicht wirklich in Ihrem Benutzerpuffer, wenn sie vom System empfangen werden. Bis eine Anwendung nach den Daten fragt, weiß der Kernel nicht, wo er landen wird. Betrachten Sie den Fall eines Multiprozess-Daemons wie Apache. Es gibt viele untergeordnete Prozesse, die alle auf demselben Socket lauschen. Sie können auch eine Verbindung herstellen, fork(), und beide Prozesse können recv() eingehenden Daten.

TCP-Pakete im Internet sind in der Regel 1460 Bytes Nutzlast (MTU von 1500 = 20 Byte IP-Header + 20 Byte TCP-Header + 1460 Bytes Daten). 1460 ist keine Potenz von 2 und entspricht nicht der Seitengröße eines Systems, das Sie finden. Dies führt zu Problemen beim erneuten Zusammensetzen des Datenstroms. Denken Sie daran, dass TCP Stream-orientiert ist. Es gibt keinen Unterschied zwischen Absenderschreibvorgängen, und zwei 1000-Byte-Schreibvorgänge, die auf den empfangenen warten, werden vollständig in einem 2000-Byte-Lesevorgang verbraucht.

Betrachten Sie die Benutzerpuffer. Diese werden von der Anwendung zugewiesen. Um für die Nullkopie vollständig verwendet zu werden, muss der Puffer seitenausgerichtet sein und diese Speicherseite nicht mit irgendetwas anderem teilen. Bei recv() Zeit, könnte der Kernel theoretisch die alte Seite mit der einen, die die Daten enthält, neu zuordnen und an Ort und Stelle "umdrehen", aber dies wird durch das oben beschriebene Problem der erneuten Zusammenfügung kompliziert, da aufeinanderfolgende Pakete auf getrennten Seiten liegen. Der Kernel könnte die Daten begrenzen, die er an die Payload eines jeden Pakets zurückgibt, aber dies wird eine Menge zusätzlicher Systemaufrufe, eine erneute Seitenzuordnung und wahrscheinlich einen insgesamt niedrigeren Durchsatz bedeuten.

Ich bin wirklich nur die Oberfläche zu diesem Thema zu kratzen. Ich habe in den frühen 2000er Jahren bei einigen Unternehmen gearbeitet, um die Zero-Copy-Konzepte auf das Userland auszudehnen. Wir haben sogar einen TCP-Stack im Userland implementiert und den Kernel komplett für Anwendungen mit dem Stack umgangen, aber das brachte seine eigenen Probleme mit sich und war nie Produktionsqualität. Es ist ein sehr schwer zu lösendes Problem.

Verwandte Themen