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