ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/docs/io-aio.pod
Revision: 1.2
Committed: Thu Feb 1 16:24:36 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
Log Message:
*** empty log message ***

File Contents

# Content
1 =encoding utf-8
2
3 =head1 IO::AIO - Asynchronous Input/Output
4
5 =head2 Motivation
6
7 In vielen Situationen wäre es schön (oder ist man sogar gezwungen),
8 bestimmte Reaktionszeiten einzuhalten: Ein Web-Server, der viele Sockets
9 bedient, sollte sich möglichst rechtzeitig um diese kümmern können. Ein
10 interktives Spiel muss bestimmte Antwortzeiten einhalten. Und manchmal
11 wäre es einfach nur hilfreich, wenn man etwas anderes tun könnte,
12 während der Rechner auf die Festplatte wartet.
13
14 Unix bietet herkömmlicherweise relativ wenig Unterstützung für
15 derartige Anliegen. Daher habe ich das Modul IO::AIO entwickelt, mit dem
16 sich alle wichtigen I/O-Operationen asynchron abwickeln lassen.
17
18 =head2 Asynchron mit Synchronisation
19
20 Asynchron bedeutet, daß die eigentliche Ein-/Ausgabe, z.B. das schreiben
21 einer Datei, gleichzeitig mit anderen Aktivitäten eines Programmes
22 geschieht. Dies unterscheidet asynchrone I/O von non-blocking I/O,
23 bei letzterem wird das Programm zwar ebenfalls nicht behindert, die
24 eigentliche Ein-/Ausgabe findte jedoch immer noch synchron statt.
25
26 Beispiel:
27
28 aio_readdir "/etc", sub {
29 my $entries = shift
30 or die "error while reading /etc: $!";
31 print "read /etc, entries: @$entries\n";
32 };
33
34 Dieser Aufruf erzeugt eine readdir-Anfrage, die asynchron bearbeitet
35 wird, d.h. C<aio_readdir> kehrt sofort zurück. Sobald das Verzeichnis
36 eingelesen wurde, wird der übergebene Callback mit den Einträgen
37 aufgerufen.
38
39 Da Perl nicht einfach jederzeit unterbrochen werden kann (bzw. man dies
40 auch garnicht zu jedem Zeitpunkt möchte), geschieht die Verarbeitung
41 von Resultaten in IO::AIO synchron, d.h. die eigentliche Ein-/Ausgabe
42 findet asynchron statt, aber der Callback, der das Ende der Operation
43 signalisiert, wird nur zu bestimmten Zeiten aufgerufen, und zwar immer
44 dann, wenn das Perl-Programm IO::AIO::poll_cb aufruft.
45
46 Wie man dies tut ist relativ unwichtig. Wann dagegen ist wichtig, und um
47 die Integration von IO::AIO in bestehende Event-Modelle zu erleichtern,
48 stellt IO::AIO einen filedeskriptor zur Verfügung: sobald dieser lesbar
49 wird, sollte man C<poll_cb> aufrufen. Für Gtk2 sieht das z.B. so aus:
50
51 add_watch Glib::IO IO::AIO::poll_fileno,
52 in => sub { IO::AIO::poll_cb; 1 };
53
54 Für AnyEvent dagegen etwas komplexer, da es einen Filehandle benötigt:
55
56 open my $fh, "<&=" . IO::AIO::poll_fileno or die "$!";
57 my $w = AnyEvent->io (fh => $fh, poll => ’r’, cb => sub { IO::AIO::poll_cb });
58
59 =head2 The Works
60
61 Hat man IO::AIO erst einmal integriert, kann man wild drauf loslegen. Fast
62 alle Operationen, die mit Dateien zu tun haben, werden von IO::AIO
63 unterstützt:
64
65 aio_sendfile aio_read aio_write aio_open aio_close aio_stat
66 aio_lstat aio_unlink aio_rmdir aio_readdir aio_symlink
67 aio_readlink aio_fsync aio_fdatasync aio_rename aio_link
68 aio_mknod aio_mkdir
69
70 Allen ist gemeinsam, daß sie ein oder mehrere Parameter verlangen und als
71 letztes einen Callback, der im Fehlerfall oder bei erfolgreichem Abschluß
72 der Operation aufgerufen wird. Anders als die eingebauten Perl-Funktionen
73 geben die meiste aio-Operationen direkt den Status des entsprechenden
74 Syscalls zurück:
75
76 # Perl
77 stat $path or die ...
78
79 # IO::AIO
80 aio_stat $path, # vvv and statt or
81 sub { $_[0] and die "..." }
82
83 =head2 The Features
84
85 IO::AIO bietet auch eine Reihe von zusammengesetzten Anfragen.
86
87 So verschieben bzw. kopieren C<aio_move> C<aio_copy> einzelne Dateien. Mit
88 C<aio_load> kann man eine Datei komplett einlesen, C<aio_rmtree>
89 löscht Verzeichnisbäume, C<aio_readahead> liest eine Datei in den
90 OS-Cache (pre-caching) und C<aio_scandir> liefert alle Einträge eines
91 Verzeichnisses in zwei Gruppen sortiert zurück: Verzeichnisse und
92 Sonstige. Der Algorithmus von C<aio_scandir> ist recht komplex aber dafür
93 sehr, sehr schnell.
94
95 =head2 The Specialties
96
97 Die meisten der etwas spezielleren Anfragen (sogenannte I<composite
98 requests>) bestehen aus mehreren Einzelanfragen. C<aio_load> z.B. öffnet
99 die Datei und liest dann deren Inhalt mit C<aio_read>. Damit diese
100 Anfragen nach aussen wie eine Anfrage aussehen, kann man Anfragen mit
101 C<aio_group> zusammengruppieren.
102
103 Die Implementation von C<aio_load> sieht Beispielsweise so aus:
104
105 sub aio_load($$;$) {
106 aio_block {
107 my ($path, undef, $cb) = @_;
108 my $data = \$_[1];
109
110 my $pri = aioreq_pri;
111 my $grp = aio_group $cb;
112
113 aioreq_pri $pri;
114 add $grp aio_open $path, O_RDONLY, 0, sub {
115 my $fh = shift
116 or return $grp->result (-1);
117
118 aioreq_pri $pri;
119 add $grp aio_read $fh, 0, (-s $fh), $$data, 0, sub {
120 $grp->result ($_[0]);
121 };
122 };
123
124 $grp
125 }
126 }
127
128 Zur Erläuterung: C<aio_block> ist eine Art Locking-Mechanismus, der
129 benötigt wird, wenn man asynchone Rückmeldungen wünscht. Das ist nicht
130 Normalbetrieb und darf hier ignoriert werden.
131
132 Zuest wird daher eine Gruppe erzeugt (C<aioreq_pri> dient dazu,
133 Anfragen untereinander zu prioritisieren). In diese Gruppe wird eine
134 C<aio_open>-Anfrage gesteckt und - falls erfolgreich - gleich noch das
135 C<aio_read>.
136
137 =head2 Request-Objekte
138
139 Alle Anfragen liefern (auf Wunsch :) ein Objekt zurück:
140
141 my $buffer;
142 my $loader = aio_load $path, $buffer, sub {
143 # $buffer voll, hoffentlich
144 };
145
146 Mit diesem Objekt kann man jede Operation unter andere, abbrechen, falls
147 diese nicht schon bearbeitet wird:
148
149 $loader->cancel; # wills nicht mehr haben
150
151 Dies ist vor allem für interaktive Programme nützlich, die auf
152 Benutzerwunsch eine Operationen starten, diese aber abbrechen, falls der
153 Benutzer nicht mehr daran interessiert ist.
154
155 =head2 Anwendungsbeispiel
156
157 IO::AIO wird, unter anderem, von dne folgendne drei Programmen benutzt:
158
159 =head3 Gtk2::CV
160
161 Ein interaktives Bildbetrachtungsprogramm. Geschrieben wurde es, um die
162 wichtigsten Features von XV in das 21te Jahrhundert zu retten, bzw.
163 schnell und effizient große Bildverzeichnisse zu durchforsten. Es benutzt
164 IO::AIO extensiv, um z.B. Dateien für den Thumbnailprozess zu lesen (es
165 ist wahrscheinlich einer der schnellsten indexer "wo gibt"), Dateien zu
166 verschieben, zu löschen und vieles mehr.
167
168 =head3 myhttpd
169
170 Ist ein single-Prozess-Webserver, der schon vor fast 10 Jahren 1400
171 Downloader gleichzeitig mit 80MBit/s von nur zwei Festplatten bedienen
172 konnte. Damals noch mit Linux::AIO, benutzt er inzwischen IO::AIO für
173 fats alle Dateiperationen, insbesondere natürlich für das Serven großer
174 Dateien.
175
176 =head3 Crossfire+
177
178 Crossfire+ ist ein grafisches Multiplayer-Online-RPG (bzw. eines der
179 ältesten). Perl und IO::AIO haben ihm vor kurzer Zeit beigebracht,
180 Karten/Levels und andere Spieldaten im Hintergrund zu Laden und zu
181 Speichern, so daß auch bei vielen Spielern und einem laufenden Backup im
182 Hintergrund keine lästigen Pausen mehr entstehen.
183
184 =head2 Coro::AIO - IO::AIO linearisiert
185
186 Mit Coro::AIO kann man alle IO::AIO-Operationen wieder "linear"
187 benutzen. Crossfire+ z.B. benutzt IO::AIO meistens nicht direkt, sondern
188 über Coro::AIO. Eine Map oder andere Daten werden z.B. so geschrieben:
189
190 if (my $fh = aio_open "$filename~", O_WRONLY | O_CREAT, 0600) {
191 chmod SAVE_MODE, $fh;
192 aio_write $fh, 0, (length $$rdata), $$rdata, 0;
193 aio_fsync $fh;
194 close $fh;
195 aio_rename "$filename~", $filename;
196 } else {
197 warn "FATAL: $filename~: $!\n";
198 }
199
200 Den Callback läßt man weg, stattdessen werden die Ergebnisse an den
201 Aufrufer zurückgeliefert. Die aktuelle Coroutine wird zwar blockiert,
202 aber andere Coroutinen (z.B. der Server selbst, der Map-Updates an die
203 Spieler liefert) läuft aber ungehindert weiter.
204
205 =head2 Autor
206
207 Marc Lehmann <pcg@goof.com>