Как параметры передаются в системный вызов Linux? Через регистр или стек? - PullRequest
1 голос
/ 09 мая 2020

Я пытаюсь понять внутреннее устройство Linux ядра, читая Роберт Лав Linux Разработка ядра .

На странице 74 он говорит, что самый простой способ передать аргументы в syscall передается через:

Каким-то образом пользовательское пространство должно передавать параметры ядру во время прерывания. Самый простой способ сделать это - использовать те же средства, что и номер системного вызова: параметры хранятся в регистрах. На x86-32 регистры ebx, ecx, edx, esi и edi содержат по порядку первые пять аргументов.

Меня это беспокоит по ряду причин:

  1. Все системные вызовы определяются с помощью опции asmlinkage. Это означает, что аргументы всегда можно найти в стеке, а не в регистре . Так что же все это за дела с регистрами?
  2. Возможно, что до выполнения системного вызова значения копируются в стек ядра. Понятия не имею, почему это было бы эффективно, но это возможно.

1 Ответ

3 голосов
/ 09 мая 2020

(Этот ответ предназначен для 32-битной x86 Linux, чтобы соответствовать вашему вопросу; для 64-битной x86 и других архитектур все немного по-другому.)

Параметры передаются из пользовательского пространства в регистрах как Love говорит.

Когда пользовательское пространство вызывает системный вызов с int $0x80, код входа системного вызова ядра получает управление. Это написано на ассемблере, и его можно увидеть, например, здесь . Одно из действий этого кода - это взять параметры из регистров и поместить их в стек, а затем вызвать соответствующую функцию ядра sys_XXX() (которая записана в C). Таким образом, эти функции действительно ожидают, что их аргументы будут в стеке.

Также не сработает попытка передать параметры из пользовательского пространства ядру в стеке. Когда выполняется системный вызов, ЦП переключается на отдельный стек ядра, поэтому параметры должны быть скопированы из стека пользовательского пространства в стек ядра, а это несколько сложно. И это нужно было бы сделать даже для очень простых системных вызовов, которые принимают всего несколько числовых c аргументов и в противном случае вообще не нуждались бы в доступе к памяти пользовательского пространства (подумайте, например, о close()).

...