Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Du 22 au 24 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. Programmation système
  3. Introduction aux appels système Linux
Extrait - Programmation système Maîtrisez les appels système Linux avec le langage C (Nouvelle édition)
Extraits du livre
Programmation système Maîtrisez les appels système Linux avec le langage C (Nouvelle édition)
1 avis
Revenir à la page d'achat du livre

Introduction aux appels système Linux

Notion d’appel système

Les appels système constituent une interface entre les applications et le noyau du système d’exploitation. Ils permettent aux programmes de demander au noyau d’exécuter des opérations sur les objets qu’il gère (périphériques, mémoire, processeurs, réseau, etc.) et auxquels ils n’ont pas directement accès.

1. Rôle du noyau

Le noyau Linux est chargé de gérer les ressources matérielles de la machine et de les mettre à la disposition des différents programmes s’exécutant sur cette machine. Parmi ses principales tâches, on peut citer :

  • Gestion du ou des microprocesseurs : il donne accès au(x) processeur(s) aux différents programmes, en fonction de leur priorité, afin que tous puissent y accéder et qu’un programme ne puisse pas monopoliser le ou les processeurs (multitâche préemptif).

  • Gestion des périphériques : en coopération avec les contrôleurs de périphériques (drivers), il gère les différents périphériques matériels (devices) et traite les demandes des programmes qui veulent y accéder.

  • Gestion de la mémoire physique et virtuelle : il détermine le partage de la mémoire entre lui-même et les programmes et gère un mécanisme de mémoire virtuelle permettant d’allouer davantage de mémoire que la machine n’en possède physiquement.

  • Gestion du stockage : il gère l’ensemble des périphériques de stockage (avec des pilotes de périphériques et des pilotes de systèmes de fichiers) et présente aux programmes une interface d’accès unique, sous forme d’une arborescence de répertoires et de fichiers, construite à partir de différents systèmes de fichiers.

  • Gestion du réseau : il prend en charge la communication sur les réseaux auxquels participe la machine, via les cartes d’interface réseau et leurs pilotes, et permet aux différents programmes d’émettre et de recevoir des messages.

  • Gestion des processus : il assure le chargement, l’exécution, le contrôle et la terminaison des programmes...

Normes et standards

Les systèmes de type Unix ont fait l’objet de différentes normalisations, que ce soit par des organismes internationaux de normalisation ou par des consortiums (constitués de constructeurs, d’éditeurs de logiciels et d’autres acteurs du monde Unix), dans le but de faciliter le portage des applications et l’interopérabilité des systèmes.

En tant que système « Unix-like », Linux implémente la plupart de ces normes et standards, tout en proposant quelques spécificités.

Les principales normes et standards concernant les appels système sont les suivants :

1. POSIX (Portable Operating System Interface X)

L’IEEE (Institute of Electrical and Electronic Engineers) a défini un ensemble de normes pour les systèmes ouverts (en s’inspirant particulièrement de ceux de type Unix) : POSIX (Portable Operating System Interface X). Ces normes s’appliquent au système d’exploitation et ont pour objectif de faciliter la portabilité des applications entre les différents systèmes.

