Below is a gist of what's wrong with System V Semaphore design.
Allocation and Deallocation Symmetry
semget() | Allocate a semaphore |
semctl() | Deallocate a semaphore |
Can you see the lack of symmetry? If
semget()
allocates a semaphore, shouldn't the deallocation function be called semremove()
or semunget()
? Please note that semremove()
and semunget()
are my suggestions---they don't exist!Undefined Union!
Adding fuel to the fire, here is a typical call tosemctl()
to remove a semaphore:semctl (semdid, 1, IPC_RMID, ignoredArgument);
Yes, you read it right:
ignoredArgument
. And what's its type? It's union semun ignoredArgument
. And in which header file is semun
is defined? Nowhere!One has to define this union himself!! That is, if you are going to use System V semaphores, somewhere in your code you must define this union:
union semun {
int val;
struct semid_ds *buff;
unsigned short int *array;
struct seminfo *_buff;
};
Why on earth this union definition is not included in the standard
sys/sem.h
is beyond me.What's the Use of an Un-initialized Semaphore
If you thinksemget()
gives you a ready to use semaphore, then you are mistaken. It only gives you an uninitialized one. You must invoke semctl()
on this semaphore to initialize it as follows:union semun argument;
unsigned short int values[1];
Values[0] = 1;
argument.array = values;
semctl (semid, 0, SETALL, argument);
Now you must have come to know where
semun
is used.Waiting and Posting on the Semaphore
Is it too much to ask to create separatesem_wait()
and sem_post()
methods? Please note that sem_wait()
and sem_post()
do exist in POSIX but not in System V. Someone designing the System V api thought that one can have a single function to do both, and the difference can be indicated with the help of a passed argument. Hence came the semop()
function. Below is how to wait on an initialized semaphore:struct sembuf operations[1];
operations[0].sem_num = 0;
operations[0].sem_op = -1;
operations[0].sem_flg = SEM_UNDO;
semop (semid, operations, 1);
Why
sem_flg
and not sem_flag
is also beyond me! How much space is saved by declaring the flag member variable as sem_flg
instead of sem_flag
? Below is how to post on a semaphore:
struct sembuf operations[1];
operations[0].sem_num = 0;
operations[0].sem_op = 1;
operations[0].sem_flg = SEM_UNDO;
semop (semid, operations, 1);
I wonder why the ALP book chose to teach System V semaphores in chapter 5 when it had already introduced POSIX semaphores as part of chapter 4 on Threads. Someone learning from the book can wrongly deduce that POSIX semaphores are for inter-thread communication while System V semaphores are for inter-process communication. This is plain wrong! Named POSIX semaphores are kernel level objects and can effectively be used for IPC.
These and many others are the reasons why there was a concerted drive in the Unix C community for POSIX compliance.
ReplyDeleteBy the way, `sem_wait` and `sem_post` do exist as part of the POSIX API for semaphores. I am not sure if the book has introduced them yet. But if you read the man page for `sem_overview` on a fairly recent Linux box, you will be able to see the names of the various `sem_` system calls at the bottom of the man page under the SEE ALSO section.
great post buddy :)
ReplyDelete