#linux #system #kernel
#linux #система #ядро
Вопрос:
Я не совсем понимаю 1. одинаковы ли адреса системных вызовов для всех машин Linux (или они зависят от параметров компиляции) 2. имеют ли 32×86 и x64 одинаковые адреса системных вызовов? Я нашел несколько ссылок в Интернете, например, swapon имеет адрес x87, но не указан, это 32-разрядная или 64-разрядная версия ядра
Комментарии:
1. Что именно вы подразумеваете под «адресом системного вызова»? номер системного вызова? адрес в памяти библиотеки C для системного вызова? адрес функции реализации ядра?
2. Я думаю, что это системный адрес в ядре, который я нашел в C:UsersekitruDownloadslinux-2.6.39.4archx86includeasm два unistd: unistd32 и unistd64 unistd32:swapon 87 unistd64:swapoff 167 итак, адреса разные, и теперь я понял, почему strace показывает неправильные имена системных вызовов (ОС x64, но программа 32-битная — она вызывает query_module (167), но strace показывает использование swapon).
Ответ №1:
Я думаю, вы путаете здесь два довольно важных понятия. Для понимания существуют два разных «адреса» как таковых:
- Фактические адреса в памяти. Они будут различаться в зависимости от компиляции ядра и, если они не исправлены намеренно (я не верю, что они есть), будут различаться в зависимости от используемого компилятора. Каждое новое ядро из моего дистрибутива имеет разные адреса для функций системного вызова.
-
Номера системных вызовов. Это целочисленные значения, которые вы используете перед запуском
sysenter
(или прерыванием), которые говорят «выполнить системный вызов». Они всегда одинаковы для данного ABI. ABI — это двоичный интерфейс приложения; возможность передавать скомпилированную программу между компьютерами и запускать ее.x86 Linux и x86_64 Linux имеют разные ABI, и поэтому номера системных вызовов разные. Но между двумя разными дистрибутивами, работающими под управлением x86 Linux, ABI одинаковый, поэтому эти системы совместимы с ABI, и теоретически вы должны иметь возможность переносить программы.
На практике это сложнее (общие библиотеки, пути и т. Д.).
Если вы хотите увидеть адрес функции ядра в вашей системе, и у вас есть System.map
(вероятно, есть), попробуйте:
cat /boot/System.map-`uname -r` | grep funcname
Таблица системных вызовов для вашей системы определена в /usr/include/asm/unistd_32.h
или /usr/include/asm/unistd_64.h
соответственно.
Ответ №2:
В системных вызовах Linux нет адреса. Конечно, они где-то есть, по какому-то адресу в памяти, но вызывающие программы обычно их не знают (или даже не имеют доступа к этой памяти). Обычно они вызываются прерыванием (например, Linux использовал 0x80, MS-Dos, например, использовал 0x21). Вызывающий процесс просто запрашивает программное прерывание, а обработчик прерываний затем обрабатывает системный вызов. Тип вызова и параметры заранее помещаются в определенные регистры, поэтому ядро знает, что делать.
В более современных процессорах разработчик изобрел конкретные инструкции (например, Intel / AMD имеют СИСТЕМНЫЙ ВЫЗОВ / SYSENTER), поэтому не нужно использовать способ прерывания для вызова системных вызовов, но в основном это то же самое с точки зрения пользователя.
Конечно, есть какая-то таблица прерываний, которая отличается в своих записях, в зависимости от того, используете ли вы x64 или 32.