#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