Semaphores are used to synchronize operations between two or more processes. POSIX defines two different sets of semaphore functions:
This section describes the System V IPC semaphores, so called because they originated with Unix System V.
First, you'll need to include the required headers. Old versions of POSIX required #include ; modern POSIX and most systems do not require it.
#include
Then, you'll need to define a key in both the parent as well as the child.
#define KEY 0x1111
This key needs to be the same in both programs or they will not refer to the same IPC structure. There are ways to generate an agreed key without hard-coding its value.
Next, depending on your compiler, you may or may not need to do this step: declare a union for the purpose of semaphore operations.
union semun < int val; struct semid_ds *buf; unsigned short *array; >;
Next, define your try ( semwait ) and raise ( semsignal ) structures. The names P and V originate from Dutch
struct sembuf p = < 0, -1, SEM_UNDO>; # semwait struct sembuf v = < 0, +1, SEM_UNDO>; # semsignal
Now, start by getting the id for your IPC semaphore.
int id; // 2nd argument is number of semaphores // 3rd argument is the mode (IPC_CREAT creates the semaphore set if needed) if ((id = semget(KEY, 1, 0666 | IPC_CREAT) < 0) < /* error handling code */ >
In the parent, initialise the semaphore to have a counter of 1.
union semun u; u.val = 1; if (semctl(id, 0, SETVAL, u) < 0) < // SETVAL is a macro to specify that you're setting the value of the semaphore to that specified by the union u /* error handling code */ >
Now, you can decrement or increment the semaphore as you need. At the start of your critical section, you decrement the counter using the semop() function:
if (semop(id, &p, 1) < 0) < /* error handling code */ >
To increment the semaphore, you use &v instead of &p :
if (semop(id, &v, 1) < 0) < /* error handling code */ >
Note that every function returns 0 on success and -1 on failure. Not checking these return statuses can cause devastating problems.
The below program will have a process fork a child and both parent and child attempt to print characters onto the terminal without any synchronization.
#include #include #include #include int main() < int pid; pid = fork(); srand(pid); if(pid < 0) < perror("fork"); exit(1); >else if(pid) < char *s = "abcdefgh"; int l = strlen(s); for(int i = 0; i < l; ++i) < putchar(s[i]); fflush(stdout); sleep(rand() % 2); putchar(s[i]); fflush(stdout); sleep(rand() % 2); >> else < char *s = "ABCDEFGH"; int l = strlen(s); for(int i = 0; i < l; ++i) < putchar(s[i]); fflush(stdout); sleep(rand() % 2); putchar(s[i]); fflush(stdout); sleep(rand() % 2); >> >
aAABaBCbCbDDcEEcddeFFGGHHeffgghh
aabbccAABddBCeeCffgDDghEEhFFGGHH
Compiling and running this program should give you a different output each time .
Modifying Example 1.1 to use semaphores, we have:
#include #include #include #include #include #include #include #define KEY 0x1111 union semun < int val; struct semid_ds *buf; unsigned short *array; >; struct sembuf p = < 0, -1, SEM_UNDO>; struct sembuf v = < 0, +1, SEM_UNDO>; int main() < int 1, 0666 | IPC_CREAT); if(id < 0) < perror("semget"); exit(11); >union semun u; u.val = 1; if(semctl(id, 0, SETVAL, u) < 0) < perror("semctl"); exit(12); >int pid; pid = fork(); srand(pid); if(pid < 0) < perror("fork"); exit(1); >else if(pid) < char *s = "abcdefgh"; int l = strlen(s); for(int i = 0; i < l; ++i) < if(semop(id, &p, 1) < 0) < perror("semop p"); exit(13); >putchar(s[i]); fflush(stdout); sleep(rand() % 2); putchar(s[i]); fflush(stdout); if(semop(id, &v, 1) < 0) < perror("semop p"); exit(14); >sleep(rand() % 2); > > else < char *s = "ABCDEFGH"; int l = strlen(s); for(int i = 0; i < l; ++i) < if(semop(id, &p, 1) < 0) < perror("semop p"); exit(15); >putchar(s[i]); fflush(stdout); sleep(rand() % 2); putchar(s[i]); fflush(stdout); if(semop(id, &v, 1) < 0) < perror("semop p"); exit(16); >sleep(rand() % 2); > > >
aabbAABBCCccddeeDDffEEFFGGHHgghh
Compiling and running this program will give you the same output each time.
PDF - Download C Language for free