System v semaphore realizes the shared memory synchronization mechanism between processes --- ring queue buffer

Shared memory : The previous article has already introduced shm shared memory and system v semaphore mechanisms, so I won’t repeat them here.

Application scenario :
There are many ways of inter-process communication, and the fastest of them should be shared memory. Because the communication is directly carried out through physical memory sharing, the speed is incomparable to other network methods. But without a synchronization mechanism to manage this memory, the application scenarios will be very limited. Next, we will add a synchronization mechanism to the shared memory through the system v semaphore to make it a perfect inter-process communication function.

Shared ring queue model between processes-producer, consumer model :
Insert picture description herering buffer data diagram : the
Insert picture description here
key code is as follows :

struct sembuf{
    
    
      unsigned short sem_num;  /* semaphore number */除非使用一组信号量,否则它为0        
      short          sem_op;   /* semaphore operation */ p -1,  v  1      		
      short          sem_flg;  /* operation flags */0就好 SEM_NOWAIT   SEM_UNDO
}

typedef struct shmhead {
    
        
int rd_idx; // 读入数据索引    
int wr_idx; // 写数据索引    
int blocks; // 存数据块数量    
int blksz;  // 每个数据块大小
}shmhead_t; 

typedef struct shmfifo {
    
    
    shmhead_t *p_head;    // 共享内存的起始地址
    char *     p_payload; // 有效数据的起始地址    
    int shmid;            // 打开的共享内存id    
    int sem_mutex;        // 互斥量     
    int sem_empty;        // 还剩多少个可以消费     
    int sem_full; // 剩余多少个地方可以生产
    }shmfifo_t;
主要通过三个信号量来解决进程间读写环形缓冲区的临界区资源的互斥性
// 初始化函数
shmfifo_t *shmfifo_init(key_t key, int blocks, int blksz);
// 放入数据
void shmfifo_put(shmfifo_t *fifo, const void *buf);
// 取得数据
void shmfifo_get(shmfifo_t *fifo, void *buf);
// 结构销毁 
void shmfifo_destroy(shmfifo_t *fifo);
#include "shmfifo.h"
typedef union semun{
    
    
    int val;
}semun; 

// 初始化
shmfifo_t* shmfifo_init(key_t key, int blocks, int blksz)
{
    
    
    shmfifo_t *p = malloc(sizeof(shmfifo_t));     
    int shmid = shmget(key, 0, 0);    
    int len = sizeof(shmhead_t) + blocks*blksz; //共享内存段大小     
    if(shmid == -1 )  // 内存段不存在,创建    
    {
    
               
        shmid = shmget(key, len, IPC_CREAT|0644);        
        if ( shmid == -1)
        {
    
     
           perror("shmget"),
           exit(1);         //初始化内存段头    
        }    
        p->p_head = shmat(shmid, NULL, 0); //将开出的内存段挂载到进程地址空间        
        p->p_head->rd_idx = 0;        
        p->p_head->wr_idx = 0;        
        p->p_head->blocks = blocks;        
        p->p_head->blksz  = blksz;        //初始化后段        
        p->p_payload = (char*)(p->p_head+1);        
        p->shmid = shmid;        
        p->sem_mutex = semget(key,   1, IPC_CREAT|0644);        
        p->sem_empty = semget(key+1, 1, IPC_CREAT|0644);        
        p->sem_full  = semget(key+2, 1, IPC_CREAT|0644);                

        semun su = {
    
    1}; //设置互斥信号量初值为1        
        semctl(p->sem_mutex, 0, SETVAL, su);         
        su.val = blocks;        
        semctl(p->sem_empty, 0, SETVAL, su);         
        su.val = 0; //初始不能消费        
        semctl(p->sem_full, 0, SETVAL, su);    
    }    
    else   //内存段存在 ,打开     
    {
    
             
        p->p_head = shmat(shmid, NULL, 0);        
        p->p_payload = (char*)(p->p_head+1);        
        p->shmid = shmid;        
        p->sem_mutex = semget(key,   0, 0); //        
        p->sem_empty = semget(key+1, 0, 0);        
        p->sem_full  = semget(key+2, 0, 0);    
    }    
    return p;
} 
static void P(int id)
{
    
        
    struct sembuf sb[1] = {
    
    0,-1, 0};
    semop(id, sb, 1);
} 
static void V(int id)
{
    
        
    struct sembuf sb[1] = {
    
    0, 1, 0};    
    semop(id, sb, 1);
} 
// 放入数据
void shmfifo_put(shmfifo_t *fifo, const void *buf)
{
    
    
    P(fifo->sem_empty);  //有多少地方可供生产,确保有空位生产    				   
    P(fifo->sem_mutex); //保证进程互斥
    memcpy(fifo->p_payload + fifo->p_head->wr_idx * fifo->p_head->blksz,uf,fifo->p_head->blksz);  //每次写入一个数据块大小
    fifo->p_head->wr_idx = (fifo->p_head->wr_idx+1)        %fifo->p_head->blocks;  //取模,保证数据存满时,转从payload处写数据     
    V(fifo->sem_full);    
    V(fifo->sem_mutex);
} 
// 取得数据
void shmfifo_get(shmfifo_t* pFifo, void *buf)
{
    
        
    P(pFifo->sem_full);  //确保有数据可取
    P(pFifo->sem_mutex);    //从内存段读取,拷入buf中       
    memcpy(buf,pFifo->p_payload + pFifo->p_head->rd_idx* pFifo->p_head->blksz, pFifo->p_head->blksz);
    pFifo->p_head->rd_idx = (pFifo->p_head->rd_idx+1)        %pFifo->p_head->blocks;  //取模,保证数据存满时,转从payload处取数据     
    V(pFifo->sem_empty);    
    V(pFifo->sem_mutex);
} 
// 销毁 
void shmfifo_destroy(shmfifo_t* pFifo)
{
    
        
    shmdt(pFifo->p_head);  //取消内存段挂载
    shmctl(pFifo->shmid, IPC_RMID, 0); //释放掉该内存段        
    //删除信号量    
    semctl(pFifo->sem_mutex, 0, IPC_RMID, 0);    
    semctl(pFifo->sem_empty, 0, IPC_RMID, 0);    
    semctl(pFifo->sem_full, 0, IPC_RMID, 0);     
    free(pFifo);
}              
消费者进程代码:
#include "shmfifo.h"                                         #include <unistd.h>
typedef struct Products{
    
    
    int id;
    char pro_name[10];
}Pro;

int main(){
    
    
    shmfifo_t* fifo = shmfifo_init(12345, 3, sizeof(Pro));    
    Pro p;
    while( 1){
    
    
       memset(&p, 0x00, sizeof(p));        
       shmfifo_get(fifo, &p);
       printf("id:%d, 产品名:%s\n", p.id, p.pro_name);        
       sleep(1);
    }
    shmfifo_destroy(fifo);
}

生产者进程代码:
#include "shmfifo.h"                                              typedef struct Product{
    
    
    int id;
    char pro_name[10];
}Pro;

int main(){
    
    
    shmfifo_t *fifo = shmfifo_init(12345, 4, sizeof(Pro));    
    Pro p;
    for (int i=0; i<20; ++i){
    
    
      memset(&p, 0x00, sizeof(p));        
      sprintf(p.pro_name, "iphone%d", i);
      p.id = i+1;
      shmfifo_put(fifo, &p);
      printf("put %d ok\n", i);
    }
}

Guess you like

Origin blog.csdn.net/wangrenhaioylj/article/details/109138178