Системні дзвінки, що підтримуються у запуску ядра


9

Чи є спосіб отримати кількість або список системних дзвінків, підтримуваних поточним Linux Kernel? Тому я хочу знайти спосіб "прочитати" таблицю syscall запущеного ядра.

Відповіді:


15

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

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

Зазвичай це не корисна інформація, оскільки системні дзвінки змінюються дуже повільно. Додаткові компоненти забезпечують функціональні можливості з точки зору існуючих системних викликів, використовуючи загальні функції , такі як пристрої (з IOCTL , коли readі writeне різати), файлові системи, розетки і т.д. Визначення списку підтримуваних системних викликів не буде нічого розповідати про особливості що система підтримує. Інші внутрішні назви функцій також не допоможуть, оскільки вони змінюються дуже швидко: назва функції, яка реалізує якусь функцію в одній версії ядра, може змінитися на наступній версії.


+1. Тепер я це мав на увазі, коли я сказав: "Я дозволю, щоб хтось із більшим досвідом, ніж я, відповідав вам" . Крім того, оскільки ним /proc/kallsymsможна маніпулювати, як і будь-яким іншим файлом, користуватися ним у програмі стає досить просто.
Джон У. Сміт

2
@JohnWHSmith "Можна керувати, як будь-яким іншим файлом" ... із застереженням, що в системах з ядром ASLR цей файл має читатись лише корінь.
Жил "ТАК - перестань бути злим"

7

TL; DR

Я продовжував знаходити нові альтернативи, коли писав цю відповідь, тому просто написав трохи деталей про кожну з них і зробив кілька статистичних даних. В основному, ви можете:

  • Прочитайте відповідь Гілла, яка забезпечує чистий і швидкий спосіб зробити це (покладається на /proc).
  • Використовуйте ресурси документації.
  • Використовуйте файли заголовків C вашої системи.
  • Використовуйте сам вихідний код ядра.
  • Скористайтеся /sysкаталогом.

Займаючись математикою, я б рекомендував (серед моїх альтернатив) використовувати /sysфайлову систему, оскільки це, здається, дає найкращий результат за кількістю системних викликів. Ви можете перейти прямо до цього розділу, якщо не хочете читати про інші хитрощі.

Використання ресурсів документації

Незважаючи на те, що ви можете пропустити деякі з них, ви можете скористатись aproposсписком усіх мандатів, що належать до розділу 2 (системні дзвінки):

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

Видаліть, columnякщо ви не хочете вигадливого колонного виводу.

Я щойно це з’ясував, але є сторінка Linux щодо системних викликів, і ви зможете знайти більшість із них у ньому.

$ man syscalls

Я також натрапив на ці два веб-сайти, які можуть бути цікавими:

Використання файлів заголовків

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

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

  • / usr / include / linux
  • / usr / include / x86_64-linux-gnu
  • / usr / include / sys
  • / usr / include / asm-generic

Шукаючи в цьому файлі визначення функцій, ви стикаєтеся з багатьма системними дзвінками, хоча вони там не будуть повністю визначені. Я пробіг декілька greps у цих каталогах, і мені вдалося знайти згадки про деякі системні виклики. Ось приклад:

$ 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 ')'

Використання вихідного коду ядра та його таблиці syscall

Ще одне рішення - використовувати сам вихідний код ядра (а не лише заголовки!) Та знайти спосіб його ефективного пошуку. Оскільки ядро ​​фіксує 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_ [syscall]
  • sys_exit_ [syscall]

Тому, використовуючи ls, grepі cut...

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

Статистика

У моїй системі:

  • За допомогою довідкових сторінок виявлено 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здається, є найближчим рішенням).


Я шукаю спосіб більше в плані «читання» таблиці системних викликів, а не з'ясування того, який із системних викликів задокументований на сторінках man
Swair

Я не думаю, що ядро ​​зберігає список своїх системних викликів, принаймні, не як список рядків. Я відредагував свою відповідь. Якщо є дійсний спосіб зробити це, я дозволю вам відповісти комусь із більшим досвідом, ніж я;)
Джон У. Сміт

тому мені було цікаво про це після того, як я додав системний виклик до ядра і намагався його використовувати, надаючи "функцію не реалізовано", і я задумався, чи є спосіб отримати таблицю 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.