• Aucun résultat trouvé

Gestion des threads au niveau noyau

10 Communication centralisée inter- inter-processus

10.1 Les tubes (pipes)

10.1.2 Les tubes nommés

NAME_MAX. Sur les systèmes GNU il n’y a pas de limite absolue à la longueur du nom d’un fichier, mais certains autres systèmes en ont une.

ENOENT : L’un des répertoire de pathname n’existe pas, ou est un lien symbolique pointant nulle part.

ENOSPC : Le répertoire, ou le système de fichiers, n’a pas assez de place pour un nouveau fichier.

ENOTDIR : Un élément de pathname n’est pas un répertoire.

EROFS : pathname est sur un système de fichiers en lecture seule.

>>

Ensuite, l’utilisation d’un tube nommé ressemble à l’utilisation d’un fichier. L’ouverture se fait à l’aide de la primitive « open() » :

<<

SYNOPSIS

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

int creat(const char *pathname, mode_t mode);

DESCRIPTION

Étant donné le chemin pathname d’un fichier, open() renvoie un descripteur de fichier (petit entier positif ou nul) qui pourra ensuite être utilisé dans d’autres appels système (read(2), write(2), lseek(2), fcntl(2), etc.).

Le descripteur de fichier renvoyé par un appel réussi

sera le plus petit descripteur de fichier non actuellement ouvert par le processus.

Le nouveau descripteur de fichier est configuré pour rester ouvert après un appel à execve(2) (son attribut FD_CLOEXEC décrit dans fcntl(2) est initialement

désactivé). La position dans le fichier est fixée au début du fichier (voir lseek(2)).

Un appel à open() crée une nouvelle description de fichier ouvert, une entrée dans la table de fichiers ouverts du système. Cette entrée enregistre la position dans le fichier et les attributs d’état du fichier

(modifiables par l’opération F_SETFL de fcntl()). Un

descripteur de fichier est une référence à l’une de ces entrées ; cette référence n’est pas modifiée si pathname est ensuite supprimé ou modifié pour correspondre à un autre fichier. La nouvelle description de fichier ouvert n’est initialement partagée avec aucun autre processus, mais ce partage peut apparaître après un fork(2).

Le paramètre flags est l’un des éléments O_RDONLY, O_WRONLY ou O_RDWR qui réclament respectivement l’ouverture du

fichier en lecture seule, écriture seule, ou lecture- écriture.

De plus, zéro ou plus d’attributs de création de fichier et d’attributs d’état de fichier peuvent être spécifiés dans flags avec un OU binaire. Les attributs de création de fichier sont O_CREAT, O_EXCL, O_NOCTTY et O_TRUNC. Les attributs d’état de fichier sont tous les autres attributs listés ci-dessous. La distinction entre ces deux groupes est que les attributs d’état de fichier peuvent être lus et (dans certains cas) modifiés avec fcntl(2). La liste complète des attributs de création et d’état de fichier est la suivante :

O_APPEND :

Le fichier est ouvert en mode « ajout ».

Initialement, et avant chaque write(), la tête de lecture/écriture est placée à la fin du fichier comme avec lseek(). Il y a un risque d’endommager le fichier lorsque O_APPEND est utilisé, sur un système de fichiers NFS, si plusieurs processus tentent d’ajouter des données simultanément au même fichier.

Ceci est dû au fait que NFS ne supporte pas l’opération d’ajout de données dans un fichier, aussi le noyau du client est obligé de la simuler, avec un risque de concurrence des tâches.

O_ASYNC :

Déclencher un signal (SIGIO par défaut, mais peut être changé via fcntl(2)) lorsque la lecture ou l’écriture deviennent possibles sur ce

descripteur. Ceci n’est possible que pour les

terminaux, pseudo-terminaux, sockets et (depuis Linux 2.6) tubes et FIFO. Voir fcntl(2) pour plus de

détails.

O_CREAT :

Créer le fichier s’il n’existe pas. Le possesseur (UID) du fichier est renseigné avec l’UID effectif du processus. Le groupe

propriétaire (GID) du fichier est le GID effectif du processus ou le GID du répertoire parent (ceci dépend du système de fichiers, des options de montage, du mode du répertoire parent, etc.) Voir par exemple les options de montage bsdgroups et sysv groups du

système de fichiers ext2, décrites dans la page mount(8)).

O_DIRECT :

Essayer de minimiser les effets du cache d’entrée- sortie sur ce fichier. Ceci dégradera en général les performances, mais est utilisé dans des

situations spéciales, lorsque les applications

ont leur propres caches. Les entrées-sorties dans le fichier se font directement depuis l’espace

utilisateur, elles sont synchrones (à la fin de read(2) ou write(2), les données ont obligatoirement été transférées). Sous Linux 2.4, la taille des

transferts, l’alignement du tampon et la position dans le fichier doivent être des multiples de la taille de blocs

logiques du système de fichiers. Sous Linux 2.6, un alignement sur des multiples de 512 octets est

suffisant.

