Какой заголовочный файл номеров системных вызовов правильный? - PullRequest
0 голосов
/ 02 ноября 2018

Я недавно занялся кодированием ядра и нашел 2 unistd.h файлов.

Местоположение первого: /usr/include/asm/unistd.h. Второй из исходного кода ядра: linux/include/uapi/asm-generic/unistd.h. Версия исходного кода совпадает с версией моего ядра, но два заголовочных файла отличаются друг от друга.

/usr/include/asm/unistd.h (с моего компьютера):

#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5
#define __NR_lstat 6
#define __NR_poll 7
#define __NR_lseek 8
#define __NR_mmap 9

linux/include/uapi/asm-generic/unistd.h (от источника):

#define __NR_io_setup 0
__SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)
#define __NR_io_destroy 1
__SYSCALL(__NR_io_destroy, sys_io_destroy)
#define __NR_io_submit 2
__SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit)
#define __NR_io_cancel 3
__SYSCALL(__NR_io_cancel, sys_io_cancel)
#define __NR_io_getevents 4
__SC_COMP(__NR_io_getevents, sys_io_getevents, compat_sys_io_getevents)

/* fs/xattr.c */
#define __NR_setxattr 5
__SYSCALL(__NR_setxattr, sys_setxattr)
#define __NR_lsetxattr 6
__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
#define __NR_fsetxattr 7
__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
#define __NR_getxattr 8
__SYSCALL(__NR_getxattr, sys_getxattr)
#define __NR_lgetxattr 9

Какая разница? Какой из них мне следует использовать для индексации sys_call_table?

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Это действительно зависит от архитектуры, которую вы ищете. Это изменяется от арки к арке и обычно помещается где-нибудь в папке arch/$ARCH. Для встроенных архитектур это обычно жестко закодированная таблица, которая может даже измениться для разных вариантов.

Для x86 / 64 эта таблица автоматически генерируется во время сборки, как вы можете видеть в arch / x86 / Makefile

syscall32 := $(srctree)/$(src)/syscall_32.tbl
syscall64 := $(srctree)/$(src)/syscall_64.tbl
...
$(uapi)/unistd_32.h: $(syscall32) $(syshdr)
    $(call if_changed,syshdr)
...
$(uapi)/unistd_64.h: $(syscall64) $(syshdr)
    $(call if_changed,syshdr)

Который в основном вызывает скрипт arch/x86/entry/syscalls/syscallhdr.sh, который будет автоматически генерировать ваши unistd_32.h / unistd_x32.h / unistd_64.h файлы в соответствии с вашими menuconfig.

Это означает, что если вы ищете эти фактические таблицы системных вызовов для x86 / x64, они находятся здесь: arch/x86/entry/syscalls/syscall_32.tbl / arch/x86/entry/syscalls/syscall_64.tbl

0 голосов
/ 02 ноября 2018

asm-generic - это шаблонная версия, которую можно использовать, если вы разрабатываете новую архитектуру для ядра. Я полагаю, вы обнаружите, что на самом деле в исходном коде ядра существует множество версий unistd.h, потому что порядок системных вызовов (и, действительно, наличие системных вызовов) варьируется в зависимости от архитектуры. Попробуйте это из корня вашей исходной иерархии ядра:

find . -name 'unistd*.h'

В частности, для x86 uapi версия генерируется при сборке ядра. См. Makefile и различные *.tbl файлы в каталоге arch/x86/entry/syscalls/. Это приводит к генерации файлов:

arch/x86/include/generated/uapi/asm/unistd_64.h
arch/x86/include/generated/uapi/asm/unistd_32.h
arch/x86/include/generated/uapi/asm/unistd_x32.h

(все они #include d из файла-заглушки unistd.h).

В конечном итоге создание linux-дистрибутива зависит от конкретной архитектуры, поэтому создатель дистрибутива должен скопировать правильные файлы unistd.h в какое-то подходящее место в иерархии /usr/include. (И, конечно, ваш libc также должен быть скомпилирован с правильной версией, чтобы обычные системные вызовы libc работали правильно.)

Таким образом, версия в /usr/include/asm имела лучше , соответствующую вашему работающему ядру, иначе будет невозможно правильно сгенерировать специальный системный вызов из пользовательского процесса в вашей системе, но вы не должен использовать его в исходной иерархии ядра, потому что категорически исходная иерархия ядра никогда не опирается на заголовки пространства пользователя. В исходном коде ядра механизм индексации этой таблицы зависит от архитектуры, поскольку сама структура и порядок таблицы зависят от архитектуры, и только специфический для архитектуры код (код записи системного вызова) обычно обращается к таблице, так что только Код "должен знать" правильные индексы.

Теперь, если вы создаете новый системный вызов, вам нужно будет определить его номер во всех unistd.h файлах для всех архитектур, в которых вы хотите, чтобы он появлялся.

...