SEMOP(2)

NOM
semop, semtimedop - Opérations sur les sémaphores System V

SYNOPSIS
#include <sys/sem.h>

int semop(int semid, struct sembuf *sops, size_t nsops);
int semtimedop(int semid, struct sembuf *sops, size_t nsops,
               const struct timespec *timeout);

    Exigences de macros de test de fonctionnalités pour la glibc (consulter feature_test_macros(7)) :

semtimedop():
    _GNU_SOURCE

DESCRIPTION
Chaque sémaphore dans un ensemble de sémaphores System V se voit associer les valeurs suivantes :

    unsigned short  semval;   /* Valeur du sémaphore   */
    unsigned short  semzcnt;  /* # Attente pour zéro   */
    unsigned short  semncnt;  /* # Attente d'incrément */
    pid_t           sempid;   /* PID du dernier processus agissant */

La fonction semop() effectue des opérations sur les membres de l'ensemble de sémaphores identifié par semid. Chacun des nsops éléments dans le tableau pointé par sops indique une opération à effectuer sur un sémaphore en utilisant une structure struct sembuf contenant les membres suivants :

    unsigned short sem_num;  /* Numéro du sémaphore        */
    short          sem_op;   /* Opération sur le sémaphore */
    short          sem_flg;  /* Options pour l'opération   */

Les options possibles pour sem_flg sont IPC_NOWAIT et SEM_UNDO. Si une opération indique l'option SEM_UNDO, elle sera annulée lorsque le processus se terminera.

L'ensemble des opérations contenues dans sops est effectué dans l'ordre et atomiquement. Les opérations sont toutes réalisées en même temps, et seulement si elles peuvent toutes être effectuées. Le comportement de l'appel système, si toutes les opérations ne sont pas réalisables, dépend de la présence de l'attribut IPC_NOWAIT dans les champs sem_flg décrits plus bas.

Chaque opération est effectuée sur le sem_num-ième sémaphore de l'ensemble. Le premier sémaphore est le numéro 0. Pour chaque sémaphore, l'opération est l'une des trois décrites ci-dessous.

Si l'argument sem_op est un entier positif, la fonction ajoute cette valeur à semval. De plus si SEM_UNDO est demandé, le système soustrait la valeur sem_op à la valeur de mise à jour du sémaphore (semadj). Cette opération n'est jamais bloquante. Le processus appelant doit avoir l'autorisation de modification sur le jeu de sémaphores.

Si sem_op vaut zéro le processus doit avoir l'autorisation de lecture sur l'ensemble de sémaphores. Le processus attend que semval soit nul : si semval vaut zéro, l'appel système continue immédiatement. Sinon, si l'on a réclamé IPC_NOWAIT dans sem_flg, l'appel système semop() échoue et errno contient le code d'erreur EAGAIN (et aucune des opérations de sops n'est réalisée). Sinon, semzcnt (le décompte de threads en attente jusqu'à ce que cette valeur de sémaphore devienne zéro) est incrémenté d'un et le thread s'endort jusqu'à ce que l'un des événements suivants se produise :

•   semval devient égal à 0, alors semzcnt est décrémenté.

•   Le jeu de sémaphores est supprimé. L'appel système échoue et errno contient le code d'erreur EIDRM.

•   Le thread reçoit un signal à intercepter, la valeur de semzcnt est décrémentée et l'appel système échoue avec errno contenant le code d'erreur EINTR.

Si sem_op est inférieur à zéro, le processus appelant doit avoir l'autorisation de modification sur le jeu de sémaphores. Si semval est supérieur ou égal à la valeur absolue de sem_op, la valeur absolue de sem_op est soustraite de semval, et si SEM_UNDO est indiqué, le système ajoute la valeur absolue de sem_op à la valeur de mise à jour de sémaphore (semadj) pour ce sémaphore. Si la valeur absolue de sem_op est plus grande que semval et si l'on a réclamé IPC_NOWAIT dans sem_flg, l'appel système échoue et errno contient le code d'erreur EAGAIN (et aucune des opérations de sops n'est réalisée). Sinon, semncnt (le décompte de threads en attente jusqu'à ce que cette valeur de sémaphore soit incrémenté) est incrémenté de un et le thread s'endort jusqu'à ce que l'un des événements suivants se produise :

