[Inter-process communication]------ semaphore (sems)

I have always wanted to see the ftok function. Today, I will briefly introduce the
ftok() function. We must specify an ID value when conducting IPC communication. This value is usually provided by ftok.

The prototype of ftok is as follows:
key_t ftok( char * fname, int id )
Parameter description:
The document name
id you specify when fname is the subsequence number.
Return value:
In the general UNIX implementation, the inode number of the document is taken out, and the sub-sequence number is added in front to get the return value of key_t.
For example, if the inode number of the specified document is 65538, which is 0x010002 in hexadecimal, and the ID value you specify is 38, which is 0x26 in hexadecimal, the return value of the final key_t is 0x26010002.

Recognize semaphores

The semaphore is mainly used for synchronization and mutual exclusion. The essence of the semaphore is a counter. The semaphore records the number of critical resources. The number of the semaphore is as much as the number of the semaphore. The value of the semaphore is called two. Meta semaphore (also called binary semaphore called mutex ). The lifetime of a semaphore varies with the kernel.

process mutual exclusion

  • Because each process requires shared resources, and some resources need to be mutually exclusive, so each process competes to use these resources, and this relationship between processes is process mutual exclusion.
  • Some resources in the system are only allowed to be used by one process at a time, and such resources are called critical resources or mutually exclusive resources.
  • Programs involving mutually exclusive resources in a process are called critical sections.
    Process synchronization refers to the need for multiple processes to cooperate with each other to complete a task.
    Semaphores and P, V primitives (p, v operations are atomic, either done or not done, no intermediate state is generated.`

  • Semaphores and P and V primitives were proposed by Dijkstra

  • Semaphore
    Mutual exclusion : P and V are in the same process
    Synchronization: P and V are not in the same process Meaning of
    semaphore
    : s>0: s means the number of available resources
    s=0: means no available resources, no Waiting process
    s<0:|s| indicates the number of processes in the waiting queue

Semaphore Structure Pseudocode

信号量本质上是一个计数器
struct   semaphore
{
    int  value
    point_PCB  queue;
}

p primitive

p(s)
{
s.value=s.value–;
if(s.value<0)
{
The process state is set to the waiting state
The PCB of the process is inserted into the end of the corresponding waiting queue s.queue
}
}

v primitive

v(s)
{
s.value=s.value++;
if(s.value>=0)
{
Wake up a process waiting in the corresponding waiting queue s.queue,
change its state to ready state
and insert it into the ready queue
}
}

Semaphore set function

semget function

Function: used to create and access a semaphore set
Prototype :
int semget (key_t key, int nsems, int semflgs);
parameters:
key: the name of the semaphore set
nsems: the number of semaphores in the semaphore set
semflg: composed of nine It is composed of permission flags, and their usage is the same as the mode flag used when creating files.
Return value; a non-negative integer is returned for success, that is, the identification code of the signal, and -1 is returned for failure

shmctl function

Function: used to control the semaphore set
Prototype :
int semctl (int semid, int semnum, int cmd, ....)
Parameters:
semid: the semaphore set identification code returned by semget
semnum: the number of the semaphore in the semaphore set
cmd: taken in the future Action (with three possible values)
The last parameter varies depending on the command
Return value: 0 for success, -1 for failure

Order illustrate
SETVAL Set the count value of the semaphore in the semaphore set
GETVAL Get the count value of the semaphore in the semaphore set
IPC_STAT Set the data in the semid_ds structure to the current associated value of the semaphore set
IPC_SET On the premise that the process has sufficient privileges, set the current associated value of the semaphore set to the value in the semid_ds data structure
IPC_RMID delete signal set

semop function

Used to create and access a semaphore set
Prototype :
int semop (int semid, struct sembuf *sops, unsigned nsops);
parameters:
semid: is the identification code of the semaphore, and is also the return value of the semget function
sops: is a pointer to a structure Numerical pointer
nsops: the number of semaphores
Return value: successful return, failure return -1

sembuf structure:

       struct sembuf{
                   short sem_num;
                   short sem_op;
                   short sem_flag;
                   };

sem_num is the number of the semaphore.
sem_op is the value added or subtracted during one pv operation of the semaphore. Generally, only two values ​​are used:
one is "-1", that is, the p operation is performed, waiting for the semaphore to become
available ; the other is "+1", also It is the v operation we performed, and the semaphore has become available
. The two values ​​of sem_flag are IPC_NOWAIT or SEM_UNDO

Example code:
Two processes print at the same time, the display is a critical resource, and a binary semaphore (mutual exclusion lock) is used for protection.
Code:

Makefile

 sem:comm.c sem.c                                                                                                                                          
  2         gcc -o $@ $^
  3 .PHONY:clean
  4 clean: 
  5         rm -f sem
  6 

comm.h

 1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/ipc.h>
  4 #include <sys/sem.h>
  5 
  6 
  7 #define PATHNAME "."
  8 #define PROJ_ID 0x6666
  9 
 10 union semun{
 11     int val;
 12     struct semid_ds *buf;
 13     unsigned short *arr;
 14     struct seminfo *_buf;
 15 };
 16 int cerateSemSet(int nums);
 17 int initSem (int semid,int nums,int initVal);
 18 int P(int semid,int who);
 19 int V(int semid,int who);
 20 int destroySemSet(int semid);
 21 
 22 
 23                                                                                                                                                           
~                       

comm.c

1 #include "comm.h"
  2 
  3 static int  commSemSet(int nums,int flags)
  4 {
  5     key_t _key=ftok(PATHNAME,PROJ_ID);
  6     if(_key<0){
  7         perror("ftork");
  8         return -1;
  9     }
 10     int semid=semget(_key,nums,flags);
 11     if(semid<0){
 12         perror("semget");
 13         return -2;
 14     }
 15     return semid;
 16 }
 17 int createSemSet(int nums){
 18     return commSemSet(nums,IPC_CREAT|IPC_EXCL|0666);
 19 }
 20 int getSemSet(int nums){
 21     return commSemSet(nums,IPC_CREAT);
 22 }
 23 
 24 int initSem(int semid,int nums,int initVal){
 25     union semun _un;
 26     _un.val=initVal;
 27     if(semctl(semid,nums,SETVAL,_un)<0){
 28         perror("semctl");
 29         return -1;
 30     }
 31     return 0;
 32 }
 33 
 34 static int commPV(int semid,int who,int op){
 35     struct sembuf _sf;
 36     _sf.sem_num=who;
 37     _sf.sem_op=op;
 38     _sf.sem_flg=0;
 39     if(semop(semid,&_sf,1)<0){
 40         perror("semop");
 41         return -1;
 42     }
 43     return 0;
 44 }
 45 
 46 int P(int semid,int who){
 47     return commPV(semid,who,1);
 48 }
 49 int V(int semid,int who){
 50    return commPV(semid,who,1);
 51 }
 52                                                                                                                                                                                                                                                                            
 53 int destroySemSet(int semid){
 54     if(semctl(semid,0,IPC_RMID)<0){
 55         perror("semctl");
 56         return -1;
 57     }
 58 }

sem.c

 1 #include "comm.h"
  2 
  3 int main()
  4 {
  5     int semid=createSemSet(1);
  6     initSem(semid,0,1);
  7     pid_t id=fork();
  8     if(id==0){
  9         int _semid=getSemSet(0);
 10         while(1){
 11             P(_semid,0);
 12             printf("A");
 13             fflush(stdout);
 14             usleep(100000);
 15             printf("A");
 16             fflush(stdout);
 17             usleep(100000);
 18             V(_semid,0);
 19         }
 20     }
 21     else {
 22         while(1){
 23             P(semid,0);
 24             printf("B");
 25             fflush(stdout);
 26             usleep(100000);
 27             printf("B");
 28             fflush(stdout);
 29             usleep(100000);
 30             V(semid,0);
 31         }
 32             wait(NULL);
 33         }
 34         destroySemSet(semid);
 35         return 0;
 36 }                                                                                                                                                                                                                                                                          

The results are as follows:
write picture description here
When we run the program again, what will we find?
write picture description here
Our solution is:
write picture description here

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325454983&siteId=291194637