Une interface à la sémantique similaire (mais obsolète) pour les périphériques de type bloc est décrite à la page raw(8).

O_DIRECTORY :

Si pathname n’est pas un répertoire, l’ouverture échoue. Cet attribut est spécifique à Linux et fut ajouté dans la version 2.1.126 du noyau, pour éviter des problèmes de dysfonctionnement si opendir(3) est invoqué sur une FIFO ou un périphérique de bande. Cet attribut ne devrait jamais être utilisé ailleurs que dans

l’implémentation de opendir.

O_EXCL :

En conjonction avec O_CREAT, déclenchera une erreur si le fichier existe, et open() échouera. On considère qu’un lien symbolique existe, quel que soit l’endroit où il pointe. O_EXCL ne fonctionne pas sur les systèmes de fichiers NFS. Les programmes qui ont besoin de cette fonctionnalité pour verrouiller des tâches risquent de rencontrer une concurrence critique (race condition). La solution consiste à créer un fichier unique sur le même système de fichiers (par exemple avec le PID et le nom de l’hôte), utiliser link(2) pour créer un lien sur un fichier de verrouillage. Si

link() renvoie 0, le verrouillage est

réussi. Sinon, utiliser stat(2) sur ce fichier unique pour vérifier si le nombre de liens a augmenté jusqu’à 2, auquel cas le verrouillage est également réussi.

O_LARGEFILE :

(LFS) (Ndt : Large Files System) Autoriser

l’ouverture des fichiers dont la taille ne peut pas être représentée avec un off_t (mais qui peut être représentée avec un off64_t).

O_NOATIME :

(Depuis Linux 2.6.8) Ne pas mettre à jour l’heure de dernier accès au fichier (champ st_atime de l’i-noeud) quand le fichier est lu avec read(2). Ce attribut est seulement conçu pour les programmes d’indexation et d’archivage, pour lesquels il peut réduire significativement l’activité du disque.

L’attribut peut ne pas être effectif sur tous les systèmes de fichiers. Par exemple, avec NFS, l’heure d’accès est mise à jour par le serveur.

O_NOCTTY :

Si pathname correspond à un périphérique de terminal - voir tty(4) -, il ne deviendra pas le terminal contrôlant le processus même si celui-ci n’est attaché à aucun autre terminal.

O_NOFOLLOW :

Si pathname est un lien symbolique, l’ouverture échoue. Ceci est une extension FreeBSD, qui fut ajoutée à Linux dans la version 2.1.126. Les liens symboliques se trouvant dans le chemin d’accès proprement dit seront suivis normalement.

O_NONBLOCK ou O_NDELAY :

Le fichier est ouvert en mode « non-bloquant ». Ni la fonction open() ni aucune autre opération ultérieure sur ce fichier ne laissera le processus appelant en attente. Pour la manipulation

des FIFO (tubes nommés), voir également fifo(7). Pour une explication de l’effet de O_NONBLOCK en

conjonction avec les verrouillages impératifs et les bauxs de fichiers, voir fcntl(2).

O_SYNC :

Le fichier est ouvert en écriture synchronisée.

Chaque appel à write() sur le fichier bloquera le processus appelant jusqu’à ce que les données aient été écrites physiquement sur le support matériel (voir la section RESTRICTIONS plus bas).

O_TRUNC :

Si le fichier existe, est un fichier régulier, et est ouvert en écriture (O_RDWR ou O_WRONLY), il sera tronqué à une longueur nulle. Si le fichier est une FIFO ou un périphérique terminal, l’attribut

O_TRUNC est ignoré. Sinon, le comportement de O_TRUNC n’est pas précisé. Sur de nombreuses versions de Linux, il sera ignoré ; sur d’autres versions il déclenchera une erreur).

Certains de ces attributs optionnels peuvent être modifiés par la suite avec la fonction fcntl().

L’argument mode indique les permissions à utiliser si un nouveau fichier est créé. Cette valeur est modifiée par le umask du processus : la véritable valeur utilisée est (mode & ~umask). Notez que ce mode ne s’applique qu’aux accès ultérieurs au fichier nouvellement créé.

L’appel open() qui crée un fichier dont le mode est en lecture seule fournira quand même un descripteur de fichier en lecture et écriture.

Les constantes symboliques suivantes sont disponibles pour mode :

S_IRWXU : 00700 L’utilisateur (propriétaire du fichier) a les autorisations de lecture, écriture, exécution.

S_IRUSR : 00400 L’utilisateur a l’autorisation de lecture.

S_IWUSR : 00200 L’utilisateur a l’autorisation d’écriture.

S_IXUSR : 00100 L’utilisateur a l’autorisation d’exécution.

S_IRWXG : 00070 Le groupe a les autorisations de lecture, écriture, exécution.

S_IRGRP : 00040 Le groupe a l’autorisation de lecture.

S_IWGRP : 00020 Le groupe a l’autorisation d’écriture.

S_IXGRP : 00010 Le groupe a l’autorisation d’exécution.

