#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