SYSV IPC uses 32-bit identifiers, called 'keys', to identify shared IPC objects. Generally, each application will have a key hard-coded in it, or will generate one at runtime based on the properties of a specific file. Unfortunately, there is no way to be absolutely sure that a SYSV IPC key is unique for your application.
The most commonly used method of generating an IPC key that is reasonably unique is to use the ftok() function. It requres sys/types.h and sys/ipc.h, and its prototype is as follows:
key_t ftok(char *pathname, char proj_id);
proj_id is an 8-bit value used to (hopefully) make the key somewhat more likely to be unique. There is no established system for selecting project ids, though. In fact, from the ftok manpage BUGS section:
The generated key_t value is obtained stat-ing the disk file corresponding to pathname in order to get its i-node number and the minor device number of the filesystem on which the disk file resides, then by combining the 8 bit proj value along with the lower 16 bits of the i-node num- ber, along with the 8 bits of the minor device number. The algorithm does not guarantee a unique key value. In fact
- Two different names linking to the same file pro- duce same key values.
- Using the lower 16 bits of the i-node number, gives some chance (also usually small) to have same key values for file names referring to different i-nodes.
- Not discriminating among major device numbers, gives some chance of collision (also usually small) for systems with multiple disk controllers.
Now, assuming you have computed (or have determined at compile-time) a key that all instances of the application will use (i.e. by each instance of the application ftok()ing the same file), you're ready to get access to the set of semaphores using that key. You do that with the semget() call (defined in sys/sem.h).
int semget(key_t key, int nsems, int flags);
key is the key to used to create the semaphores 'on', nsems is the number of semaphores you want in the set, and flags can be any combination of IPC_CREAT and IPC_EXCL, whose meanings are similar to the flags of the open(2) call. The lower 9 bits of the flags specify user, group, and other permissions for the set of semaphores. See the semget manpage for more details of permissions.
The function returns yet another integer identifier that you use to do operations on that set of semaphores.
Most manipulations of a semaphore set are done through the semctl() call:
int semctl(int semset_id, int sem_number, int command, union semun arg);
semset_id specifies the particular set of semaphores to operate upon, sem_number, when appropriate, specifies a particular semaphore within that set, and command specifies what to do to that semaphore or set. commands include:
get permission info and put it in the structure specified by arg.buf
set permission information, if you have permission to do so
destroy the semaphore set and wake up all processes waiting on it with the error code EIDRM
obtain the current values of all the semaphores atomically
obtain the value of the specific semaphore in the set atomically
set the values of all the semaphores in the set atomically
set the value of a particular semaphore, atomically
For more commands, and specifics of each, look at the semctl(2) manpage.
int semop(int semset_id, struct sembuf *semops, unsigned nsops);
The function semop() is used to do operations such as incrementing and decrementing semaphores in a set, and waiting for semaphores to reach certain values.
semset_id is the id of the semaphore set to operate upon, and semops points to an array of semaphore operations to carry out. If all of the operations in semops cannot be carried out, none are. nsops specifies the length of the semops array.
See the semop(2) manpage for details and types of semaphore operations.