sem_wait(3)

NUME
sem_wait, sem_timedwait, sem_trywait - blochează un semafor

BIBLIOTECA
Biblioteca de fire de execuție POSIX (libpthread, -lpthread)

SINOPSIS
#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);

    Cerințe pentru macrocomenzi de testare a caracteristicilor pentru glibc (consultați feature_test_macros(7)):

sem_timedwait():
    _POSIX_C_SOURCE >= 200112L

DESCRIERE
sem_wait() decrementează (blochează) semaforul indicat de sem. În cazul în care valoarea semaforului este mai mare decât zero, atunci decrementarea are loc, iar funcția returnează, imediat. În cazul în care semaforul are în prezent valoarea zero, apelul se blochează până când fie devine posibilă efectuarea decrementării (de exemplu, valoarea semaforului crește peste zero), fie un gestionar de semnal întrerupe apelul.

sem_trywait() este la fel ca sem_wait(), cu excepția faptului că, dacă decrementarea nu poate fi efectuată imediat, apelul returnează o eroare (errno este configurată la EAGAIN) în loc să blocheze.

sem_timedwait() este la fel ca sem_wait(), cu excepția faptului că abs_timeout specifică o limită de timp în care apelul trebuie blocat dacă decrementarea nu poate fi efectuată imediat. Argumentul abs_timeout indică o structură timespec(3) care specifică un timp de așteptare absolut în secunde și nanosecunde de la Epoch, 1970-01-01 00:00:00 +0000 (UTC).

Dacă timpul de așteptare a expirat deja în momentul apelului, iar semaforul nu a putut fi blocat imediat, atunci sem_timedwait() eșuează cu o eroare de timp (errno este configurată la ETIMEDOUT).

Dacă operația poate fi efectuată imediat, atunci sem_timedwait() nu eșuează niciodată cu o eroare de timp de așteptare, indiferent de valoarea lui abs_timeout. În plus, validitatea lui abs_timeout nu este verificată în acest caz.

VALOAREA RETURNATĂ
Toate aceste funcții returnează 0 în caz de succes; în caz de eroare, valoarea semaforului rămâne neschimbată, se returnează -1, iar errno este configurată pentru a indica eroarea.

ERORI-IEȘIRE

EAGAIN
    (sem_trywait()) Operația nu a putut fi efectuată fără blocare (de exemplu, semaforul are în prezent valoarea zero).

EINTR
    Apelul a fost întrerupt de un gestionar de semnal; a se vedea signal(7).

EINVAL
    semafor nu este un semafor valid.

EINVAL
    (sem_timedwait()) Valoarea abs_timeout.tv_nsecs este mai mică decât 0 sau mai mare sau egală cu 1000 de milioane.

ETIMEDOUT
    (sem_timedwait()) Apelul a expirat înainte ca semaforul să poată fi blocat.

ATRIBUTE
Pentru o explicație a termenilor folosiți în această secțiune, a se vedea attributes(7).
Interfață | Atribut | Valoare
sem_wait(), sem_trywait(), sem_timedwait() | Siguranța firelor | MT-Safe

STANDARDE
POSIX.1-2008.

ISTORIC
POSIX.1-2001.

EXEMPLE
Programul (oarecum trivial) prezentat mai jos operează pe un semafor fără nume. Programul așteaptă două argumente în linia de comandă. Primul argument specifică o valoare în secunde care este utilizată pentru a configura un temporizator de alarmă pentru a genera un semnal SIGALRM. Acest gestionar efectuează un sem_post(3) pentru a incrementa semaforul care este așteptat în main() utilizând sem_timedwait(). Al doilea argument din linia de comandă specifică lungimea timpului de așteptare, în secunde, pentru sem_timedwait(). Ceea ce urmează arată ce se întâmplă la două execuții diferite ale programului:

    $ ./a.out 2 3
    În curs de apelare a sem_timedwait()
    sem_post() de la gestionar
    sem_timedwait() a reușit
    $ ./a.out 2 1
    În curs de apelare a sem_timedwait()
    ssem_timedwait() a expirat

  Sursa programului
    #include <err.h>
    #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;

    static void
    handler(int sig)
    {
        write(STDOUT_FILENO, "sem_post() de la gestionar\n", 24);
        if (sem_post(&sem) == -1) {
            write(STDERR_FILENO, "sem_post() a eșuat\n", 18);
            _exit(EXIT_FAILURE);
        }
    }

    int
    main(int argc, char *argv[])
    {
        struct sigaction sa;
        struct timespec ts;
        int s;

        if (argc != 3) {
            fprintf(stderr, "Utilizare: %s <secunde-alarmă> <secunde-așteptare>\n",
                    argv[0]);
            exit(EXIT_FAILURE);
        }

        if (sem_init(&sem, 0, 0) == -1)
            err(EXIT_FAILURE, "sem_init");

        /* Stabilește gestionarul SIGALRM; fixează temporizatorul de alarmă utilizând argv[1]. */

        sa.sa_handler = handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        if (sigaction(SIGALRM, &sa, NULL) == -1)
            err(EXIT_FAILURE, "sigaction");

        alarm(atoi(argv[1]));

        /* Calculează intervalul relativ ca timp curent plus
           numărul de secunde dat de argv[2]. */

        if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
            herr(EXIT_FAILURE, "clock_gettime");

        ts.tv_sec += atoi(argv[2]);

        printf("%s() pe cale să apeleze sem_timedwait()\n", __func__);
        while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
            continue;       /* Repornește dacă este întrerupt de gestionar. */

        /* Verifică ce s-a întâmplat. */

        if (s == -1) {
            if (errno == ETIMEDOUT)
                printf("sem_timedwait() timed out\n");
            else
                perror("sem_timedwait");
        } else
            printf("sem_timedwait() a reușit\n");

        exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
    }

CONSULTAȚI ȘI
clock_gettime(2), sem_getvalue(3), sem_post(3), timespec(3), sem_overview(7), time(7)

TRADUCERE
Traducerea în limba română a acestui manual a fost făcută de Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>

Această traducere este documentație gratuită; citiți Licența publică generală GNU Versiunea 3 (https://www.gnu.org/licenses/gpl-3.0.html) sau o versiune ulterioară cu privire la condiții privind drepturile de autor. NU se asumă NICIO RESPONSABILITATE.

Dacă găsiți erori în traducerea acestui manual, vă rugăm să trimiteți un e-mail la translation-team-ro@lists.sourceforge.net.