next up previous
Next: About this document ... Up: Semafoare Previous: semctl

Exemplu de utilizare

Urmatorul program invoca functiile specifice unui semafor de mai multe ori. Un parametru optional specifica daca se doreste crearea sau distrugerea semaforului. Vom folosi doua caractere diferite pentru a indica intrarea respectiv iesirea dintr-o regiune critica. Programul, invocat cu un parametru afiseaza caracterul X, iar cel fara parametru afiseaza caracterul 0. Deoarece un singur proces poate intra intr-o regiune critica la un anumit moment de timp, toate caracterele X si 0 vor aparea in pereche.

/*
 * semun.h - definitie pentru union semun 
 */

#ifndef _SEMUN_H
#define _SEMUN_H      1

union semun {
        int val;                /* Value for SETVAL */
        struct semid_ds *buf;   /* Buffer for IPC_STAT, IPC_SET */
        unsigned short *array;  /* Array for GETALL, SETALL */
        struct seminfo *__buf;  /* buffer pentru IPC_INFO
                                   (Linux specific) */
};

#endif


/*
 * fisier de test pentru lucrul cu semafoare
 */

#define _POSIX_SOURCE     1
#define _SVID_SOURCE      1
#define _XOPEN_SOURCE     1

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#include "semun.h"

static int set_semvalue (void);
static void del_semvalue (void);
static int semaphore_p (void);
static int semaphore_v (void);

static int sem_id;

int main(int argc, char *argv[])
{
        int i;
        int pause_time;
        char op_char = 'O';

        srand ((unsigned int) getpid ());
    
        sem_id = semget ((key_t) 1234, 1, 0666 | IPC_CREAT);

        if (argc > 1) {
                if (!set_semvalue ()) {
                        fprintf (stderr, "Failed to initialize semaphore\n");
                        exit (EXIT_FAILURE);
                }
                op_char = 'X';

                sleep (2);
        }

        /*
         * bucla infinita in care intram si parasim regiunea critica de 10 ori;
         * in prima faza vom pune procesul sa astepte, folosind operatia P
         * asupra semaforului
         */

        for(i = 0; i < 10; i++) {        

                if (!semaphore_p ()) exit (EXIT_FAILURE);
                printf ("%c", op_char); fflush (stdout);
                pause_time = rand () % 3;
                
                sleep (pause_time);
                
                printf ("%c", op_char); fflush (stdout);
        
                /*
                 * la iesirea din regiunea critica apelam semaphore_v
                 */

                if (!semaphore_v ()) exit (EXIT_FAILURE);
        
                pause_time = rand () % 2;
                sleep (pause_time);
        }

        printf("\n%d - finished\n", getpid ());

        if (argc > 1) {    
                sleep (10);
                del_semvalue ();
        }
        
        return 0;
}

/*
 * apelul set_semvalue initializeaza un semafor folosind comanda SETVAL
 * in cadrul unui apel SEMCTL
 */

static int set_semvalue(void)
{
        union semun sem_union;

        sem_union.val = 1;
        if (semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);
        return(1);
}

/*
 * functia del_semvalue are o forma asemanatoare cu cea de mai sus,
 * mai putin faptul ca apelul semctl utilizeaza comanda IPC_RMID pentru
 * a elimina id-ul semaforului
 */

static void del_semvalue(void)
{
        union semun sem_union;
    
        if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
                fprintf(stderr, "Failed to delete semaphore\n");
}

/*
 * semphore_p schimba valoarea semaforului cu -1 (eventual asteapta)
 */

static int semaphore_p(void)
{
        struct sembuf sem_b;
    
        sem_b.sem_num = 0;
        sem_b.sem_op = -1; /* P() */
        sem_b.sem_flg = SEM_UNDO;
        if (semop(sem_id, &sem_b, 1) == -1) {
                fprintf(stderr, "semaphore_p failed\n");
                return(0);
        }
        return(1);
}

/*
 * semaphore_v incrementeaza valoarea semaforului cu 1, astfel ca
 * semaforul devine disponibil
 */

static int semaphore_v(void)
{
        struct sembuf sem_b;
    
        sem_b.sem_num = 0;
        sem_b.sem_op = 1; /* V() */
        sem_b.sem_flg = SEM_UNDO;
        if (semop(sem_id, &sem_b, 1) == -1) {
                fprintf(stderr, "semaphore_v failed\n");
                return(0);
        }
        return(1);
}

Rularea executabilului generat de fisierul de mai sus rezulta in urmatorul output:

razvan@ragnarok:~/cfiles/solab/labs/lab5$ gcc -Wall -pedantic -ansi -o sem semaphore.c
razvan@ragnarok:~/cfiles/solab/labs/lab5$ ./sem 1 &
[3] 4247
razvan@ragnarok:~/cfiles/solab/labs/lab5$ XXXXXXX./sem
XOOOOXXXXOOXXOOXXOOXXOOXX
4247 - finished
OOOOOOOO
4258 - finished
razvan@ragnarok:~/cfiles/solab/labs/lab5$



Razvan Adrian Deaconescu 2005-11-02