Hintergrund:
Der Systemaufruf-Overhead ist viel größer als der Funktionsaufruf-Overhead (Schätzungen reichen von 20-100x), was hauptsächlich auf die Kontextumschaltung vom Benutzerbereich zum Kernelbereich und zurück zurückzuführen ist. Inline-Funktionen werden häufig verwendet, um Funktionsaufruf-Overhead zu sparen, und Funktionsaufrufe sind viel billiger als Syscalls. Es liegt auf der Hand, dass Entwickler einen Teil des Systemaufruf-Overheads vermeiden möchten, indem sie so viel Kernel-Betrieb wie möglich in einem Systemaufruf erledigen.
Problem:
Dies hat eine Menge von (? Überflüssig) Systemaufrufen wie geschaffen sendmmsg () , recvmmsg () sowie den chdir, offen, lseek und / oder Symlink Kombinationen wie: openat
, mkdirat
, mknodat
, fchownat
, futimesat
, newfstatat
, unlinkat
, fchdir
, ftruncate
, fchmod
, renameat
, linkat
, symlinkat
, readlinkat
, fchmodat
, faccessat
, lsetxattr
, fsetxattr
, execveat
, lgetxattr
, llistxattr
, lremovexattr
, fremovexattr
, flistxattr
, fgetxattr
, pread
, pwrite
etc ...
Nun hat Linux hinzugefügt, copy_file_range()
das offenbar Lese- und Schreibsyscalls kombiniert. Es ist nur eine Frage der Zeit, bis fcopy_file_range (), lcopy_file_range (), copy_file_rangeat (), fcopy_file_rangeat () und lcopy_file_rangeat () angezeigt werden Mehr. OK, Linus und die verschiedenen BSD-Entwickler ließen es nicht so weit kommen, aber mein Punkt ist, dass, wenn es einen Batch-Systemaufruf gäbe, all diese (die meisten?) Im Benutzerraum implementiert werden könnten und die Kernel-Komplexität reduziert werden könnte, ohne viel hinzuzufügen wenn irgendein Aufwand auf der libc-Seite.
Es wurden viele komplexe Lösungen vorgeschlagen, die einen speziellen Syscall-Thread für nicht blockierende Syscalls zur Stapelverarbeitung von Syscalls enthalten. Diese Methoden erhöhen jedoch die Komplexität sowohl des Kernels als auch des Benutzerbereichs auf die gleiche Weise wie libxcb im Vergleich zu libX11 (die asynchronen Aufrufe erfordern viel mehr Setup).
Lösung?:
Ein generisches Batching-System. Dies würde die größten Kosten (mehrere Moduswechsel) verringern, ohne die Komplexität, die mit einem spezialisierten Kernel-Thread verbunden ist (obwohl diese Funktionalität später hinzugefügt werden könnte).
Grundsätzlich gibt es im socketcall () syscall bereits eine gute Basis für einen Prototyp. Erweitern Sie es einfach von einem Array von Argumenten zu einem Array von Rückgaben, einem Zeiger auf ein Array von Argumenten (einschließlich der Syscall-Nummer), der Anzahl der Syscalls und einem Flags-Argument ... so etwas wie:
batch(void *returns, void *args, long ncalls, long flags);
Ein Hauptunterschied wäre, dass die Argumente der Einfachheit halber wahrscheinlich alle Zeiger sein müssten, damit die Ergebnisse früherer Systemaufrufe von nachfolgenden Systemaufrufen verwendet werden können (zum Beispiel der Dateideskriptor von open()
zur Verwendung in read()
/ write()
).
Einige mögliche Vorteile:
- weniger User Space -> Kernel Space -> User Space Switching
- mögliche Compiler-Schalter -fcombine-syscalls, um zu versuchen, automatisch zu stapeln
- optionales Flag für asynchronen Betrieb (fd zurückgeben, um sofort zu sehen)
- Fähigkeit zur Implementierung zukünftiger kombinierter Syscall-Funktionen im Userspace
Frage:
Ist es möglich, ein Batching-System zu implementieren?
- Vermisse ich einige offensichtliche Fallstricke?
- Überschätze ich die Vorteile?
Lohnt es sich für mich, ein Batching-System zu implementieren (ich arbeite nicht bei Intel, Google oder Redhat)?
- Ich habe meinen eigenen Kernel schon mal gepatcht, fürchte mich aber vor dem Umgang mit dem LKML.
- Die Geschichte hat gezeigt, dass selbst wenn etwas für "normale" Benutzer (Nicht-Firmen-Endbenutzer ohne Git-Schreibzugriff) von großem Nutzen ist, es möglicherweise nie im Upstream akzeptiert wird (unionfs, aufs, cryptodev, tuxonice, etc ...)
Verweise:
batch
Syscalls inbatch
Syscalls verschachteln, können Sie einen beliebig tiefen Aufrufbaum beliebiger Syscalls erstellen. Grundsätzlich können Sie Ihre gesamte Anwendung in einem einzigen Systemaufruf zusammenfassen.