web-dev-qa-db-fra.com

Comment puis-je trouver les implémentations des appels système du noyau Linux?

J'essaie de comprendre comment une fonction, disons mkdir, fonctionne en regardant la source du noyau. Il s'agit d'une tentative de comprendre les internes du noyau et de naviguer entre les différentes fonctions. Je sais que mkdir est défini dans sys/stat.h. J'ai trouvé le prototype:

/* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

Maintenant, je dois voir dans quel fichier C cette fonction est implémentée. Depuis le répertoire source, j'ai essayé

ack "int mkdir"

qui a affiché

security/inode.c
103:static int mkdir(struct inode *dir, struct dentry *dentry, int mode)

tools/perf/util/util.c
4:int mkdir_p(char *path, mode_t mode)

tools/perf/util/util.h
259:int mkdir_p(char *path, mode_t mode);

Mais aucun d'entre eux ne correspond à la définition de sys/stat.h.

Questions

  1. Quel fichier a l'implémentation mkdir?
  2. Avec une définition de fonction comme celle ci-dessus, comment savoir quel fichier a l'implémentation? Existe-t-il un modèle que le noyau suit pour définir et implémenter des méthodes?

REMARQUE: j'utilise le noyau 2.6.36-rc1 .

376
Navaneeth K N

Les appels système ne sont pas traités comme les appels de fonction standard. Il faut du code spécial pour faire la transition de l'espace utilisateur à l'espace noyau, essentiellement un peu de code d'assemblage en ligne injecté dans votre programme sur le site d'appel. Le code côté noyau qui "intercepte" l'appel système est également un élément de bas niveau que vous n'avez probablement pas besoin de comprendre en profondeur, du moins au début.

Dans include/linux/syscalls.h sous votre répertoire source du noyau, vous trouvez ceci:

asmlinkage long sys_mkdir(const char __user *pathname, int mode);

Ensuite, dans /usr/include/asm*/unistd.h, Vous trouvez ceci:

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

Ce code indique que mkdir(2) est l'appel système # 83. C'est-à-dire que les appels système sont appelés par numéro et non par adresse comme avec un appel de fonction normal dans votre propre programme ou vers une fonction d'une bibliothèque liée à votre programme. Le code de colle d'assemblage en ligne que j'ai mentionné ci-dessus l'utilise pour effectuer la transition de l'espace utilisateur à l'espace noyau, en prenant vos paramètres avec lui.

Une autre preuve que les choses sont un peu étranges ici est qu'il n'y a pas toujours une liste de paramètres stricte pour les appels système: open(2), par exemple, peut prendre 2 ou 3 paramètres. Cela signifie que open(2) est surchargé , une fonctionnalité de C++, pas C, mais l'interface syscall est compatible C. (Ce n'est pas la même chose que C fonction varargs , qui permet à une seule fonction de prendre un nombre variable d'arguments.)

Pour répondre à votre première question, il n'y a pas de fichier unique où mkdir() existe. Linux prend en charge de nombreux systèmes de fichiers différents et chacun a sa propre implémentation de l'opération "mkdir". La couche d'abstraction qui permet au noyau de cacher tout ce qui se cache derrière un seul appel système s'appelle VFS . Donc, vous voulez probablement commencer à creuser dans fs/namei.c, Avec vfs_mkdir(). Les implémentations réelles du code de modification du système de fichiers de bas niveau sont ailleurs. Par exemple, l'implémentation ext4 est appelée ext4_mkdir(), définie dans fs/ext4/namei.c .

Quant à votre deuxième question, oui, il y a des modèles à tout cela, mais pas une seule règle. Ce dont vous avez réellement besoin, c'est d'une compréhension assez large du fonctionnement du noyau afin de savoir où rechercher un appel système particulier. Tous les appels système n'impliquent pas le VFS, donc leurs chaînes d'appels côté noyau ne démarrent pas toutes dans fs/namei.c. mmap(2), par exemple, commence par mm/mmap.c , car il fait partie du sous-système de gestion de la mémoire ("mm") du noyau.

Je vous recommande d'obtenir une copie de " nderstanding the Linux Kernel " de Bovet et Cesati.

388
Warren Young

Cela ne répond probablement pas directement à votre question, mais j'ai trouvé que strace était vraiment cool quand on essayait de comprendre les appels système sous-jacents, en action, qui sont faits même pour les commandes Shell les plus simples. par exemple.

