NOM¶
semop, semtimedop - Opérations sur les sémaphores
SYNOPSIS¶
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
struct timespec *timeout);
Exigences de macros de test de fonctionnalités pour la glibc (consultez
feature_test_macros(7)) :
semtimedop() : _GNU_SOURCE
DESCRIPTION¶
Chaque sémaphore dans un ensemble de sémaphores 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 elle 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 met à jour le compteur « undo » 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.
- •
- La limite temporelle indiqué par timeout dans
un semtimedop() a expiré : l'appel système
échoue avec errno contenant EAGAIN.
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 met
à jour le compteur « undo » du sémaphore (
semadj). Puis l'appel système continue. 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 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 supérieur ou égal à la
valeur absolue de sem_op, alors la valeur semncnt est
décrémentée, la valeur absolue de sem_op est
soustraite de semval et si SEM_UNDO est demandé le
système met à jour le compteur « undo » (
semadj) du sémaphore.
- •
- 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.
- •
- La limite temporelle indiqué par timeout dans
un semtimedop() a expiré : l'appel système
échoue avec errno contenant EAGAIN.
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.
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().
VALEUR RENVOYÉE¶
En cas de réussite,
semop() et
semtimedop() renvoient 0.
Sinon ils renvoient -1 et
errno contient le code d'erreur.
ERREURS¶
En cas d'erreur,
errno prend l'une des valeurs suivantes :
- E2BIG
- l'argument nsops est supérieur à
SEMOPM, le nombre maximal d'opérations 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.
- 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.
SVr4, POSIX.1-2001.
NOTES¶
L'inclusion de
<sys/types.h> et
<sys/ipc.h> n'est pas
nécessaire sous Linux et n'est exigée par aucune version de POSIX.
Cependant, certaines implémentations anciennes nécessitent
l'inclusion de ces fichiers d'en-tête, et le SVID documente aussi leur
inclusion. Les applications ayant pour but d'être portables pourraient
inclure ces fichiers d'en-tête.
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.
semadj est un entier pour le processus qui représente simplement le
compte (négatif) des opérations sur le sémaphore
réalisées par l'attribut
SEM_UNDO. 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.
Les valeurs
semval,
sempid,
semzcnt, et
semnct pour
un sémaphore peuvent être retrouvées avec des appels
semctl(2) spécifiques.
Les limites système suivantes concernent
semop() :
- SEMOPM
- Nombre maximal d'opérations pour une appel à
semop() (32). Sous Linux, cette limite peut être lue et
modifiée via le troisième champ du fichier
/proc/sys/kernel/sem.
- 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. Ceci 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.
EXEMPLE¶
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 semaphore 0 */
sops[0].sem_op = 0; /* Attendre que la valeur soit égal à 0 */
sops[0].sem_flg = 0;
sops[1].sem_num = 0; /* Agir sur le semaphore 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);
}
VOIR AUSSI¶
clone(2),
semctl(2),
semget(2),
sigaction(2),
capabilities(7),
sem_overview(7),
svipc(7),
time(7)
COLOPHON¶
Cette page fait partie de la publication 3.44 du projet
man-pages Linux.
Une description du projet et des instructions pour signaler des anomalies
peuvent être trouvées à l'adresse
<
http://www.kernel.org/doc/man-pages/>.
TRADUCTION¶
Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a
<
http://po4a.alioth.debian.org/> par l'équipe de traduction
francophone au sein du projet perkamon
<
http://perkamon.alioth.debian.org/>.
Christophe Blaess <
http://www.blaess.fr/christophe/> (1996-2003), Alain
Portal <
http://manpagesfr.free.fr/> (2003-2006). Julien Cristau et
l'équipe francophone de traduction de Debian (2006-2009).
Veuillez signaler toute erreur de traduction en écrivant à
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet
manpages-fr.
Vous pouvez toujours avoir accès à la version anglaise de ce document
en utilisant la commande «
man -L C
<section> <page_de_man> ».