Semaphore (セマフォ) のサンプル

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

#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

static int sem_id;

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);
}

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);
}

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);
}

int main(int args, char** argv){

	key_t key = ftok(argv[1], 1);
	sem_id = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL);
	if(-1 == sem_id){
		sem_id = semget(key, 1, 0666 | IPC_CREAT);
	}
	else {
		set_semvalue();
	}
	
	int retry=5;
	while(retry--){
		if( semaphore_p() ) break;
		printf("pid %d is waiting\n", getpid());
		fflush(stdout);
		sleep(1);
	}
	
	printf(">>pid %d is in critical section\n", getpid());
	fflush(stdout);
	sleep(10);
	printf("<<pid %d is in critical section\n", getpid());
	fflush(stdout);
	semaphore_v();

}
# ./semaphore /tmp/a.out &
# ./semaphore /tmp/a.out &
>>pid 14654 is in critical section
<<pid 14654 is in critical section
>>pid 14655 is in critical section
<<pid 14655 is in critical section

排他処理されているのが確認できる。