Semaphores–System V semaphores and Posix semaphores

What is a semaphore

A semaphore is a counter used to control access to resources shared by multiple processes/threads. Often used together with locks. When a process/thread is accessing a resource, the semaphore can prevent another process/thread from disturbing it. Producer and consumer models are typical uses of semaphores.

Why are there two sets of semaphores (what are the differences between the two sets)

Briefly speaking, Posix is the abbreviation of “Portable Operating System Interface”, but it is not a single standard, but a series of standards developed by the Electrical and Electronic Engineering Society, the IEEE. It is also An international standard adopted by ISO (International Organization for Standardization) and IEC (International Electrotechnical Commission). System v is a branch of many versions of the Unix operating system. It was originally released by AT&T for the first time in 1983. System v There are four versions of v, and the most successful one is System V Release 4, or SVR4. From this point of view, one is one of the Unix standards (the other standard is Open Group), and the other is one of the branches of many versions of Unix. First (other branches include Linux and BSD), it should be said that the Posix standard is becoming more and more popular, and many manufacturers have begun to adopt this standard.

So what is the difference between the two, or application scenarios: 1. POSIX semaphores are often used for threads; system v semaphores are often used for process synchronization.

2. From a usage perspective, the use of System V semaphores is relatively complex, while the use of POSIX semaphores is relatively simple.

3. For POSIX, the semaphore is a non-negative integer. The System V semaphore is a collection of one or more semaphores, which corresponds to a semaphore structure. This structure serves System V IPC, and the semaphore is just a part of it.

4. Posix semaphore is memory-based, that is, the semaphore value is placed in shared memory, and it is identified by a name that may correspond to a path name in the file system. The System v semaphore is based on the kernel and is placed in the kernel.

5. The header file of POSIX semaphore is , while the header file of System V semaphore is .

6. Posix also has named semaphores, which are generally used for process synchronization. Named semaphores are sustained by the kernel.

[This article does not introduce too much about the famous Posix]

How to achieve it?

1. Create a new semaphore

System V Posix (unnamed)
int semget(key_t key,int nsems,int semflg ); int sem_init(sem_t *sem,int pshared,int values);
  • system V
#include<sys/type.h>
#include<sys/ipc.h>
#include<sys/sem.h>

int semget(key_t key,int nsems,int semflg);
/*
nsems: how many to create
semflg:IPC_CREAT、IPC_EXCL;
*/

Use System V functions to wrap the code that creates the semaphore;

typedef int sem_t;
union semun
{
int val;
struct semid_ds *buf; //pointer of semid_ds
unsigned short *array; //array type
} arg; //Define a global variable

sem_t CreateSem(key_t key,int value)
{
union semun sem; //Semaphore structure variable
sem_t sem_id;
sem.val = value; //Set initial value

sem_id = semget(key,0,IPC_CREAT|0666); //Get the semaphore id
if(sem_id == -1)
{
printf("create sem failed\\
");
exit(-1);
}
semctl(sem_id,0,SETVAL,sem); //Send command to establish value initial semaphores
return sem_id;
}
  • Posix semaphore: Just use that function directly, and you can add an error insurance. [The following chestnuts are the same, Posix is that simple]

2. PV operation (increase or decrease semaphore)

System V Posix (unnamed)
int semop(int semid,struct sembuf *sops, unsigned nsops); sem_post(sem_t *sem); sem_wait(sem_t *sem);
  • System V
/*
Parameter explanation:
struct sembuf
{
ushort sem_num; //The number of the semaphore
short sem_op; //Semaphore operation {positive or negative zero}
short sem_flg; //Semaphore operation flag {NOWAIT}
};
//sem_op takes 0 to set the semaphore to sleep state until the value of the semaphore is 0

nsops: the number of operations in the array
*/
int Sem_P(sem_t semid)
{
struct sembuf sops = {0, + 1,IPC_NOWAIT};
return (semop(semid, & amp;sops,1));
}
intSem_V(sem_t semid)
{
struct sembuf sops = {0,-1,IPC_NOWAIT};
return (semop(semid, & amp;sops,1));
}

P operation: perform an operation to increase the value of a semaphore. V operation: perform an operation to decrease the value of a semaphore.

  • Posix P:sem_post(sem_t *sem); V:sem_wait(sem_t *sem);

3. Control semaphore parameters

System V Posix
int semctl(int semid,int semnum,int cmd,…) ; /
#include<sys/type.h>
#include<sys/ipc.h>
#include<sys/sem.h>
int semctl(int semid,int semnum,int cmd,...);

/*
This function is a function that performs control operations on a collection of semaphores.
Parameter explanation:
semnum: The semaphore number to be performed. For the first semaphore in the collection, its value is 0.
cmd:
IPC_STAT: Get the semid_ds structure of a certain set and store it in the buf of the semun union.
IPC_SET: Set the value of the ipc_perm member in the semid_ds of a certain set. The value of this command is obtained from buf.
IPC_RMID: Remove this collection from the kernel.
GETTALL: used to obtain the values of all semaphores in the collection, stored in the array of the semun union.
GETPID: Returns the PID of the last semop call.
GETVAL: Returns the value of a semaphore in the collection.
GETZCNT: Returns the number of processes that are waiting for resource utilization to reach 100%.
SETALL: Set the values of all semaphores in the collection to the values in the array in the semun union.
SETVAL: Set the value of a semaphore in the collection to the value of val in the semun union.
*/

//I won’t leave the chestnuts

4. Destroy the semaphore

System V Posix (unnamed)
ctl customization int sem_destory(sem_t *sem);
  • System V
void DestroySem(sem_t semid)
{
union semun sem;
sem.val = 0;
se,ctl(semid,0,IPC_RMID,sem);
}

Finally, put a string of producer and consumer code

//Implement thread mutual exclusion

#include <iostream>
#include<unistd.h>
#include<stdlib.h>
#include<semaphore.h>
#include<errno.h>
#include<pthread.h>
using namespace std;
 
sem_t sem;
void* productor(void* arg)
{
    while(1)
    {
        sem_wait( & amp;sem);
        cout << "create noodle!!!" << endl;
        sem_post( &sem);
        usleep(10);
    }
    return NULL;
}
 
void* consumer(void* arg)
{
    while(1)
    {
        sem_wait( & amp;sem);
        cout << "eat noodle!!!" << endl;
        sem_post( &sem);
        usleep(10);
    }
    return NULL;
}
int main()
{
    pthread_t tid1,tid2;
    
    sem_init( & amp;sem, 0, 1);
 
    pthread_create( & amp;tid1, NULL, productor, NULL);
    pthread_create( & amp;tid2, NULL, consumer, NULL);
 
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    
    sem_destroy( & amp;sem);
    return 0;
}

Original author: look, future

Original address: Semaphore–System V Semaphore and Posix Semaphore-Tencent Cloud Developer Community-Tencent Cloud (Copyright belongs to the original author, please contact us to delete any infringement messages)