2010-10-11 6 views
10

Ich frage hier, denn googeln führt Sie auf eine fröhliche Reise durch Archive ohne Hinweis darauf, was der aktuelle Zustand ist. Wenn Sie von Google gehen, scheint es, dass async IO war der letzte Schrei in den Jahren 2001 bis 2003, und bis 2006 einige Sachen wie epoll und libaio auftauchte; kevent erschien aber scheint verschwunden zu sein, und soweit ich das beurteilen kann, gibt es immer noch keine gute Möglichkeit, completion-based und ready-based Signalisierung zu mischen, async sendfile - ist das überhaupt möglich? - und alles andere in einer single-threaded Ereignisschleife.Der Status von Linux async IO?

Also bitte sag mir, dass ich falsch liege und alles rosig ist! - und, was wichtig ist, welche APIs zu verwenden.

Wie vergleicht Linux in diesem Zusammenhang mit FreeBSD und anderen Betriebssystemen?

+3

Mm, vielleicht solltest du deinen Flammenanzug anziehen und nach LKML fragen. – ninjalj

+1

siehe http://blog.libtorrent.org/2012/10/asynchronous-disk-io/ –

Antwort

3

Asynchronous Disk IO ist lebendig und tritt auf ... es wird tatsächlich unterstützt und funktioniert jetzt einigermaßen gut, hat aber erhebliche Einschränkungen (aber mit genügend Funktionalität, dass einige der Hauptbenutzer es sinnvoll nutzen können - zum Beispiel MySQL Innodb tut in Die neueste version).

Asynchronous Disk IO ist die Fähigkeit, Disc IO-Operationen auf nicht blockierende Weise (in einem einzelnen Thread) aufzurufen und auf deren Beendigung zu warten. Dies funktioniert gut, hat mehr Informationen.

AIO reicht aus, um eine typische Anwendung (Datenbankserver) verwenden zu können. AIO ist eine gute Alternative, um entweder viele Threads zu erstellen, die synchrone IOs ausführen, oder Scatter/Gather in der Preadv-Familie von Systemaufrufen zu verwenden, die jetzt existieren.

Es ist möglich, einen synchronen "Einkaufslisten" -IOS-Job unter Verwendung des neuen Preadv-Aufrufs auszuführen, wo der Kernel gehen wird und eine Reihe von Seiten von verschiedenen Offsets in einer Datei erhält. Dies ist in Ordnung, solange Sie nur eine Datei zum Lesen haben. (NB: Äquivalente Schreibfunktion existiert).

poll, epoll etc, sind nur einige Möglichkeiten, select() zu verwenden, die weniger Einschränkungen und Skalierbarkeitsprobleme haben - sie können nicht einfach mit disc aio gemischt werden, aber in einer realen Anwendung können Sie das tun wahrscheinlich umgehen Sie dies ziemlich trivial mit Hilfe von Threads (einige Datenbankserver neigen dazu, diese Art von Operationen in separaten Threads sowieso durchzuführen). Poll() ist gut, epoll ist besser für eine große Anzahl von Dateideskriptoren. select() ist auch für kleine Anzahlen von Dateideskriptoren geeignet (oder speziell für niedrige Dateideskriptorzahlen).

+0

also wo steht das? http://StackOverflow.com/Questions/1825621/how-do-you-use-aio-and-epoll-together-in-a-single-event-loop – Will

+0

