970 Chapter 47
The semid argument is the identifier of the semaphore set on which the operation is
to be performed. For those operations performed on a single semaphore, the
semnum argument identifies a particular semaphore within the set. For other opera-
tions, this argument is ignored, and we can specify it as 0. The cmd argument specifies
the operation to be performed.
Certain operations require a fourth argument to semctl(), which we refer to by
the name arg in the remainder of this section. This argument is a union defined as
shown in Listing 47-2. We must explicitly define this union in our programs. We do
this in our example programs by including the header file in Listing 47-2.
Although placing the definition of the semun union in a standard header file
would be sensible, SUSv3 requires the programmer to explicitly define it
instead. Nevertheless, some UNIX implementations do provide this definition
in <sys/sem.h>. Older versions of glibc (up to and including version 2.0) also
provided this definition. In conformance with SUSv3, more recent versions of
glibc do not, and the macro _SEM_SEMUN_UNDEFINED is defined with the value 1 in
<sys/sem.h> to indicate this fact (i.e., an application compiled against glibc can
test this macro to determine if the program must itself define the semun union).
Listing 47-2: Definition of the semun union
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––svsem/semun.h
#ifndef SEMUN_H
#define SEMUN_H /* Prevent accidental double inclusion */
#include <sys/types.h> /* For portability */
#include <sys/sem.h>
union semun { /* Used in calls to semctl() */
int val;
struct semid_ds * buf;
unsigned short * array;
#if defined(__linux__)
struct seminfo * __buf;
#endif
};
#endif
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––svsem/semun.h
SUSv2 and SUSv3 specify that the final argument to semctl() is optional. However, a
few (mainly older) UNIX implementations (and older versions of glibc) prototyped
semctl() as follows:
int semctl(int semid, int semnum, int cmd, union semun arg);
This meant that the fourth argument was required even in the cases where it is not
actually used (e.g., the IPC_RMID and GETVAL operations described below). For full
portability, we specify a dummy final argument to semctl() in those calls where it is
not required.
In the remainder of this section, we consider the various control operations
that can be specified for cmd.