•   semval devient supérieur ou égal à la valeur absolue de sem_op : l'opération est effectuée comme décrit ci-dessus.

•   Le jeu de sémaphores est supprimé. L'appel système échoue et errno contient le code d'erreur EIDRM.

•   Le thread reçoit un signal à intercepter, la valeur de semncnt est décrémentée et l'appel système échoue avec errno contenant le code d'erreur EINTR.

En cas de succès, le membre sempid de chacun des sémaphores indiqués dans le tableau pointé par sops est rempli avec le PID de l'appelant. Enfin sem_otime est défini à l'heure actuelle.

  semtimedop()
La fonction semtimedop() se comporte comme semop() sauf que dans le cas où le thread doit dormir, la durée maximale du sommeil est limitée par la valeur spécifiée dans la structure timespec dont l'adresse est transmise dans le paramètre timeout (cet intervalle de sommeil sera arrondi à la granularité de l'horloge système, et les délais d'ordonnancement du noyau font que cette valeur peut être légèrement dépassée). Si la limite indiquée a été atteinte, l'appel système échoue avec errno contenant EAGAIN (et aucune opération de sops n'est réalisée). Si le paramètre timeout est NULL, alors semtimedop() se comporte exactement comme semop().

Si semtimedop() est interrompu par un signal, causant l'échec de l'appel avec l'erreur EINTR, les valeurs contenues dans timeout restent inchangées.

VALEUR RENVOYÉE
En cas de réussite, semop() et semtimedop() renvoient 0. En cas d'échec, ils renvoient -1 et errno contient le code d'erreur.

ERREURS

E2BIG
    l'argument nsops est supérieur à SEMOPM, le nombre maximal d'opérations autorisées par appel système.

EACCES
    Le processus appelant n'a pas les permissions nécessaires pour effectuer les opérations sur les sémaphores spécifiés et n'a pas la capacité CAP_IPC_OWNER dans l'espace de noms utilisateur qui régit son espace de noms IPC.

EAGAIN
    Une opération ne pouvait pas être effectuée immédiatement et IPC_NOWAIT a été indiqué dans l'argument sem_flg, ou la durée limite indiquée dans timeout a expiré.

EFAULT
    sops ou timeout pointent en dehors de l'espace d'adressage accessible.

EFBIG
    La valeur de sem_num est inférieure à 0 ou supérieure ou égale au nombre de sémaphores dans l'ensemble.

EIDRM
    Le jeu de sémaphores a été supprimé.

EINTR
    Un signal a été reçu pendant l'attente ; consultez signal(7).

EINVAL
    L'ensemble de sémaphores n'existe pas ou semid est inférieur à zéro, ou nsops n'est pas strictement positive.

ENOMEM
    L'argument sem_flg de certaines opérations demande SEM_UNDO et le système n'a pas assez de mémoire pour allouer les structures nécessaires.

ERANGE
    sem_op+semval est supérieur à SEMVMX (la valeur maximale de semval autorisée par l'implémentation) pour l'une des opérations.

VERSIONS
semtimedop() est apparu pour la première fois dans Linux 2.5.52, puis a été rétroporté au noyau 2.4.22. La gestion de semtimedop() dans la glibc date de la version 2.3.3.

CONFORMITÉ
POSIX.1-2001, POSIX.1-2008, SVr4.

NOTES
Les structures sem_undo d'un processus ne sont pas héritées par ses enfants lors d'un fork(2), mais elles le sont lors d'un appel système execve(2).

semop() n'est jamais relancé automatiquement après avoir été interrompu par un gestionnaire de signal quelque soit l'attribut SA_RESTART durant l'installation du gestionnaire.

Une valeur de mise à jour de sémaphore (semadj) est un entier propre à un processus et sémaphore, qui représente le compte négatif des opérations utilisant l'attribut SEM_UNDO. Chaque processus dispose d'une liste de valeurs semadj — une valeur pour chaque sémaphore où SEM_UNDO a été utilisé. Quand un processus se termine, chacune des valeurs semadj de ses sémaphores est ajoutée au sémaphore correspondant, annulant ainsi l'effet des opérations du processus sur le sémaphore (voir la section BOGUES ci-dessous). Quand la valeur d'un sémaphore est définie directement par une requête SETVAL ou SETALL de semctl(2), la valeur semadj correspondante est effacée dans tous les processus. L'option CLONE_SYSVSEM de clone(2) permet à plusieurs processus de partager une liste de semadj. Consultez clone(2) pour plus d'informations.

Les valeurs semval, sempid, semzcnt et semnct pour un sémaphore peuvent être retrouvées avec des appels semctl(2) spécifiques.

  Limites des sémaphores
Les limites suivantes de ressources concernent l'appel système semop() :

SEMOPM
    Nombre maximal d'opérations pour un appel à semop. Avant Linux 3.19, la valeur par défaut pour cette limite était de 32. Depuis Linux 3.19, cette valeur est de 500. Sous Linux, cette limite peut être lue et modifiée via le troisième champ du fichier /proc/sys/kernel/sem. Note : cette limite ne devrait pas être augmentée au-delà de 1000 à cause du risque que semop() échoue en raison de la fragmentation de la mémoire du noyau pendant l'allocation de mémoire pour copier le tableau sops.

SEMVMX
    Valeur maximale pour semval : dépendante de l'implémentation (32767).

L'implémentation n'a pas de limites intrinsèques pour la valeur maximale d'effacement en sortie (SEMAEM), le nombre de structures d'annulation sur le système (SEMMNU) et le nombre maximal de structures d'annulation pour un processus.

BOGUES
Quand un processus se termine, l'ensemble des structures semadj qui lui sont associées servent à annuler les effets de toutes les opérations sur les sémaphores réalisées avec l'attribut SEM_UNDO. Cela pose un problème : si l'une (ou plusieurs) des modifications sur les sémaphores demande une descente du compteur d'un sémaphore au-dessous de zéro, que doit faire l'implémentation ? Une approche possible consiste à bloquer jusqu'à ce que la modification du sémaphore soit possible. C'est néanmoins peu désirable, car la terminaison du processus peut alors bloquer pendant une période arbitrairement longue. Une autre possibilité est d'ignorer la modification du sémaphore (comme un échec lorsque IPC_NOWAIT est spécifié durant une opération). Linux adopte une troisième approche : décroître la valeur du sémaphore autant que possible (jusqu'à zéro) et permettre au processus de se terminer immédiatement.

Dans les noyaux 2.6.x (x <= 10) un bogue peut, dans certaines circonstances, empêcher un thread, attendant que la valeur d'un sémaphore s'annule, d'être réveillé quand cette valeur atteint 0. Ce bogue est corrigé dans le noyau 2.6.11.

EXEMPLES
Le bout de code suivant utilise semop() pour attendre de façon atomique que la valeur du sémaphore 0 vaille zéro, puis incrémente la valeur du sémaphore de un.

    struct sembuf sops[2];
    int semid;
    /* Le code pour configurer semid est omis */
    sops[0].sem_num = 0;        /* Agir sur le sémaphore 0 */
    sops[0].sem_op = 0;         /* Attendre que la valeur soit égale à 0 */
    sops[0].sem_flg = 0;
    sops[1].sem_num = 0;        /* Agir sur le sémaphore 0 */
    sops[1].sem_op = 1;         /* Incrémenter la valeur de un */
    sops[1].sem_flg = 0;
    if (semop(semid, sops, 2) == -1) {
        perror("semop");
        exit(EXIT_FAILURE);
    }

Un autre exemple de l'usage de semop() peut être trouvé dans shmop(2).

VOIR AUSSI
clone(2), semctl(2), semget(2), sigaction(2), capabilities(7), sem_overview(7), sysvipc(7), time(7)

COLOPHON
Cette page fait partie de la publication 5.13 du projet man-pages Linux. Une description du projet et des instructions pour signaler des anomalies et la dernière version de cette page peuvent être trouvées à l'adresse https://www.kernel.org/doc/man-pages/.

TRADUCTION
La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org>, Thomas Vincent <tvincent@debian.org> et Jean-Pierre Giraud <jean-pierregiraud@neuf.fr> Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 (https://www.gnu.org/licenses/gpl-3.0.html) concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE. Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.