Фон:
Накладні витрати на системний виклик набагато більше, ніж накладні виклики функцій (оцінки складають від 20-100x), в основному за рахунок переходу контексту з простору користувача на простір ядра та назад. Загальні вбудовані функції для збереження накладних викликів функцій, а виклики функцій значно дешевші, ніж системні дзвінки. Цілком очевидно, що розробники хотіли б уникнути деяких накладних системних викликів, піклуючись про якомога більше роботи в ядрі за один системний виклик.
Проблема:
Це створило багато (зайві?) Системні виклики , як sendmmsg () , recvmmsg () , а також Chdir, відкритий, lseek і / або символічні посилання поєднань , як: 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
т.д. ...
Тепер Linux додав, copy_file_range()
що, очевидно, поєднує в собі читання lseek та запису системних дзвінків. Є лише питання часу, перш ніж це стане fcopy_file_range (), lcopy_file_range (), copy_file_rangeat (), fcopy_file_rangeat () та lcopy_file_rangeat () ... але оскільки замість X більше дзвінків задіяні 2 файли, це може стати X ^ 2 більше. Гаразд, Лінус та різні розробники BSD не давали б цього зайти, але я висловлюю думку про те, що якби пакетна системна виклик, все (більшість?) З них можна було б реалізувати в просторі користувача та зменшити складність ядра, не додаючи багато якщо є накладні на стороні libc.
Було запропоновано багато складних рішень, які включають певну форму спеціального потоку syscall для неблокуючих систематичних викликів для пакетних системних викликів; однак ці методи додають значної складності як ядра, так і користувальницького простору приблизно так само, як libxcb проти libX11 (асинхронні виклики потребують набагато більшої настройки)
Рішення ?:
Загальний системний виклик. Це зменшило б найбільшу вартість (перемикачі декількох режимів) без складностей, пов’язаних із наявністю спеціалізованої нитки ядра (хоча цю функціональність можна буде додати пізніше).
В основному вже є хороша основа для прототипу в socketcall () syscall. Просто розгорніть його від прийняття масиву аргументів, щоб замість цього взяти масив повернень, вказівник на масиви аргументів (що включає номер syscall), кількість syscall та аргумент прапорів ... щось на кшталт:
batch(void *returns, void *args, long ncalls, long flags);
Одним з основних відмінностей є те , що аргументи, ймовірно , все потрібно бути покажчики для простоти так , що результати попередніх системних викликів можуть бути використані в наступних системних викликів (наприклад , дескриптор файлу з open()
для використання в read()
/ write()
)
Деякі можливі переваги:
- менший простір користувача -> простір ядра -> комутація простору користувача
- можливий перемикач компілятора -fcombine-syscalls, щоб спробувати провести автоматичну партію
- необов'язковий прапор для асинхронної роботи (повернути fd для перегляду негайно)
- можливість реалізовувати майбутні комбіновані функції системного виклику в просторі користувачів
Питання:
Чи можливо здійснити пакетний системний виклик?
- Невже я пропускаю якісь очевидні прищі?
- Чи я завищую переваги?
Чи варто мені заважати впроваджувати пакетний syscall (я не працюю в Intel, Google чи Redhat)?
- Я вже виправляв власне ядро, але боявся мати справу з LKML.
- Історія показала, що навіть якщо "звичайним" користувачам щось є корисним (некорпоративним кінцевим користувачам без доступу до запису git), воно ніколи не може бути прийнятим вгору за течією (unionfs, aufs, cryptodev, tuxonice тощо).
Список літератури:
batch
системних викликів вbatch
системні виклики, ви можете створити скільки завгодно глибоке дерево викликів довільних системних викликів. В основному, ви можете помістити всю свою програму в єдиний системний виклик.