S_IRWXO : 00007 Tout le monde a les autorisations de lecture, écriture, exécution.

S_IROTH : 00004 Tout le monde a l’autorisation de lecture.

S_IWOTH : 00002 Tout le monde a l’autorisation d’écriture.

S_IXOTH : 00001 Tout le monde a l’autorisation d’exécution.

Le mode devrait toujours être indiqué quand O_CREAT est dans les attributs flags, (il est ignoré dans les autres cas).

creat() est équivalent à open() avec l’attribut flags égal à O_CREAT | O_WRONLY | O_TRUNC.

VALEUR RENVOYÉE

open() et creat() renvoient le nouveau descripteur de

fichier s’ils réussissent, ou -1 s’ils échouent, auquel cas errno contient le code d’erreur.

NOTES

Notez que open() peut ouvrir des fichiers spéciaux mais creat() ne peut pas en créer, il faut utiliser mknod(2) à la place.

Sur les systèmes de fichiers NFS, où la

correspondance d’UID est activée, open() peut renvoyer un descripteur de fichier alors qu’une requête read(2) par exemple sera refusée avec le code d’erreur EACCES.

En effet, c’est parce que le client a effectué open() en vérifiant les autorisations d’accès, mais la correspondance d’UID est calculée par le serveur au moment des requêtes de lecture ou d’écriture.

Si un fichier est créé, ses horodatages st_atime, st_ctime, st_mtime (respectivement heure de dernier accès, de dernière modification d’état, et de dernière modification ; voir stat(2)) sont fixés à

l’heure actuelle, ainsi que les champs st_ctime et st_mtime du répertoire parent. Sinon, si le fichier est modifié à cause de l’attribut O_TRUNC, ses champs st_ctime et st_mtime sont remplis avec l’heure actuelle.

ERREURS

EACCES : L’accès demandé au fichier est interdit, ou la permission de parcours pour l’un des

répertoires du chemin pathname est refusée, ou le fichier n’existe pas encore et le répertoire parent ne permet pas l’écriture. (Voir aussi path_resolution(2).)

EEXIST : pathname existe déjà et O_CREAT et O_EXCL ont été indiqués.

EFAULT : pathname pointe en dehors de l’espace d’adressage accessible

EISDIR : On a demandé une écriture alors que pathname correspond à un répertoire (en fait, O_WRONLY ou O_RDWR ont été demandés).

ELOOP : pathname contient une référence circulaire (à travers un lien symbolique), ou l’attribut O_NOFOLLOW est indiqué et pathname est un lien symbolique.

EMFILE : Le processus a déjà ouvert le nombre maximal de fichiers.

ENAMETOOLONG : pathname est trop long.

ENFILE : La limite du nombre total de fichiers ouverts sur le système a été atteinte.

ENODEV : pathname correspond à un fichier spécial et il n’y a pas de périphérique correspondant. (Ceci est un bogue du noyau Linux ; dans cette situation, ENXIO devrait être renvoyé.)

ENOENT : O_CREAT est absent et le fichier n’existe pas. Ou un répertoire du chemin d’accès pathname n’existe pas, ou est un lien symbolique pointant nulle part.

ENOMEM : Pas assez de mémoire pour le noyau.

ENOSPC : pathname devrait être créé mais le périphérique concerné n’a plus assez de place pour un nouveau fichier.

ENOTDIR: Un élément du chemin d’accès pathname n’est pas un répertoire, ou l’attribut O_DIRECTORY est utilisé et pathname n’est pas un répertoire.

ENXIO : O_NONBLOCK | O_WRONLY est indiqué, le fichier est une FIFO et le processus n’a pas de fichier ouvert en lecture. Ou le fichier est un noeud spécial et il n’y a pas de périphérique

correspondant.

EOVERFLOW : pathname fait référence à un fichier régulier, trop grand pour pouvoir être ouvert — voir

O_LARGEFILE plus haut.

EPERM : L’attribut O_NOATIME est indiqué, mais l’UID effectif de l’appelant n’est pas le

propriétaire du fichier, et l’appelant n’est pas privilégié (CAP_FOWNER).

EROFS : Un accès en écriture est demandé alors que pathname réside sur un système de fichiers en lecture

seule.

ETXTBSY : On a demandé une écriture alors que pathname correspond à un fichier exécutable actuellement utilisé.

EWOULDBLOCK : L’attribut O_NONBLOCK est indiqué, et un bail incompatible est détenu sur le fichier (voir fcntl(2)).

RESTRICTIONS

Plusieurs problèmes se posent avec le protocole NFS, concernant entre autres O_SYNC, et O_NDELAY.

POSIX fournit trois variantes différentes des entrées- sorties synchronisées correspondant aux attributs O_SYNC, O_DSYNC et O_RSYNC. Actuellement (2.1.130) elles sont toutes équivalentes sous Linux.

>>

La lecture, l’écriture, et la fermeture se font avec les même fonction que celles utilisées pour les tubes anonymes (et les fichiers), c’est à dire avec read(), write(), et close().