Путь программы до системного вызова
Когда мы пишем программу на Си и подключаем библиотеку например <unistd.h> и делаем вызов write(), то это вызов библиотечной функции Си (вопрос где она лежит в linux), в которой есть вызов системного вызова write(где он лежит в линукс), а write() где то скомпилирован в ядре ОС. А что такое syscall? Как раз он и передает номер и аргументы в ос для вызова нужного кода выполнения?
Почему столько вопросов? Везде в инете написано, это интерфейс между пользовательскими программами и ядром ОС. А хочется понять, вот наша программа она дергает вот эту функцию, та в свою очередь вот эту... А там еще бывает linux-gateway это вот прослойка между этим и этим. И в итоге системный вызов это код в ядре для исполнения в ring0? Можно ли напрямую вызвать системный вызов без библиотеки?
Ответы (1 шт):
Просто так взять и позвать (через call) "ядерную" функцию нельзя - обычно они работают на другом уровне защиты. И если можно было бы просто так позвать, то система безопасности ядра была бы под угрозой. Именно syscall и решает эту проблему. А вот как именно он устроен - это другое дело.
В Linux для x86 долгое время применялось 128 прерывание (0x80). Когда срабатывает прерывание, то процессор вызывает "специальную подпрограмму", которая просто вызывает соответствующую функцию ядра, но уже в на уровне ядра. Как стает понятно, что именно вызывать? вызывающая программа оставляет в регистрах процессора данные об этом. Например, в eax хранится номер нужной функции (их можно подсмотреть в файлах /usr/include/asm*/unistd.h и они имеют вид
#define __NR_connect 203
__SYSCALL(__NR_connect, sys_connect)
файлов может быть несколько - они платформенно-зависимые)
И так как теперь процессор находится на уровне ядра, а пользовательская программа "поставлена на паузу", ядро может для начала понять, а нужно ли что то делать, может вообще лучше прибить приложение. А потом запланировать выполнение задач пользователя. И когда будут результаты, разместить в нужных регистрах и дать указание планировщику задач поставить задачу на выполнение. А для самой задачи как будто ничего и не произошло, но результаты уже есть.
Если подобных прерываний нет (какая-нибудь экзотическая платформа), то используют другие приемы. Например, какую то несуществующую команду. Процессор генерирует исключение и оно перехватывается. а дальше по известной описанной выше схеме.
Потом поняли, что некоторые функции так "невыгодно" вызывать. Например, узнать текущее время (тут нет проблем с защитой ядра, это же не открытие какого то файла). И начали придумывать, как это ускорить. В результате начали появляться новые способы, некоторые даже являются инструкциями процессора. Например, amd придумала syscall/sysret.
- почитать https://habr.com/ru/post/347596/