1. What is Semaphore
The semaphore is a special variable, and access is atomic.
Only two actions are allowed on it:
1) wait for the semaphore
When the semaphore value is 0 o'clock, the program waits; When the semaphore value is greater than 0 o'clock, the semaphore is reduced by 1, and the program continues to run.
2) Send signal volume
Add a semaphore value of 1.
We use semaphores to resolve synchronization issues caused by shared resources between processes or threads.
Use of the semaphore in 2.Linux
Linux provides a set of semaphore APIs that are declared in the header file sys/sem.h.
1) semget function: New semaphore
int semget (key_t key,int num_sems,int sem_flags);
Key: The semaphore key value, which can be understood as a unique token of the semaphore.
Num_sems: The number of semaphores, typically 1
Sem_flags: There are two values, ipc_create and IPC_EXCL,
Ipc_create indicates that the semaphore identifier is returned if the semaphore already exists.
IPC_EXCL indicates that an error is returned if the semaphore already exists.
return value: Corresponding semaphore identifier, failure return-1
2) Semop function: Modify the value of the semaphore
int semop (int sem_id,struct sembuf *sem_opa,size_t num_sem_ops);
SEM_ID: Semaphore identifier
SEM_OPA: Structure as follows
struct sembuf{ short sem_num ; unless a set of semaphores is used, it is 0 short sem_op; the amount of data that the semaphore needs to change in a single operation, usually two numbers, one is-1, that is, the P (wait) operation,// One is +1, which is the V (Send signal) operation. Short SEM_FLG; // typically Sem_undo, which enables the operating system to trace signals, // and when the process terminates without releasing the semaphore, the operating system releases the semaphore
3) Semctl function: For initialization and deletion of semaphores
int semctl (int sem_id,int sem_num,int command,[union Semun sem_union]);
Command: There are two values Setval,ipc_rmid, which represent the initialization and deletion of semaphores, respectively.
Sem_union: Optional parameters, the structure is as follows:
Union semun{ int val; struct semid_ds *buf; Short *arry;
Typically, Val is used to indicate the initial value to be passed to the semaphore.
Example of 3.Linux semaphore usage
In the following example, we have written a program that has a char type character in the program, Char message= ' x '
Then run two instances of the program at the same time.
The first instance, with a parameter, assigned the first word of the argument to a message, such as ' 0 '
Second instance, using the default message value ' X '
Our goal is to use the semaphore to loop through the two instances,
We can see that the execution result should be ' x0x0x0x0x0x0 '
#include <stdio.h>#include<stdlib.h>#include<sys/sem.h>Union semun{intVal; structSemid_ds *buf; unsigned Short*array;};intsem_id;intSet_semvalue () {Union Semun sem_union; Sem_union.val=1; if(Semctl (sem_id,0, setval,sem_union) ==-1) return 0; return 1;}intsemaphore_p () {structSembuf Sem_b; Sem_b.sem_num=0; Sem_b.sem_op= -1; SEM_B.SEM_FLG=Sem_undo; if(Semop (Sem_id,&sem_b,1)==-1) {fprintf (stderr,"semaphore_p failed\n"); return 0; } return 1;}intSemaphore_v () {structSembuf Sem_b; Sem_b.sem_num=0; Sem_b.sem_op=1; SEM_B.SEM_FLG=Sem_undo; if(Semop (Sem_id,&sem_b,1)==-1) {fprintf (stderr,"Semaphore_v failed\n"); return 0; } return 1;}voidDel_semvalue () {//Delete SemaphoreUnion Semun Sem_union; if(Semctl (sem_id,0, ipc_rmid,sem_union) ==-1) fprintf (stderr,"Failed to delete semaphore\n");}intMainintargcChar*argv[]) { CharMessage ='x'; //Create Semaphoresem_id = Semget ((key_t)1234,1,0666|ipc_creat); if(argc>1) { //Initialize the semaphore if(!Set_semvalue ()) {fprintf (stderr,"Init failed\n"); Exit (Exit_failure); } //the first character of the parameter assigned to the messagemessage = argv[1][0]; } intI=0; for(i=0;i<5; i++) { //wait for the semaphore if(!semaphore_p ()) exit (Exit_failure); printf ("%c", message); Fflush (stdout); Sleep (1); //Send Signal Volume if(!Semaphore_v ()) exit (Exit_failure); Sleep (1); } printf ("\n%d-finished\n", Getpid ()); if(argc>1) { //remove semaphore before exitingDel_semvalue (); } exit (exit_success);}
Output Result:
Linux Signal Volume detailed