Appels système pris en charge lors de l'exécution du noyau

9

Existe-t-il un moyen d'obtenir le nombre ou la liste des appels système pris en charge par le noyau Linux en cours d'exécution? Je veux donc trouver un moyen de «lire» la table syscall d'un noyau en cours d'exécution.

Swair
la source

Réponses:

15

Le fichier /proc/kallsymsrépertorie tous les symboles du noyau en cours d'exécution. Par convention, les appels système ont un nom commençant par sys_. Sur un système 64 bits, les appels système pour les programmes 32 bits ont un nom commençant par sys32_. Strictement parlant, cela répertorie les fonctions internes du noyau, pas les appels système, mais je pense que la correspondance fonctionne (chaque appel système appelle une fonction interne du noyau pour faire le travail, et je pense que le nom est toujours le nom de l'appel système avec sys_préfixé ).

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

Il ne s'agit généralement pas d'informations utiles, car les appels système changent très lentement. Les composants facultatifs fournissent des fonctionnalités en termes d'appels système existants, en utilisant des fonctionnalités générales telles que les périphériques (avec ioctl quand readet writene le coupent pas), les systèmes de fichiers, les sockets, etc. La détermination de la liste des appels système pris en charge ne vous dira rien sur les fonctionnalités que le système prend en charge. D'autres noms de fonctions internes ne seront pas utiles non plus car ils changent très rapidement: le nom de la fonction qui implémente certaines fonctionnalités sur une version du noyau peut changer sur la version suivante.

Gilles 'SO- arrête d'être méchant'
la source
+1. C'est ce que je voulais dire quand j'ai dit "je laisserai quelqu'un avec plus d'expérience que moi vous répondre" . De plus, comme il /proc/kallsymspeut être manipulé comme n'importe quel autre fichier, il devient assez facile de l'utiliser dans un programme.
John WH Smith
2
@JohnWHSmith «Peut être manipulé comme n'importe quel autre fichier»… avec la mise en garde que sur les systèmes avec noyau ASLR, ce fichier ne doit être lisible que par root.
Gilles 'SO- arrête d'être méchant'
7

TL; DR

J'ai continué à trouver de nouvelles alternatives lors de l'écriture de cette réponse, alors j'ai juste écrit un peu de détails sur chacun d'eux et fait quelques statistiques. Fondamentalement, vous pouvez soit:

  • Lisez la réponse de Gilles, qui fournit un moyen propre et rapide de le faire (repose sur /proc).
  • Utilisez les ressources de documentation.
  • Utilisez les fichiers d'en-tête C de votre système.
  • Utilisez le code source du noyau lui-même.
  • Utilisez le /sysrépertoire.

Après avoir fait le calcul, je recommanderais (parmi mes alternatives) d'utiliser le /syssystème de fichiers, car il semble donner le meilleur résultat en termes de nombre d'appels système. Vous pouvez passer directement à cette section si vous ne voulez pas en savoir plus sur les autres astuces.

Utilisation des ressources documentaires

Bien que vous puissiez en manquer certains, vous pouvez utiliser apropospour répertorier toutes les pages de manuel appartenant à la section 2 (appels système):

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

Supprimez columnsi vous ne voulez pas de sortie en colonnes fantaisie.

Je viens de le découvrir, mais il existe une page de manuel Linux sur les appels système, et vous pourrez en trouver la plupart.

$ man syscalls

Je suis également tombé sur ces deux sites web qui pourraient être intéressants:

Utilisation des fichiers d'en-tête

Edit: Maintenant, quand il s'agit de déterminer par programmation (ou du moins, sans s'appuyer sur des fonctionnalités documentées) quels appels système sont disponibles, j'ai peur que le noyau ne garde pas une table de ses appels système, du moins pas sous la forme de une liste de chaînes (comme vous vous attendez probablement à les manipuler). À ce niveau, nous parlons plus d'adresses de fonctions et de pointeurs, plutôt que de noms de fonctions.

Je viens de parcourir mon /usr/includerépertoire et j'ai grepnoté quelques choses: vous pourriez trouver les répertoires suivants intéressants. Certains d'entre eux peuvent être différents sur votre machine, selon votre architecture et votre distribution, mais je suis sûr que vous pourrez les adapter.

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

