sem_wait, sem_timedwait, sem_trywait - Verrouiller un sémaphore
Bibliothèque de threads POSIX (
libpthread,
-lpthread)
#include <semaphore.h>
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *restrict sem,
const struct timespec *restrict abs_timeout);
sem_timedwait() :
_POSIX_C_SOURCE >= 200112L
sem_wait() décrémente (verrouille) le sémaphore
pointé par
sem. Si la valeur du sémaphore est plus grande
que zéro, la décrémentation s'effectue et la fonction
renvoie immédiatement. Si le sémaphore vaut zéro, l'appel
bloquera jusqu'à ce qu’il devienne possible d'effectuer la
décrémentation (c'est-à-dire la valeur du
sémaphore devient positive) ou qu’un gestionnaire de signaux
interrompe l'appel.
sem_trywait() est pareil à
sem_wait(), excepté que
si la décrémentation ne peut pas être effectuée
immédiatement, l'appel renvoie une erreur (
errno vaut
EAGAIN) plutôt que de bloquer.
sem_timedwait() est pareil à
sem_wait() excepté que
abs_timeout spécifie une limite sur le temps pendant lequel
l'appel bloquera si la décrémentation ne peut pas être
effectuée immédiatement. L'argument
abs_timeout pointe
sur une structure
timespec(3) qui spécifie un temps absolu en
secondes et nanosecondes depuis l'époque, 1er janvier 1970
à 00:00:00 (UTC).
Si le délai est déjà expiré à l'heure de
l'appel et si le sémaphore ne peut pas être verrouillé
immédiatement,
sem_timedwait() échoue avec l'erreur
d'expiration de délai (
errno vaut
ETIMEDOUT).
Si l'opération peut être effectuée immédiatement,
sem_timedwait() n'échoue jamais avec une valeur d'expiration de
délai, quelque soit la valeur de
abs_timeout. De plus, la
validité de
abs_timeout n'est pas vérifiée dans ce
cas.
Toutes ces fonctions renvoient
0 si elles réussissent. Si elles
échouent, la valeur du sémaphore n'est pas modifiée,
elles renvoient
-1 et écrivent
errno en
conséquence.
- EAGAIN
- (sem_trywait()) L'opération ne peut pas
être effectuée sans bloquer (c'est-à-dire, le
sémaphore a une valeur nulle).
- EINTR
- L'appel a été interrompu par un gestionnaire
de signal ; consultez signal(7).
- EINVAL
-
sem n'est pas un sémaphore valable.
- EINVAL
- (sem_timedwait()) La valeur de
abs_timeout.tv_nsecs est plus petite que 0 ou
supérieure ou égale à 1 milliard.
- ETIMEDOUT
- (sem_timedwait()) Le délai a expiré
avant que le sémaphore ait pu être verrouillé.
Pour une explication des termes utilisés dans cette section, consulter
attributes(7).
Interface |
Attribut |
Valeur |
sem_wait(), sem_trywait(), sem_timedwait() |
Sécurité des threads |
MT-Safe |
POSIX.1-2001, POSIX.1-2008.
Le (quelque peu trivial) programme suivant opère sur un sémaphore
non nommé. Il attend deux arguments sur la ligne de commande. Le
premier argument spécifie une valeur en secondes qui est
utilisée pour configurer une alarme pour générer un
signal
SIGALRM. Ce gestionnaire effectue un
sem_post(3) pour
incrémenter le sémaphore qui est attendu dans le
main()
en utilisant
sem_timedwait(). Le second argument de la ligne de
commande spécifie la durée, en secondes, du délai
d'attente pour
sem_timedwait(). Ci-dessous, le résultat de deux
exécutions différentes du programme :
$ ./a.out 2 3
main() est sur le point d'appeler sem_timedwait()
sem_post() depuis le gestionnaire
sem_timedwait() a réussi
$ ./a.out 2 1
main() est sur le point d'appeler sem_timedwait()
sem_timedwait() a expiré
#include <errno.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
sem_t sem;
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static void
handler(int sig)
{
write(STDOUT_FILENO, "sem_post() depuis le gestionnaire\n", 24);
if (sem_post(&sem) == -1) {
write(STDERR_FILENO, "sem_post() a échoué\n", 18);
_exit(EXIT_FAILURE);
}
}
int
main(int argc, char *argv[])
{
struct sigaction sa;
struct timespec ts;
int s;
if (argc != 3) {
fprintf(stderr, "Usage : %s <alarme-secs> <attente-secs>\n",
argv[0]);
exit(EXIT_FAILURE);
}
if (sem_init(&sem, 0, 0) == -1)
handle_error("sem_init");
/* Établit le gestionnaire de signal pour SIGALARM ;
fixe le chronomètre de l'alarme selon argv[1]. */
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGALRM, &sa, NULL) == -1)
handle_error("sigaction");
alarm(atoi(argv[1]));
/* Calcule l'intervalle relatif comme l'heure actuelle plus
un certain nombre de secondes données dans argv[2]. */
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
handle_error("clock_gettime");
ts.tv_sec += atoi(argv[2]);
printf("%s() est sur le point d'appeler sem_timedwait()\n");
while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
continue; /* Redémarre si interrompu par le gestionnaire. */
/* Observe ce qui s'est passé. */
if (s == -1) {
if (errno == ETIMEDOUT)
printf("sem_timedwait() a expiré\n");
else
perror("sem_timedwait");
} else
printf("sem_timedwait() a réussi\n");
exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
}
clock_gettime(2),
sem_getvalue(3),
sem_post(3),
timespec(3),
sem_overview(7),
time(7)
La traduction française de cette page de manuel a été
créée par Christophe Blaess
<
https://www.blaess.fr/christophe/>, Stéphan Rafin
<
[email protected]>, Thierry Vignaud
<
[email protected]>, François Micaux, Alain Portal
<
[email protected]>, Jean-Philippe Guérard
<
[email protected]>, Jean-Luc Coulon (f5ibh)
<
[email protected]>, Julien Cristau
<
[email protected]>, Thomas Huriaux <
[email protected]>,
Nicolas François <
[email protected]>, Florentin
Duneau <
[email protected]>, Simon Paillard
<
[email protected]>, Denis Barbier
<
[email protected]>, David Prévot <
[email protected]>,
Thomas Vincent <
[email protected]> et Jean-Pierre Giraud
<
[email protected]>
Cette traduction est une documentation libre ; veuillez vous reporter
à la
GNU
General Public License version 3 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 à
[email protected]