strace -o trace.txt mkdir mynewdir

Le système appelle la commande mkdir mynewdir sera sauvegardé dans trace.txt pour votre plus grand plaisir.

86
Banjer

Un bon endroit pour lire la source du noyau Linux est la référence croisée Linux (LXR) ¹. Les recherches renvoient des correspondances typées (prototypes de fonctions, déclarations de variables, etc.) en plus des résultats de recherche de texte libre, donc c'est plus pratique qu'un simple grep (et plus rapide aussi).

LXR ne développe pas les définitions de préprocesseur. Les appels système ont leur nom mutilé par le préprocesseur partout. Cependant, la plupart (tous?) Des appels système sont définis avec l'un des SYSCALL_DEFINEx familles de macros. Puisque mkdir prend deux arguments, une recherche pour SYSCALL_DEFINE2(mkdir conduit à déclaration du mkdir syscall :

SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
{
    return sys_mkdirat(AT_FDCWD, pathname, mode);
}

d'accord, sys_mkdirat signifie que c'est le syscall mkdirat, donc cliquer dessus ne vous mène qu'à la déclaration dans include/linux/syscalls.h, mais la définition est juste au-dessus.

La tâche principale de mkdirat est d'appeler vfs_mkdir (VFS est la couche générique du système de fichiers). Cliquer sur cela montre deux résultats de recherche: la déclaration dans include/linux/fs.h, et la définition quelques lignes ci-dessus. Le travail principal de vfs_mkdir consiste à appeler l'implémentation spécifique au système de fichiers: dir->i_op->mkdir. Pour trouver comment ceci est implémenté, vous devez vous tourner vers l'implémentation du système de fichiers individuel, et il n'y a pas de règle stricte - il pourrait même s'agir d'un module en dehors de l'arborescence du noyau.

¹ LXR est un programme d'indexation. Il existe plusieurs sites Web qui fournissent une interface à LXR, avec des ensembles légèrement différents de versions connues et des interfaces Web légèrement différentes. Ils ont tendance à aller et venir, donc si celui auquel vous êtes habitué n'est pas disponible, faites une recherche sur le Web pour "référence croisée Linux" pour en trouver un autre.

Les appels système sont généralement enveloppés dans la macro SYSCALL_DEFINEx(), c'est pourquoi un simple grep ne les trouve pas:

fs/namei.c:SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)

Le nom de la fonction finale après la macro est développée finit par être sys_mkdir. La macro SYSCALL_DEFINEx() ajoute des éléments passe-partout comme le code de traçage que chaque définition syscall doit avoir.

22
stefanha

Remarque: le fichier .h ne définir la fonction. C'est déclaré dans ce fichier .h et défini (implémenté) ailleurs. Cela permet au compilateur d'inclure des informations sur la signature de la fonction (prototype) pour permettre la vérification du type des arguments et faire correspondre les types de retour à tous les contextes d'appel dans votre code.

En général, les fichiers .h (en-tête) en C sont utilisés pour déclarer des fonctions et définir des macros.

mkdir en particulier est un appel système. Il peut y avoir un GNU libc wrapper autour de cet appel système (presque certainement, en fait). La véritable implémentation du noyau de mkdir peut être trouvée en recherchant les sources du noyau et les appels système en particulier.

Notez qu'il y aura également une implémentation d'une sorte de code de création de répertoire pour chaque système de fichiers. La couche VFS (système de fichiers virtuel) fournit une API commune à laquelle la couche d'appel système peut appeler. Chaque système de fichiers doit enregistrer des fonctions pour la couche VFS à appeler. Cela permet à différents systèmes de fichiers d'implémenter leur propre sémantique sur la façon dont les répertoires sont structurés (par exemple, s'ils sont stockés à l'aide d'une sorte de schéma de hachage pour rendre la recherche d'entrées spécifiques plus efficace). Je mentionne cela parce que vous risquez de trébucher sur ces fonctions de création de répertoires spécifiques au système de fichiers si vous recherchez l'arborescence des sources du noyau Linux.

17
Jim Dennis

Aucune des implémentations que vous avez trouvées ne correspond au prototype dans sys/stat.h Peut-être que la recherche d'une instruction include avec ce fichier d'en-tête serait plus réussie?

8
greg0ire

Voici quelques articles de blog vraiment géniaux décrivant diverses techniques pour rechercher le code source du noyau de bas niveau.

6
An̲̳̳drew