Ядро Linux в комментариях

Sys_ni_syscall


sys_ni_syscall, вне всяких сомнений, представляет собой простейший системный вызов; он просто возвращает ошибку ENOSYS. Поначалу он выглядит бесполезным, однако это не так. Действительно, sys_ni_syscall занимает несколько позиций в sys_call_table и на то существует несколько причин. Во-первых, sys_ni_syscall находится в позиции0 (строка ) для того, чтобы в случае, когда ошибочный код вызывает system_call некорректно (скажем, без инициализации переменной, передаваемой в качестве аргумента), передавался 0. Не стоит в таких случаях прибегать к решительным мерам наподобие уничтожения процесса. (Нельзя предупредить возникновение ошибок, не отменив заодно и всю полезную функциональность.) Подобная практика использования элемента 0 с целью предохранения от упомянутых ошибок применяется в ядре повсеместно.

Кроме того, в доброй дюжине позиций таблицы явным образом присутствует sys_ni_syscall. Такие элементы представляют системные вызовы, которые из ядра были удалены. Один из примеров находится в строке , где имеет место устаревший системный вызов prof. Здесь нельзя помещать другие, «реальные» системные вызовы, поскольку некоторые старые исполняемые модули могут все еще обращаться к этим устаревшим вызовам. Как будет выглядеть программа, которая выполняет устаревший системный вызов, а в результате получает, скажем, окно открытия файлов?

В конечном итоге, sys_ni_syscall занимает все неиспользуемые позиции в конце таблицы; это устанавливается в строках с  по , которые повторяют элемент необходимое количество раз с целью заполнения таблицы. Поскольку sys_ni_syscall просто возвращает код ошибки ENOSYS, обращение к sys_ni_syscall эквивалентно переходу на метку badsys в рамках system_call, таким образом эффект от использования номера системного вызова, расположенного в данных позициях таблицы, такой же как и в случае применения номера, лежащего за пределами таблицы. Следовательно, системные вызовы можно добавлять в таблицу (или удалять из нее) без изменений NR_syscalls, тем не менее, эффект будет таким, как если бы вносились изменения в NR_syscalls (во всяком случае, в рамках установленных пределов). Буквосочетание «ni» в имени sys_ni_syscall означает ни что иное, как «not implemented» (не реализовано).

В этой простой функции присутствует дескриптор asmlinkage, относящийся к специфике компилятора gcc. Он уведомляет компилятор, что функция не будет искать свои аргументы в регистрах (случай общепринятой оптимизации), поскольку она ожидает их в стеке ЦП. Вспомните последнее утверждение о том, что system_call работает с собственными первыми четырьмя аргументами, номером системного вызова и допускает до четырех дополнительных аргументов, которые передаются реальному системному вызову. Такое достигается за счет оставления своих аргументов (передаваемых в регистрах) в стеке. Все системные вызовы помечаются дескриптором asmlinkage, поэтому они ищут аргументы в стеке. Разумеется, что в случае с sys_ni_syscall это ничего не меняет, поскольку sys_ni_syscall не принимает каких-либо аргументов. Теперь-то вы уже знаете, о чем идет речь, когда перед функциями присутствует asmlinkage.



Содержание раздела