Системные вызовы поддерживаются в работающем ядре


9

Есть ли способ узнать количество или список системных вызовов, поддерживаемых в настоящее время работающим ядром Linux? Поэтому я хочу найти способ «прочитать» таблицу системных вызовов работающего ядра.

Ответы:


15

В файле /proc/kallsymsперечислены все символы работающего ядра. По соглашению системные вызовы имеют имя, начинающееся с sys_. В 64-битной системе системные вызовы для 32-битных программ начинаются с имени sys32_. Строго говоря, здесь перечислены внутренние функции ядра, а не системный вызов, но я думаю, что переписка работает (каждый системный вызов вызывает внутреннюю функцию ядра для выполнения этой работы, и я думаю, что имя - это всегда имя системного вызова с sys_префиксом). ).

</proc/kallsyms sed -n 's/.* sys_//p'

Обычно это бесполезная информация, потому что системные вызовы меняются очень медленно. Дополнительные компоненты обеспечивают функциональные возможности с точки зрения существующих системных вызовов, используя общие функции , такие как устройства (с IOCTL , когда readи writeне резать), файловые системы, розетки и т.д. Определение списка поддерживаемых системных вызовов не будет ничего рассказывать об особенностях что система поддерживает. Другие внутренние имена функций также не помогут, потому что они меняются очень быстро: имя функции, реализующей некоторые функции в одной версии ядра, может измениться в следующей версии.


+1. Вот что я имел в виду, когда сказал: «Я позволю кому-то с большим опытом, чем я, ответить вам» . Кроме того, поскольку им /proc/kallsymsможно манипулировать, как и любым другим файлом, его довольно просто использовать в программе.
Джон У. С. Смит,

2
@JohnWHSmith «Можно манипулировать как любым другим файлом»… с оговоркой, что в системах с ядром ASLR этот файл должен быть доступен для чтения только пользователю root.
Жиль "ТАК ... перестать быть злым"

7

TL; DR

Я продолжал находить новые альтернативы, когда писал этот ответ, поэтому я просто написал немного деталей о каждом из них и сделал некоторые статистические данные. По сути, вы можете:

  • Прочитайте ответ Жиля, который обеспечивает чистый и быстрый способ сделать это (полагается на /proc).
  • Используйте ресурсы документации.
  • Используйте заголовочные файлы C вашей системы.
  • Используйте исходный код ядра.
  • Используйте /sysкаталог.

После выполнения математики я бы порекомендовал (среди моих альтернатив) использовать /sysфайловую систему, поскольку она, похоже, дает лучший результат с точки зрения количества системных вызовов. Вы можете перейти прямо к этому разделу, если не хотите читать о других хитростях.

Использование ресурсов документации

Хотя вы можете пропустить некоторые из них, вы можете использовать aproposдля просмотра всех man-страниц, относящихся к разделу 2 (системные вызовы):

$ apropos -s2 . | awk '{print $1}' | column

Удалите, columnесли вы не хотите показывать колонки.

Я только что узнал, но есть справочная страница Linux о системных вызовах, и вы сможете найти большинство из них в ней.

$ man syscalls

Я также наткнулся на эти два веб-сайта, которые могут быть интересны:

Использование заголовочных файлов

Изменить: Теперь, когда речь идет о программном (или по крайней мере, не полагаясь на документированные возможности) определении доступных системных вызовов, я боюсь, что ядро ​​не хранит таблицу своих системных вызовов, по крайней мере, не в форме список строк (как вы, вероятно, ожидаете манипулировать ими). На этом уровне мы больше говорим об адресах и указателях функций, а не об именах функций.

Я только что просмотрел мой /usr/includeкаталог и grep-ed несколько вещей: вы можете найти следующие каталоги интересными. Некоторые из них могут отличаться на вашей машине, в зависимости от вашей архитектуры и дистрибутива, но я уверен, что вы сможете адаптировать их.

  • / USR / включать / Linux
  • / USR / включать / x86_64-Linux-гну
  • / USR / включать / SYS
  • / USR / включать / ASM-родовое

Посмотрев определения функций в этом файле, вы столкнетесь со многими системными вызовами, даже если они там не будут полностью определены. Я провел несколько grepсекунд в этих каталогах и смог найти упоминания о некоторых системных вызовах. Вот пример:

