POSIX semaphore code analysis in Linux (P/V operation)

POSIX semaphore

1. Basic concepts

The logic of POSIX semaphore is exactly the same as that of semaphore elements in IPC semaphore group, but the operation of POSIX semaphore is simpler and the interface is easier to use. It is widely used in multi process and multi thread.
POSIX semaphores are divided into two types:

POSIX anonymous semaphore
It is usually used between lines
It only exists in memory and is not visible in the file system
POSIX named semaphore
Usually used between processes
It exists in the file system / dev/shm and can be operated by different processes

2. POSIX anonymous semaphore

2. Definitions

#include <semaphore.h>
sem_t s;

2.2 initialization

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);

Interface Description:
sem: semaphore pointer to be initialized
pshared: Specifies the scope of the semaphore
0: works between threads within a process
Non 0: acts on interprocess
Value: initial value of semaphore
Example

sem_t s;
int main()
{
  // Initialize POSIX anonymous semaphore:
  // Set it to be used between threads in this process
  // And set its initial value to 1
  sem_init(&s, 0, 1);
}

2.3 P/V operation

The P/V operation of POSIX semaphores (whether anonymous or named) is very simple compared with the semaphore group of systemV:
#include <semaphore.h>
int sem_wait(sem_t *sem); // P operation
int sem_post(sem_t *sem); // V operation
Interface Description:
P operation is to apply for resources, so sem_wait() will block when resources are insufficient. V operation is to release resources, and V operation will never block
Example

#include <semaphore.h>
sem_t s;
char buf[100];
void *routine(void *arg)
{
    while(1)
    {
        // Apply semaphore - 1, output string length p operation
        sem_wait(&s);
        printf("%d\n", strlen(buf));
    }
}
int main()
{
    // Initialization, the initial value of semaphore is 0
    sem_init(&s, 0, 0);
    pthread_t t;
    pthread_create(&t, NULL, routine, NULL);
    while(1)
    {
        fgets(buf, 100, stdin);
        // After entering the string, release the semaphore + 1 V operation
        sem_post(&s);
    }
}

3. POSIX named semaphore

POSIX named semaphore is mainly used for synchronization and mutual exclusion between multiple processes. Its P/V operation is no different from the anonymous version. Its biggest feature is that it exists in the file system / dev/shm and can be opened by any process with permission in the system.

3.1 creating and opening

POSIX named semaphores are created using the following interfaces:

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

explain
Similar to the file IO function open(), sem_open() also provides two versions. The file permission mode and initial value need to be specified during initial construction. It is not required to be specified during subsequent opening.
Example
//Create a named semaphore in process a.c

int main()
{
    // Create a named semaphore. Parameter 1 represents that the initial value is 1
    sem_t *s = sem_open("mysem", O_CREAT, 0666, 1);
}

//Open a named semaphore in process b.c

int main()
{
    // Open named semaphore
    sem_t *s = sem_open("mysem", O_RDWR);
}

Compile the program a.c (pay attention to adding the line library lpthread) and run the program, and the corresponding file will be generated in the system / dev/shm /
gec@ubuntu:~$ gcc a.c -o a -lpthread
gec@ubuntu:~$ ./a
gec@ubuntu:~$ ls -l /dev/shm/
Total consumption 4
-rw-rw-r-- 1 gec gec 32 Nov 26 18:27 sem.mysem
gec@ubuntu:~$

3.2 P/V operation

Exactly consistent with anonymous semaphores:

#include <semaphore.h>
int sem_wait(sem_t *sem); // P operation
int sem_post(sem_t *sem); // V operation

Example
// a.c

int main()
{
    sem_t *s = sem_open("mysem", O_CREAT, 0666, 0);
    printf("A\n");
    sem_post(s); // V operation
}
// b.c
int main()
{
    sem_t *s = sem_open("mysem", O_RDWR);
    // Wait for A to complete before executing B
    sem_wait(s); // P operation
    printf("B\n");
}

The V operation of semaphore is like A remote switch, which controls the progress of another process: SEM has not been executed in process A_ Process B will be in SEM until post (s)_ Wait (s) wait quietly, which is multi process progress control.
Note that the above program a.c and program b.c are two independent programs without any shared variables and data. They cooperate through the named semaphore based on the file system.

3.3 closing, deleting and other precautions

POSIX named semaphores are very similar to file operations. After opening, they will be maintained in the kernel, so they should be closed when they are no longer needed:

sem_close(s);

In addition, even if all processes close the semaphore and exit, the file corresponding to the named semaphore will not disappear, and all the values after P/V operation will be retained. If the file itself is no longer needed, it can be deleted directly in the file system, or use the following interface:

sem_unlink("mysem");

As mentioned above, the named semaphore will all the values after P/V operation. Therefore, if the above program a.c is executed three times continuously, the value of the semaphore will be + 3. Therefore, program b.c can perform P operation three times continuously.

Keywords: Linux Operation & Maintenance bash thread pool

Added by polarbear66 on Sat, 01 Jan 2022 10:41:55 +0200