En recherchant des définitions de fonctions dans ce fichier, vous rencontrerez de nombreux appels système, même s'ils n'y seront pas entièrement définis. J'ai exécuté quelques greps dans ces répertoires et j'ai pu trouver des mentions de certains appels système. Voici un exemple:

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

Donc, je suppose qu'une autre façon d'en trouver certains serait:

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

Utilisation du code source du noyau et de sa table syscall

Une autre solution consiste à utiliser le code source du noyau lui-même (et pas seulement les en-têtes!), Et à trouver un moyen de le rechercher efficacement. Depuis que le noyau a validé 303395ac3bf3e2cb488435537d416bc840438fcb , vous pourriez trouver cela un peu plus facile qu'auparavant. Voici un exemple pour 3.13 (qui est mon noyau):

$ 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

Maintenant que vous avez la table syscalls, parcourez-la:

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

Vous pouvez trouver un moyen, en utilisant unameet arch, pour télécharger le tblfichier directement depuis git.kernel.org , en fonction de la version et de l'architecture de votre noyau en cours d'exécution.

Utilisation du /syssystème de fichiers

La réponse de Gilles m'a donné un peu d'inspiration, et vous pouvez trouver ces appels système à l'intérieur /sys/kernel/debug/tracing/events/syscalls. Ce répertoire est utilisé pour surveiller l'utilisation de chaque appel système sur le système. Chaque syscall contient deux répertoires:

  • sys_enter_ [syscall]
  • sys_exit_ [syscall]

Par conséquent, l' utilisation ls, grepet cut...

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

Statistiques

Sur mon système:

  • L'utilisation des pages de manuel a révélé 440 appels système.
  • grep-la présence __SYSCALLdans les fichiers d'en-tête a révélé 212 appels système.
  • La lecture de la table syscalls à partir des sources du noyau a révélé 346 appels système.
  • Utilisation de /sys290 appels système révélés.

Maintenant, si je rassemble tout ...

$ 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

Voilà, 707 appels système! Bien sûr, ce nombre reflète une définition très flexible d'un "appel système", car 3.13 est censé fournir 274 appels système uniquement (la lecture /syssemble être la solution la plus proche).

John WH Smith
la source
Je cherche un moyen plus en termes de `` lecture '' de la table des appels système d'une certaine manière plutôt que de savoir lesquels des appels système sont documentés dans les pages de
manuel
Je ne pense pas que le noyau garde une liste de ses appels système, du moins pas comme une liste de chaînes. J'ai édité ma réponse. S'il existe un moyen réel de le faire, je laisserai quelqu'un ayant plus d'expérience que moi vous répondre;)
John WH Smith
donc je me posais la question après avoir ajouté un appel système au noyau et essayer de l'utiliser donnait "fonction non implémentée", et je me demandais s'il y avait un moyen d'obtenir la table syscall pour le noyau actuel. quand je fais '#make install', mets à jour grub et démarre un nouveau noyau, à quelle étape le nouveau noyau obtient-il les fichiers d'inclusion pertinents qui contiennent le nouvel appel système?
Swair
1
Si votre appel système est introuvable, vous ne l'avez pas implémenté correctement. Ma réponse vous indique comment trouver les appels système de Linux, mais pas comment déboguer les vôtres (car ce n'est pas ce que vous demandez). Si vous rencontrez des difficultés pour le développer, vous devez poser une question spécifiquement à ce sujet et éviter le problème XY .
John WH Smith
@swair Il est très inhabituel d'ajouter des fonctionnalités en ajoutant un appel système. Nous ne pouvons pas dire avec certitude ce qui ne va pas puisque vous n'avez fourni aucun code (et si votre question nécessite du code C, c'est hors sujet ici, mais à la maison sur Stack Overflow ). Je soupçonne que vous avez implémenté un appel système (correctement ou non) et que vous essayez de l'utiliser à partir d'un programme C, et que vous manquez l'étape d'écriture d'une fonction C qui fait l'appel système. Un appel système n'est pas un appel de fonction ordinaire.
Gilles 'SO- arrête d'être méchant'
1

Toutes les réponses sont bonnes.

Si vous recherchez un nom d'appel système spécifique:

$ cat /proc/kallsyms | grep <sys_call_name>

Si vous recherchez la liste de tous les appels système:

$ cat /proc/kallsyms
Hamed Kamrava
la source