$ grep 'sys_exit' /usr/include -R
asm-generic/unistd.h:__SYSCALL(__NR_exit, sys_exit)

Итак, я предполагаю, что другой способ найти некоторые из них будет:

$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')'

Использование исходного кода ядра и его таблицы системных вызовов

Другое решение - использовать сам исходный код ядра (а не только заголовки!) И найти способ его эффективного поиска. Поскольку ядро ​​совершает 303395ac3bf3e2cb488435537d416bc840438fcb , вы можете найти это немного проще, чем раньше. Вот пример для 3.13 (который является моим ядром):

$ wget https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/arch/x86/syscalls/syscall_64.tbl?id=refs/tags/v3.13 -O syscall_64.tbl

Теперь, когда вы получили реальную таблицу системных вызовов, просто просмотрите ее:

$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl

Вы можете найти способ, используя unameи arch, загрузить tblфайл прямо с git.kernel.org , в зависимости от используемой версии ядра и архитектуры.

Использование /sysфайловой системы

Ответ Жиля дал мне немного вдохновения, и вы можете найти эти системные вызовы внутри /sys/kernel/debug/tracing/events/syscalls. Этот каталог используется для мониторинга использования каждого системного вызова в системе. Каждый системный вызов имеет две директории:

  • sys_enter_ [системный вызов]
  • sys_exit_ [системный вызов]

Поэтому, используя ls, grepи cut...

$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3

Статистика

В моей системе:

  • Использование man-страниц выявило 440 системных вызовов.
  • grep-ing для __SYSCALLв заголовочных файлах выявлено 212 системных вызовов.
  • Чтение таблицы системных вызовов из источников ядра выявило 346 системных вызовов.
  • С помощью /sysвыявлено 290 системных вызовов.

Теперь, если я соберу все вместе ...

$ apropos -s2 . | awk '{print $1}' > system_calls.txt
$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')' >> system_calls.txt
$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl >> system_calls.txt
$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3 >> system_calls.txt

$ sort < system_calls.txt | uniq | wc -l
707

Ну вот, 707 системных звонков! Конечно, это число отражает очень гибкое определение «системного вызова», поскольку предполагается , что 3.13 обеспечивает только 274 системных вызова (чтение /sysявляется наиболее близким решением).


Я ищу способ «чтения» таблицы системных вызовов каким-то образом, а не выяснения того, какие системные вызовы описаны в
справочных

Я не думаю, что ядро ​​хранит список своих системных вызовов, по крайней мере, не как список строк. Я отредактировал свой ответ. Если есть реальный способ сделать это, я позволю кому-то с большим опытом, чем я, ответить вам;)
Джон В. У. Смит,

поэтому мне было интересно об этом после того, как я добавил системный вызов в ядро ​​и попытался использовать его, давая «функцию не реализована», и я подумал, есть ли какой-нибудь способ получить таблицу syscall для текущего ядра. когда я выполняю '#make install', обновляю grub и запускаю новое ядро, на каком этапе новое ядро ​​получает соответствующие включаемые файлы, содержащие новый системный вызов?
Swair

1
Если ваш системный вызов не найден, значит, вы неправильно его реализовали. Мой ответ говорит вам, как найти системные вызовы Linux, но не как отлаживать свои собственные (поскольку это не то, что вы просите). Если у вас возникли проблемы с его разработкой, вам следует задать вопрос именно об этом и избежать проблемы XY .
Джон У. С. Смит,

@swair Очень необычно добавлять функциональность, добавляя системный вызов. Мы не можем точно сказать, что не так, так как вы не предоставили никакого кода (и если ваш вопрос требует кода на C, здесь это не по теме, но дома на Stack Overflow ). Я подозреваю, что вы реализовали системный вызов (правильно или нет), и что вы пытаетесь использовать его из программы на C, и что вам не хватает этапа написания функции C, которая выполняет системный вызов. Системный вызов - это не обычный вызов функции.
Жиль "ТАК ... перестать быть злым"

1

Все ответы в порядке.

Если вы ищете конкретное имя системного вызова:

$ cat /proc/kallsyms | grep <sys_call_name>

Если вы ищете список всех системных вызовов:

$ cat /proc/kallsyms
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.