Elles ont connu différentes évolutions, prenant en compte différents niveaux d’interface (appels système, interpréteur de commande, commandes de bases, etc.), et ont été adoptées par l’ISO (International Standard...

Documentation

Les appels système et leurs fonctions enveloppes, sont documentés, entre autres, dans la section 2 du manuel, accessible par la commande man.

Cette section contient une partie intro, décrivant les caractéristiques générales des appels système, et une entrée par appel système (ou par ensemble d’appels système de nature similaire). Pour chaque appel, sont spécifiés sa syntaxe générale, les fichiers d’en-tête nécessaires à son utilisation, les différents paramètres qu’il attend, les codes retours susceptibles d’être reçus et sa conformité aux différentes normes.

Les types redéfinis, déclarés dans le fichier d’en-tête sys/types.h, sont décrits dans la section 5 du manuel : man 5 types.

Les codes erreurs et les constantes symboliques qui leur correspondent, sont documentés par la commande : man errno.

Exemple

man 2 unlink

images/01RI001.png
images/01RI002.png

Selon les distributions, le manuel peut être en français ou uniquement en anglais. 

Portabilité et types

Comme nous l’avons vu, les appels système Linux sont, sauf exception, conformes aux différentes normes du monde Unix, en particulier POSIX et SUS. Cela permet aux programmes qui les utilisent d’être facilement portables sur les différents systèmes de type Unix (Linux, HP-UX, MacOS, BSD*, etc.).

Pour renforcer cette portabilité et masquer les différences d’architecture matérielle, des types redéfinis ont été inclus dans les spécifications SUS (et repris dans POSIX.1).

Ils sont implémentés par des fichiers d’en-tête, le principal étant sys/types.h. Il est conseillé de les utiliser, de façon à assurer une bonne portabilité pour les programmes.

Beaucoup de ces types correspondent à des entiers. Ils permettent en particulier de contourner les problèmes liés aux différences de longueur des entiers, entre systèmes 32 bits ou 64 bits, ou en cas d’évolution des valeurs admises pour certains objets (extension d’un identifiant, initialement sur 16 ou 32 bits, en 64 bits ou davantage).

Ces types redéfinis, basés sur un entier, peuvent poser problème quand on souhaite afficher leur valeur, à des fins de débogage par exemple, avec une fonction de type printf(). On peut dans ce cas demander un affichage en forçant...

Gestion des erreurs

Presque tous les appels système retournent une valeur indiquant si l’appel a réussi ou non. Il est bien sûr très important de vérifier ce code retour, pour s’assurer que l’appel s’est déroulé correctement, sans quoi des erreurs graves et difficiles à diagnostiquer peuvent se produire à l’exécution du programme.

La documentation de chaque appel système (man 2) décrit l’ensemble des codes retours qu’il est susceptible de retourner.

Quelques appels système n’échouent jamais (getpid() par exemple, qui retourne l’identifiant du processus exécutant le programme).

1. Code retour et variable errno

La plupart des appels système retournent -1 en cas d’erreur et positionnent la variable globale d’erreur errno. Cette variable est définie dans le fichier d’en-tête errno.h, qui spécifie également une série de constantes symboliques pour les différentes valeurs d’erreurs possibles, toutes commençant par la lettre E. Elles sont décrites dans la documentation, accessible par la commande man errno.

Un appel système réussi ne réinitialise pas la variable errno à zéro, elle conserve donc la valeur de l’erreur retournée par le dernier appel infructueux. Quelques appels système...

Un premier programme système

Nous allons écrire un petit utilitaire, taillefic.c, qui affiche la taille en octets du fichier dont on lui passe le chemin d’accès en argument :

taillefic CheminFichier 

Pour cela, nous utiliserons l’appel système stat().

Nous désignerons désormais les appels système directement par leur fonction enveloppe, sauf quand cela prête à confusion.

1. Documentation de l’appel système

Pour obtenir la documentation de l’appel système, nous pouvons accéder à sa description dans la section 2 du manuel.

Exemple

Voici un extrait de l’affichage obtenu sur une distribution Linux CentOS :

man 2 stat 
STAT(2)                              Manuel du programmeur Linux 
STAT(2) 
NOM 
      stat, fstat, lstat - Obtenir l'état d'un fichier (file status) 
SYNOPSIS 
      #include <sys/types.h> 
      #include <sys/stat.h> 
      #include <unistd.h> 
      int stat(const char *path, struct stat *buf); 
      int fstat(int fd, struct stat *buf); 
      int lstat(const char *path, struct stat *buf); 
DESCRIPTION 
      Ces  fonctions renvoient des informations à propos du fichier 
indiqué. Vous n'avez besoin d'aucun droit d'accès au fichier pour obtenir ...