I wrote an example program about UNIX semaphores, where a process and its child lock/unlock the same semaphore. I would appreciate your feedback about what I could improve in my C style. Generally I feel that the program flow is hard to read because of all those error checks, but I didn't find a better way to write it. It's also breaking the rule of "one vertical screen maximum per function" but I don't see a logical way to split it into functions.
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(void)
{
/* place semaphore in shared memory */
sem_t *sema = mmap(NULL, sizeof(sema),
PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if (!sema) {
perror("Out of memory");
exit(EXIT_FAILURE);
}
/* create, initialize semaphore */
if (sem_init(sema, 1, 0) < 0) {
perror("semaphore initilization");
exit(EXIT_FAILURE);
}
int i, nloop=10;
int ret = fork();
if (ret < 0) {
perror("fork failed");
exit(EXIT_FAILURE);
}
if (ret == 0) {
/* child process*/
for (i = 0; i < nloop; i++) {
printf("child unlocks semaphore: %d\n", i);
sem_post(sema);
sleep(1);
}
if (munmap(sema, sizeof(sema)) < 0) {
perror("munmap failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
if (ret > 0) {
/* back to parent process */
for (i = 0; i < nloop; i++) {
printf("parent starts waiting: %d\n", i);
sem_wait(sema);
printf("parent finished waiting: %d\n", i);
}
if (sem_destroy(sema) < 0) {
perror("sem_destroy failed");
exit(EXIT_FAILURE);
}
if (munmap(sema, sizeof(sema)) < 0) {
perror("munmap failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}