next up previous
Next: A Função semop() Up: Os Semáforos Previous: Como criar um conjunto

A Função semctl()

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

   #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
   /* union semun is defined by including <sys/sem.h> */
   #else
   /* according to X/OPEN we have to define it ourselves */
   union semun {
         int val;                    /* value for SETVAL */
         struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
         unsigned short int *array;  /* array for GETALL, SETALL */
         struct seminfo *__buf;      /* buffer for IPC_INFO */
   };
   #endif

   int  semctl  (int  semid, int semnum, int cmd, union semun arg)

   /* Commands for `semctl'.  */
   #define GETPID               11              /* get sempid */
   #define GETVAL               12              /* get semval */
   #define GETALL               13              /* get all semval's */
   #define GETNCNT              14              /* get semncnt */
   #define GETZCNT              15              /* get semzcnt */
   #define SETVAL               16              /* set semval */
   #define SETALL               17              /* set all semval's */

Valor de retorno: Depende do valor do argumento cmd:

Para todos os outros valores de cmd, o valor de retorno é 0 em caso de sucesso, e -1 em caso de erro.

A função semctl é utilizada para examinar e mudar (controlar) os valores de cada um dos componentes de um conjunto de semáforos. Ela executa as ações de controle definidas em cmd no conjunto de semáforos (ou no semnun-ésimo semáforo do conjunto) identificado por semid. O primeiro semáforo do grupo é identificado pelo valor 0 e o último por semnum-1. O último argumento arg é uma variável do tipo union semun.

Observação: Em alguns casos o usuário deve definir a union dentro do seu arquivo fonte se este não for definido dentro de <sys/sem.h>). Pode se testar a macro _SEM_SEMUN_UNDEFINED para se verificar se a union está ou não definida.

Os possíveis comandos para um semáforo
Os diferentes comandos possíveis para semctl() podem ser encontrados fazendo-se o comando shell man semctl(). Neste caso, as seguintes informações são disponibilizadas:

Exemplo:

                 /* arquivo test_semctl.c */
/* exemplo de uso de semctl() */

#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>

#define KEY 123

union semun {
              int val ;
              struct semid_ds buf[2] ;
              unsigned short int array[4] ;
              struct seminfo *__buf; 
};

int main()
{
  struct sembuf sempar;
  int semid, semval , sempid;
  union semun arg;
  char *path = "nome_de_arquivo_existente" ;
    /*
     * recuperacao do identificador do
     * do conjunto de semaforos do projeto 123
     */
     if (( semid = semget(ftok(path,(key_t)KEY),0,0)) == -1 ) {
          perror ("Error semget()") ;
          exit(1) ;
      }
      printf("O conjunto de semaforos tem semid : %d\n",semid) ;
      printf("A chave de acesso unica e : %d\n",ftok(path,(key_t)KEY)) ;

    /*    
     * leitura do 3o. semaforo
     */
      if ( (semval = semctl(semid,2,GETVAL,arg)) == -1){
          perror("Error semctl() GETVAL") ;
          exit(1) ;
     }
     else {
       printf("O valor do terceiro semaforo e : %d\n",semval) ;
     }
    /*
     * atualizacao do 3o. semaforo
     */
     sempar.sem_num = 2 ;
     sempar.sem_op = 1 ;
     sempar.sem_flg = SEM_UNDO ;
     if (semop(semid, &sempar, 1) == -1) {
          perror("Error semop()") ;
          exit(-1);
     }
    /*    
     * leitura do 3o. semaforo
     */
      if ( (semval = semctl(semid,2,GETVAL,arg)) == -1){
          perror("Error semctl() GETVAL") ;
          exit(1) ;
     }
     else printf("O valor do terceiro semaforo e : %d\n",semval) ;

    /*
     * leitura do pid do processo que executou a ultima operacao 
     */
      if (( sempid = semctl(semid,2,GETPID,arg) )== -1){
          perror("Error semctl()") ;
          exit(1) ;
     }
     else 
       {
         printf("O valor do pid do processo que\n");
         printf("\t realizou o ultimo semop no semaforo e : %d\n",sempid);
         printf("\t Meu pid e : %d\n",getpid()) ;
       }

    /*
     * destruicao do semaforo
     */
     if (semctl(semid,0,IPC_RMID,0)==-1){
             perror("Impossivel de destruir o semaforo") ;
             exit(1) ;
     }
     else printf("O semaforo com semid %d foi destruido\n",semid) ;

     exit(0);
}

Resultado da execução:

Após o programa test_semget ser executado, uma chave com ID igual a 1024 foi criada no sistema. O programa test_semctl recupera essa chave dos semáforos e realiza uma operação sobre o terceiro semáforo.

euler:~/> test_semget
 O semid do conjunto do semaforo e : test_semget
 O semid do conjunto do semaforo e : 1024
 Este conjunto e identificado pela chave unica : 2063837372
euler:~/> ipcs -s

------ Semaphore Arrays --------
key       semid     owner     perms     nsems     status      
0x7b03a8bc 1024      saibel    600       4         

euler:~/> test_semctl
O conjunto de semaforos tem semid : 1024
A chave de acesso unica e : 2063837372
O valor do terceiro semaforo e : 0
O valor do terceiro semaforo e : 1
O valor do pid do processo que
         realizou a ultima operacao no semaforo e : 1067
         Meu pid e : 1067
O semaforo com semid 1024 foi destruido
euler:~/> ipcs -s

------ Semaphore Arrays --------
key       semid     owner     perms     nsems     status


next up previous
Next: A Função semop() Up: Os Semáforos Previous: Como criar um conjunto
Celso Alberto Saibel Santos 2000-11-14