Linux, таблица системных вызовов, 32 и x64

#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:

Я думаю, вы путаете здесь два довольно важных понятия. Для понимания существуют два разных «адреса» как таковых:

  1. Фактические адреса в памяти. Они будут различаться в зависимости от компиляции ядра и, если они не исправлены намеренно (я не верю, что они есть), будут различаться в зависимости от используемого компилятора. Каждое новое ядро из моего дистрибутива имеет разные адреса для функций системного вызова.
  2. Номера системных вызовов. Это целочисленные значения, которые вы используете перед запуском 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.