(Ich dachte, Abfrage und Auswahl waren symmetrisch und O (n), während epoll ist O (1) – Will

+0

Abfrage ist besser als auswählen, weil es viel besser mit einem spärlichen Satz von Dateideskriptoren funktioniert - sagen Sie wollen 10 FDs von 10000 geöffneten zu holen, Sie brauchen kein Array von 10000 Einträge, die mit Nullen initialisiert werden sollen, epoll ist besser, weil Sie nur die neuen FDs registrieren müssen, an denen Sie interessiert sind, und nicht all die, die Sie bereits gesehen haben – MarkR

2

Das meiste, was ich über asynchrone I/O in Linux gelernt habe, war durch die Arbeit an der Quelle Lighttpd. Es ist ein single-threaded Web-Server, der viele simultane Verbindungen verarbeitet, wobei er das nutzt, was es für das beste asynchrone E/A-Mechanismen auf dem laufenden System hält. Schauen Sie sich die Quelle an, sie unterstützt Linux, BSD und (denke ich) einige andere Betriebssysteme.

4

AIO als solches ist immer noch etwas begrenzt und ein echter Schmerz, um damit anzufangen, aber es funktioniert zum größten Teil, wenn Sie erst einmal durchgegraben haben.

Es hat einige meiner Meinung nach gravierenden Fehlern, aber das ist wirklich gehört. Wenn Sie beispielsweise eine bestimmte Anzahl von Befehlen oder Daten senden, wird Ihr übersetzender Thread blockiert. Ich erinnere mich nicht die genaue Begründung für diese Funktion, aber die Antwort, die ich zurück bekam dann war so etwas wie „Ja natürlich, die Kernel eine Begrenzung seiner Warteschlange Größe hat, dass beabsichtigt ist“. Was ist akzeptabel, wenn Sie ein paar tausend Anfragen einreichen ... offensichtlich muss irgendwo ein Limit sein. Dies könnte auch unter DoS-Gesichtspunkten sinnvoll sein (andernfalls könnte ein böswilliges Programm den Kernel dazu bringen, nicht genügend Arbeitsspeicher zu haben, indem es eine Milliarde Anfragen sendet). Aber es ist immer noch etwas, das Sie realistisch mit "normalen" Zahlen (etwa hundert) treffen können und es wird Sie unerwartet treffen, was nicht gut ist.Wenn Sie nur ein halbes Dutzend Anfragen einreichen und diese ein wenig größer sind (einige Megabyte an Daten), kann das gleiche passieren, anscheinend weil der Kernel sie in Unteranforderungen aufteilt. Was wiederum sinnvoll ist, aber wenn man sieht, wie die Docs es nicht sagen, sollte man erwarten, dass es keinen Unterschied macht (abgesehen davon, dass man länger braucht), ob man 500 Bytes oder 50 Megabyte Daten liest.

Es scheint auch keine Möglichkeit gepuffertes AIO zu geben, zumindest auf keinem meiner Debian- und Ubuntu-Systeme (obwohl ich andere Leute über das genaue Gegenteil klagen gesehen habe, dh ungepufferte Schreibvorgänge, die tatsächlich über die Puffer laufen). Von dem, was ich auf meinen Systemen sehen kann, ist AIO nur wirklich asynchron mit deaktivierter Pufferung, was eine Schande ist (deshalb verwende ich momentan ein hässliches Konstrukt um Speicherabbildung und einen Worker Thread).

Ein wichtiges Problem bei etwas Asynchronem ist es, epoll_wait() darauf zu setzen, was wichtig ist, wenn Sie etwas anderes machen, abgesehen von der Festplatten-IO (wie das Empfangen von Netzwerkverkehr). Natürlich gibt es io_getevents, aber es ist nicht so wünschenswert/nützlich, da es nur für eine einzige Sache funktioniert.

In den letzten Kernen gibt es Unterstützung für eventfd. Auf den ersten Blick erscheint es nutzlos, da es nicht offensichtlich ist, wie es in irgendeiner Weise hilfreich sein könnte. Doch zu Ihrer Rettung gibt es die undokumentierte Funktion io_set_eventfd, mit der Sie AIO mit einer eventfd verknüpfen können, die epoll_wait() - fähig ist. Sie müssen durch die Header graben, um es herauszufinden, aber es ist sicherlich da, und es funktioniert gut.

+0

Ich nehme an, dies bezieht sich auf Kernel AIO im Gegensatz zu POSIX AIO? –

+1

@ JanusTroelsen: Ja, wie die Frage, bezieht sich das auf Kernel AIO ('libaio'). POSIX AIO ist nicht so sehr eine Linux-Funktion, sondern eine Bibliothek Feature in' librt' mit einem Thread-Pool und Standard-Synchron I/O. Überraschenderweise funktioniert das ** viel besser als der Kernel im in jeder Hinsicht. – Damon

Verwandte Themen