| C: System V Semaphore Example |
| Monday, 24 November 2008 17:33 |
|
Here is a simple example of a System V semaphore. The code is very basic and does not do to much error checking. If you decide to play with this example I recommend you check out the man pages for 'ipcs' and 'ipcrm' (Respectively they list and remove semaphores). Anyways ... as usual enjoy: main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semTake(int semid);
int semGive(int semid);
int semDestroy(int semid);
void printErrno(int myerrno);
int main(void) {
key_t semkey;
int semid;
pid_t pid;
FILE * fp;
const char * keyfilename = ".";
printf("Start\n");
semkey = ftok(keyfilename, 'z');
if (semkey == -1) {
printf("ERROR:could get key\n");
return EXIT_FAILURE;
}
semid = semget(semkey, 1, (IPC_CREAT| IPC_EXCL | 0666));
if (semid == -1) {
printf("ERROR:could not create semaphore\n");
printErrno(errno);
return EXIT_FAILURE;
}
if ((pid = fork()) == 0) {
int i = 0;
int sleeptime = 1;
for (i = 0; i < 10; i += 1) {
if (semTake(semid) == EXIT_FAILURE) {
printf("ERROR: semTake failed\n");
if (semDestroy(semid) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
return EXIT_FAILURE;
}
printf("\tCHILD OWNS MUTEX FOR %d SLEEP(S) ... %d\n", sleeptime, i);
sleep(1);
if (semGive(semid) == EXIT_FAILURE) {
printf("ERROR: semTake failed\n");
if (semDestroy(semid) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
} else if (pid > 0) {
int i = 0;
int status;
int sleeptime = 1;
for (i = 0; i < 10; i += 1) {
if (semGive(semid) == EXIT_FAILURE) {
printf("ERROR: semTake failed\n");
if (semDestroy(semid) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
return EXIT_FAILURE;
}
if (semTake(semid) == EXIT_FAILURE) {
printf("ERROR: semTake failed\n");
if (semDestroy(semid) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
return EXIT_FAILURE;
}
printf("\tPARENT OWNS MUTEX FOR %d SLEEP(S) ... %d\n", sleeptime, i);
sleep(2);
}
/*Do one last give to prevent below wait from hanging. */
/*Without this the child will wait forever*/
if (semGive(semid) == EXIT_FAILURE) {
printf("ERROR: semTake failed\n");
if (semDestroy(semid) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
return EXIT_FAILURE;
}
if (pid != waitpid(pid, &status, 0)) {
printf("ERROR: could not join with child process\n");
if (semDestroy(semid) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
return EXIT_FAILURE;
}
if (semDestroy(semid) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
} else {
printf("ERROR:could not fork process (pid=%d)\n", pid);
return EXIT_FAILURE;
}
printf("Done\n");
fflush(stdout);
return EXIT_SUCCESS;
}
int semTake(int semid) {
struct sembuf sops;
sops.sem_num = 0;
sops.sem_op = -1; /* semaphore operation */
sops.sem_flg = SEM_UNDO;
if (semop(semid, &sops, 1) == -1) {
printErrno(errno);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int semGive(int semid) {
struct sembuf sops;
sops.sem_num = 0;
sops.sem_op = 1; /* semaphore operation */
sops.sem_flg = SEM_UNDO;
if (semop(semid, &sops, 1) == -1) {
printErrno(errno);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int semDestroy(int semid) {
if (semctl(semid, 0, IPC_RMID) == -1) {
printf("ERROR: could not clean up semaphore\n");
printErrno(errno);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void printErrno(int myerrno) {
switch (myerrno) {
case EACCES:
printf("EACCES\n");
break;
case EEXIST:
printf("EEXIST\n");
break;
case EINVAL:
printf("EINVAL\n");
break;
case ENOENT:
printf("ENOENT\n");
break;
case ENOMEM:
printf("ENOMEM\n");
break;
case ENOSPC:
printf("ENOSPC\n");
break;
case E2BIG:
printf("E2BIG\n");
break;
case EAGAIN:
printf("EAGAIN\n");
break;
case EFAULT:
printf("EFAULT\n");
break;
case EFBIG:
printf("EFBIG\n");
break;
case EIDRM:
printf("EIDRM\n");
break;
case EINTR:
printf("EINTR\n");
break;
case ERANGE:
printf("ERANGE\n");
break;
default:
printf("default\n");
break;
}
fflush(stdout);
}
|