Linux system V semaphore

In Linux, a semaphore is a mechanism for synchronization and mutual exclusion between processes. It can be used to control access to shared resources to avoid race conditions caused by simultaneous access by multiple processes.

Linux provides two types of semaphores: System V semaphores and POSIX semaphores.

System V semaphores are operated through system calls such as semget, semop, and semctl. They are the basic mechanism for inter-process synchronization and mutual exclusion, and can be shared between different processes.

POSIX semaphores are operated through library functions such as sem_init, sem_wait, and sem_post. They are a more modern and flexible semaphore mechanism provided by Linux that can also be shared between different processes.

Whether it is System V semaphore or POSIX semaphore, they can be used to implement various synchronization and mutual exclusion mechanisms, such as mutex locks, condition variables, read-write locks, etc.

System V semaphore

  1. semget: Create or obtain a semaphore set. Each semaphore set contains multiple semaphores, each with a unique identifier.
  2. semop: Used to perform semaphore operations, including P operations (waiting for the semaphore) and V operations (releasing the semaphore). The P operation decrements the value of the semaphore by one. If its value is less than zero, the process will be blocked. The V operation increases the value of the semaphore by one and wakes up the waiting process.
  3. semctl: Used to perform semaphore control operations, such as obtaining and setting semaphore values, deleting semaphore sets, etc.

semget

int senget(key_t key, int nsems, int semfalg);
  • key: It is a key value used to identify the semaphore set. Multiple processes can use the same key to obtain the same semaphore set.
  • nsems: Indicates the number of semaphores contained in the semaphore set.
  • semflag: Specifies the flag to create or obtain a semaphore set. Can be used with IPC_CREAT to create new semaphore sets, with IPC_EXCL to ensure unique semaphore sets are created, and with other flags for permission settings (0666) . *

return value

  • Successfully returns a semaphore set identifier.
  • On failure, -1 is returned and errno is set.

Example:

################### Create a unique semaphore###################### #
key_t key = ftok("/usr/bin", 255);
    //Create a semaphore set and return an error if the semaphore already exists.
    m_semId = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);

################### Open an existing semaphore ######################
\t
m_semId = semget(key, 0, 0);

Parameters nsems, semfalg will be ignored.

semctl

 int semctl(int semid, int semnum, int cmd, union semnu arg);

union semnu
{<!-- -->
    int val;
    struct semid_ds *buf;
    unsigned short *array;
    struct seminfo *__buf;
};

parameter:

  • semid: The identifier of the semaphore set, created or obtained by the semget function.

  • semnum: Indicates the index in the specific semaphore set to be operated, usually 0 indicates the first semaphore.

  • cmd: Indicates the operation to be performed, which can be one of the following:

    • GETVAL: Get the current value of the semaphore.
    • SETVAL: Set the value of the semaphore.
    • GETPID: Get the process ID of the last semop operation
    • GETNCNT: Get the number of processes waiting for operations.
    • GETZCNT: Get the number of processes waiting for the zeroing operation.
    • SETALL: Used to set the value of a set of semaphores, usually used with the array provided in the arg parameter.
    • IPC_STAT: used to obtain the information result of the semaphore.
    • IPC_SET: Information structure used to modify the semaphore, usually used together with the sembuf structure provided in the arg parameter
    • IPC_RMID: Removes the semaphore set from the system.
    • etc.
  • arg: A union (union semun) used to pass the parameters required for the operation, the specific content depends on the value of cmd.

return value:

  • On failure, -1 is returned and errno is set. When successful, cmd marked yellow will return the corresponding value (non-negative value), and the rest will return 0.

semop

It allows processes to perform P (wait) and V (release) operations on semaphores to achieve synchronization and mutual exclusion between processes.

 int semop(int semid, struct sembug* sops, size_t nsops);

// Definition of sembug
struct sembuf {<!-- -->
    short sem_num; //The index of the semaphore in the semaphore set, starting from 0
    short sem_op; //Operation, usually a positive number indicates V operation, and a negative number indicates P operation
    short sem_flg; // Operation flag, usually 0, the value is SEM_UNDO | IPC_NOWAIT
};

If sem_op > 0, the value of the semaphore will be added to the value of sem_op, indicating that the process releases the controlled resources.
If sem_op = 0, if IPC_NOWAIT is not set, the calling process will enter sleep state until the value of the semaphore is 0; otherwise, the process will not sleep and return EAGAIN directly.
If sem_op < 0, the value of the semaphore is added to the value of sem_op. If IPC_NOWAIT is not set, the calling process will block until the resource is available; otherwise, the process returns EAGAIN directly.

parameter:

  • semid: The identifier of the semaphore set, created or obtained by the semget function.
  • sops: Pointer to an array of sembuf structures containing the operation to be performed and the semaphore index.
    • SEM_UNDO: Used to enable automatic undo when the process terminates. If this flag is set and the process exits abnormally after performing a semop operation, the kernel will automatically perform an undo operation and restore the value of the semaphore to the state before the operation to avoid resource leaks. This is typically used to prevent resource leaks due to abnormal process exits.
    • IPC_NOWAIT: For non-blocking operations. If this flag is set and the semop operation cannot be performed immediately (for example, because the semaphore value does not allow it), the operation does not wait but returns an error immediately.
  • nsops: Represents the number of operations in the sops array.

Example:

################### Perform P operation (wait for semaphore) ################### ##
struct sembuf operation;
operation.sem_num = 0; // Semaphore index of operation
operation.sem_op = -1; //Perform P operation
operation.sem_flg = SEM_UNDO;

semop(semid, &operation, 1);


################### Perform V operation (release the semaphore) #####################
struct sembuf operation;
operation.sem_num = 0; // Semaphore index of operation
operation.sem_op = 1; //Perform V operation
operation.sem_flg = SEM_UNDO; //When the program exits abnormally, the operation will be undone, and all operations in the program that set this flag will be undone.
semop(semid, &operation, 1);

The set of operations contained in the sops parameter are automatically executed in array order, that is, the operations are either executed as a complete unit or not at all. If not all operations can be performed immediately, the behavior of the system call depends on the presence of the IPC IPC_NOWAIT flag in the various sem_flg fields.

 # The initialization of both semaphores is set to 1

struct sembuf sops[2] = {<!-- -->0};
    sops[0].sem_flg = SEM_UNDO | IPC_NOWAIT;
    sops[0].sem_num = 0;
    sops[0].sem_op = 0;

    sops[1].sem_flg = SEM_UNDO;
    sops[1].sem_num = 1;
    sops[1].sem_op = -1;

    int rv = semop(m_semId, & amp;sops[0], 2);
    if (0 != rv)
    {<!-- -->
        printf("Lock error, errno = %d, errmsg = %s\
", errno, strerror(errno));
        return rv;
    }

In the above example, two semaphores in the semaphore set are operated at the same time. However, the first semaphore cannot be executed immediately because the IPC_NOWAIT attribute is set, so the semop fails at this time and errno is set to EAGAIN (and sops are not executed. any operation).

Notes

  • The created semaphore set needs to be released manually when the program ends. If it is not released, it will not be recycled by the system even when the program exits. (Semaphores can be deleted using the ipcrm command).
  • When multiple processes use the same semaphore set, if one process releases the semaphore set, other processes will fail when operating on the semaphore set.