Contexte:
La surcharge des appels système est beaucoup plus importante que la surcharge des appels de fonction (les estimations vont de 20 à 100x), principalement en raison du changement de contexte de l'espace utilisateur vers l'espace noyau et inversement. Il est courant d'utiliser des fonctions en ligne pour économiser la surcharge des appels de fonction et les appels de fonction sont beaucoup moins chers que les appels système. Il va de soi que les développeurs voudraient éviter une partie de la surcharge des appels système en prenant en charge autant d'opérations dans le noyau en un seul appel système que possible.
Problème:
Cela a créé beaucoup d'appels système (superflu?) Comme sendmmsg () , recvmmsg () , ainsi que le chdir, ouvert, lseek et / ou des combinaisons symlink comme: 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 ...
Maintenant, Linux a ajouté copy_file_range()
qui combine apparemment lseek et write syscalls. Ce n'est qu'une question de temps avant que cela ne devienne fcopy_file_range (), lcopy_file_range (), copy_file_rangeat (), fcopy_file_rangeat () et lcopy_file_rangeat () ... mais comme il y a 2 fichiers impliqués au lieu de X appels supplémentaires, cela pourrait devenir X ^ 2 plus. OK, Linus et les différents développeurs BSD ne laisseraient pas aller aussi loin, mais mon point est que s'il y avait un appel système par lots, tous (la plupart?) Pourraient être implémentés dans l'espace utilisateur et réduire la complexité du noyau sans ajouter beaucoup s'il y a des frais généraux sur le côté libc.
De nombreuses solutions complexes ont été proposées qui incluent une certaine forme de thread syscall spécial pour les appels sys non bloquants pour les appels sys de traitement par lots; cependant, ces méthodes ajoutent une complexité significative au noyau et à l'espace utilisateur de la même manière que libxcb vs libX11 (les appels asynchrones nécessitent beaucoup plus de configuration)
Solution?:
Un appel système générique par lots. Cela réduirait le coût le plus élevé (commutateurs multi-modes) sans les complexités associées à la présence d'un thread noyau spécialisé (bien que cette fonctionnalité puisse être ajoutée plus tard).
Il existe fondamentalement déjà une bonne base pour un prototype dans le syscall socketcall (). Il suffit de l'étendre de prendre un tableau d'arguments pour prendre à la place un tableau de retours, un pointeur sur des tableaux d'arguments (qui inclut le numéro de syscall), le nombre de syscalls et un argument flags ... quelque chose comme:
batch(void *returns, void *args, long ncalls, long flags);
Une différence majeure serait que les arguments devraient probablement tous être des pointeurs de simplicité afin que les résultats des appels système précédents puissent être utilisés par les appels système suivants (par exemple, le descripteur de fichier open()
à utiliser dans read()
/ write()
)
Quelques avantages possibles:
- moins d'espace utilisateur -> espace noyau -> changement d'espace utilisateur
- commutateur de compilateur possible -fcombine-syscalls pour essayer de créer un lot de manière automatique
- drapeau optionnel pour un fonctionnement asynchrone (retournez fd pour regarder immédiatement)
- pouvoir implémenter les futures fonctions de syscall combinées dans l'espace utilisateur
Question:
Est-il possible de mettre en œuvre un appel système par lots?
- Suis-je en train de rater des problèmes évidents?
- Suis-je surestimer les avantages?
Vaut-il la peine de mettre en œuvre un appel système par lots (je ne travaille pas chez Intel, Google ou Redhat)?
- J'ai déjà patché mon propre noyau, mais je crains d'avoir affaire au LKML.
- L'histoire a montré que même si quelque chose est largement utile aux utilisateurs "normaux" (utilisateurs finaux non-entreprise sans accès en écriture git), il peut ne jamais être accepté en amont (unionfs, aufs, cryptodev, tuxonice, etc ...)
Les références:
batch
appels système dans desbatch
appels système, vous pouvez créer une arborescence d'appels arbitrairement approfondie de appels système arbitraires. Fondamentalement, vous pouvez mettre votre application entière dans un seul appel système.