как вы делаете системные вызовы прерываний в C? - PullRequest
2 голосов
/ 05 января 2011

Я узнал от download.savannah.gnu.org /.../ ProgrammingGroundUp-1-0-booksize.pdf что программы прерывают ядро, и так все и делается. Что я хочу знать, так это как вы делаете это в C (если это возможно)

Ответы [ 5 ]

4 голосов
/ 06 января 2011

Не существует независимого от платформы способа (очевидно)! На платформах x86 системные вызовы обычно реализуются путем помещения кода системного вызова в регистр eax и запуска int 80h в ассемблере, что вызывает переход в режим ядра. Затем ядро ​​выполняет соответствующий код на основе того, что видит в eax.

3 голосов
/ 06 января 2011

Пользовательские процессы обычно запрашивают службы ядра, вызывая системный вызов функции-оболочки из Стандартная библиотека C .Вы можете сделать это вручную с помощью syscall(2).

1 голос
/ 06 января 2011

Если вы используете glibc (который вы, вероятно, используете, если вы используете gcc и linux), тогда в unistd.h есть функция syscall, которую вы можете использовать.Он имеет разные реализации для разных архитектур и операционных систем, но реализация выполняется в сборке (может быть встроенной сборкой).syscall имеет справочную страницу, поэтому:

 man syscall

даст вам некоторую информацию.

Если вам просто интересно, как все это работает, вы должны знать, что это изменилосьв линуксе на х86 в последние годы.Первоначально прерывание 0x80 использовалось Linux как обычная точка входа системного вызова на x86.Это работало достаточно хорошо, но поскольку процессоры получили более продвинутую конвейерную обработку (запуск инструкции до выполнения предыдущих инструкций), прерывания замедлились (по сравнению с выполнением обычного кода, который ускорился, хотя некоторые тесты показали, что он замедлился более чемтот).Причина этого заключается в том, что даже когда инструкция int используется для запуска прерывания, она работает в основном так же, как и аппаратные прерывания, которые происходят непредсказуемо, что приводит к тому, что они не очень хорошо работают с конвейерной обработкой команд (конвейерная обработка работает лучше, когдапути к кодам предсказуемы.)

Чтобы помочь в этом, у более новых процессоров x86 есть инструкции, специально предназначенные для выполнения системных вызовов, но Intel и AMD используют для этого разные инструкции (sysenter и syscall соответственно).Кроме того, инструкция Intel systenter закрывает регистр общего назначения, который Linux использовал в x86_32 для передачи параметра в ядро.Это означает, что программы должны знать, какой из 3 возможных механизмов системных вызовов использовать, а также, возможно, разные способы передачи аргументов ядру.Чтобы обойти все эти новые ядра, сопоставьте специальную страницу памяти с программами (эта страница называется vsyscall, и если вы cat /proc/self/maps увидите запись для нее), которая содержит код для механизма системных вызовов, который определено ядром, должениспользовать в системе, и более новые версии glib могут реализовать запись о системных вызовах, используя код на этой странице.

Смысл всего этого в том, что это не так просто, как раньше,но если вы просто играете на x86_32, тогда вы сможете использовать инструкцию int 80h, поскольку она будет поддерживаться в системах, которые могут использовать один из других механизмов для обратной совместимости.

1 голос
/ 06 января 2011

Взаимодействие пользовательской программы с ядром будет зависеть от платформы, поэтому обычно происходит за кулисами в различных подпрограммах библиотеки. Поэтому нужно просто вызывать printf, write, select или другие библиотечные подпрограммы, которые позволяют программисту писать код, не беспокоясь о деталях интерфейса ядра, драйверов устройств и т. Д.

И обычно он работает так: когда одной из этих библиотечных подпрограмм нужно, чтобы ядро ​​что-то сделало от его имени, он выполняет системный вызов низкого уровня, который возвращает управление ЦП ядро. Прерывается только пользовательская программа, а не ядро.

0 голосов
/ 06 января 2011

В C вы на самом деле не делаете это напрямую, но вы в конечном итоге будете делать это косвенно каждый раз, когда используете библиотечные функции, которые в конечном итоге вызывают системные вызовы.Доступ к файлам, доступ к сети и т. Д. Являются типичными примерами этого.

Все эти функции в конечном итоге будут "захватывать" ядро, которое будет обрабатывать запрос.

...