/* * sem-producer-consumer.c - demonstrates a basic producer-consumer * implementation. */ #include /* standard I/O routines. */ #include /* rand() and srand() functions */ #include /* fork(), etc. */ #include /* nanosleep(), etc. */ #include /* various type definitions. */ #include /* general SysV IPC structures */ #include /* semaphore functions and structs. */ #define NUM_LOOPS 20 /* number of loops to perform. */ #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) /* union semun is defined by including */ #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 main(int argc, char* argv[]) { int sem_set_id; /* ID of the semaphore set. */ union semun sem_val; /* semaphore value, for semctl(). */ int child_pid; /* PID of our child process. */ int i; /* counter for loop operation. */ struct sembuf sem_op; /* structure for semaphore ops. */ int rc; /* return value of system calls. */ struct timespec delay; /* used for wasting time. */ /* create a private semaphore set with one semaphore in it, */ /* with access only to the owner. */ sem_set_id = semget(IPC_PRIVATE, 1, 0600); if (sem_set_id == -1) { perror("main: semget"); exit(1); } printf("semaphore set created, semaphore set id '%d'.\n", sem_set_id); /* intialize the first (and single) semaphore in our set to '0'. */ sem_val.val = 0; rc = semctl(sem_set_id, 0, SETVAL, sem_val); /* fork-off a child process, and start a producer/consumer job. */ child_pid = fork(); switch (child_pid) { case -1: /* fork() failed */ perror("fork"); exit(1); case 0: /* child process here */ for (i=0; i 3*(RAND_MAX/4)) { delay.tv_sec = 0; delay.tv_nsec = 10; nanosleep(&delay, NULL); } } break; } return 0; }