Системные вызовы и syscall в Linux: как программа стучится в ядро
Каждый раз, когда программа читает файл, открывает сокет или печатает строку в терминал, она не делает это сама. Она просит об этом ядро. Механизм этой просьбы называется системным вызовом syscall.
Что это
Syscall - это запрос программы к ядру на операцию, которую ей не дают сделать напрямую: доступ к диску, сети, памяти, процессам. Это единственный легальный вход из твоего кода внутрь ядра.
Два пространства
Программы работают в
user space с урезанными правами. Ядро и железо живут в
kernel space. Между ними стену ставит сам процессор: приложения крутятся в кольце защиты
ring 3, ядро в
ring 0. Дёрнуть драйвер диска из обычного процесса нельзя, можно только попросить ядро.
Сделано это для изоляции и безопасности. Если бы любой процесс мог писать прямо в железо или в чужую память, один баг ронял бы всю систему. Ядро выступает арбитром: проверяет права, валидирует аргументы и только потом выполняет операцию.
Примеры
Базовые сисколы, на которых держится почти всё:
int fd = open("file.txt", O_RDONLY); // открыть файл
read(fd, buf, 1024); // прочитать данные
write(1, "hello\\n", 6); // записать в stdout
close(fd); // закрыть
А ещё fork() порождает новый процесс, execve() запускает программу, mmap() выделяет память. В Linux x86-64 их несколько сотен.
Под капотом
То, что в C выглядит как обычная функция, на деле оказывается переходом в ядро. Номер сисколла кладётся в регистр rax, аргументы в rdi, rsi, rdx, а инструкция syscall передаёт управление ядру:
mov rax, 1 ; номер вызова write
mov rdi, 1 ; fd = stdout
mov rsi, msg ; адрес буфера
mov rdx, 6 ; длина
syscall ; прыжок в kernel space
libc
Руками syscall почти никто не пишет: между тобой и ядром стоит glibc. Функция write() из unistd.h это тонкая обёртка: разложить аргументы по регистрам и вызвать syscall. Поэтому «функция» и «системный вызов» не одно и то же: printf() это функция libc, а write() под ней уже настоящий syscall.
strace
Хочешь увидеть все сисколы программы вживую:
strace ./program # все вызовы подряд
strace -c ls # сводка с подсчётом и таймингами
Вывод покажет каждый open, read и write с аргументами и кодом возврата. Незаменимо для отладки и реверса.
Итог
Syscall это мост между твоим кодом и ядром. Разберёшься в сисколах и будешь видеть, что программа делает на самом деле: где тормозит, куда лезет и почему падает.
LinuxCamp | #utils
Обсуждение 13
Обсуждение не доступно в веб-версии. Чтобы написать комментарий, перейдите в приложение Telegram.
Обсудить в Telegram