Я очень сомневаюсь, что компилятор знает, что это системный вызов. Гораздо более вероятно, что open
находится где-то в библиотеке, а код внутри библиотеки вызывает соответствующий интерфейс ядра.
Вывод сборки из простой программы:
#include <stdio.h>
int main (void) {
int fd = open("xyz");
return 0;
}
is (ненужные биты удалены):
main:
pushl %ebp ; stack frame setup.
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl $.LC0, (%esp) ; Store file name address.
call open ; call the library function.
movl %eax, 28(%esp) ; save returned file descriptor.
movl $0, %eax ; return 0 error code.
leave ; stack frame teardown.
ret
.LC0:
.string "xyz" ; file name to open.
Первое, что вы заметите, это то, что есть звонок на open
. Другими словами, это функция. В поле зрения нет int 80
или sysenter
, который является механизмом, используемым для правильных системных вызовов (в любом случае, на моей платформе - YMMV).
Функции-оболочки в libc - это место, где выполняется фактическая работа с доступом к интерфейсу системного вызова.
Отрывок из Википедии о системных вызовах :
Обычно системы предоставляют библиотеку, которая находится между обычными программами и операционной системой, обычно это реализация библиотеки C (libc), например, glibc. Эта библиотека существует между ОС и приложением и увеличивает переносимость.
В системах, основанных на exokernel, библиотека особенно важна как посредник. В exokernels библиотеки защищают пользовательские приложения от API ядра очень низкого уровня и обеспечивают абстракции и управление ресурсами.
Термины «системный вызов» и «системный вызов» часто неправильно используются для обозначения стандартных функций библиотеки C, особенно тех, которые выполняют функцию оболочки для соответствующих системных вызовов с тем же именем. Вызов самой функции библиотеки не вызывает переключение в режим ядра (если выполнение не было уже в режиме ядра) и обычно является обычным вызовом подпрограммы (то есть с использованием инструкции сборки "CALL" в некоторых ISA). Реальный системный вызов передает управление ядру (и в большей степени зависит от реализации, чем абстрагирующий его библиотечный вызов). Например, fork
и execve
являются функциями GLIBC, которые, в свою очередь, вызывают системные вызовы fork
и execve
.
И, после небольшого поиска, функция __open
найдена в glibc 2.9 в файле io/open.c
и weakref
'преобразована в open
. Если вы выполните:
nm /usr/lib/libc.a | egrep 'W __open$|W open$'
вы можете увидеть их там:
00000000 W __open
00000000 W open