Use of semaphore P/V operations and shared resources

Shared Memory (SHM)
    Shared memory is the most efficient IPC because it abandons the "agent" of the kernel and directly
The exposed memory is placed in front of the processes that need data transmission and let them do it themselves. The price of this is: these processes must be careful
Operate this exposed shared memory carefully and do tasks such as synchronization and mutual exclusion. After all, there is no one to help them manage it now.
After all, you have to do everything yourself. For this reason, shared memory generally cannot be used alone, but must be used in conjunction with semaphores,
Coordination mechanisms such as mutual exclusion locks allow each process to exchange data efficiently without accidents such as data trampling and destruction.
The idea of ​​shared memory is very simple. The virtual memory spaces between processes are originally independent of each other and cannot access each other.
However, some methods can be used to map the same piece of physical memory to different process virtual spaces multiple times.
This effect is equivalent to the virtual memory space of multiple processes partially overlapping together, see the schematic diagram.

The general steps for using shared memory are:
1. Get the ID of the shared memory object
2. Map the shared memory to a certain area of ​​the virtual memory space of this process.
3. Release the mapping relationship when no longer in use.
4. When no process needs this shared memory anymore, delete it
Semaphore (SEM)
     The full name of semaphore SEM is Semaphore, which is also translated as signal light in Chinese. As the last type of system-V IPC, semaphores are very different from the previous MSG and SHM . SEM is not used to transmit data, but as a "semaphore" to coordinate the work of various processes or threads.
Some basic concepts are as follows:
        1. Resources (variables, linked lists, files, etc.) that multiple processes or threads may access at the same time are called shared resources.
Also called critical resources.
        2. The code that accesses these resources is called critical code, and these code areas are called critical zones.
        3. Before the program enters the critical section, it must apply for resources. This action is called P operation. This is just like if you want to
Before driving the car into the parking lot, you must first apply for a parking card from the security guard. The P operation is to apply for resources. If the application is successful,
If successful, the number of resources will be reduced. If the application fails, either wait at the door or leave.
        4. After the program leaves the critical section, it must release the corresponding resources. This action is called a V operation. This is just like when you put
After the car drives out of the parking lot, just like returning the parking card to the security guard, the V operation is to release resources, and releasing resources is to let the resources go.
The number of sources increases.
         All processes that access common critical resources must follow the above game rules, otherwise everyone will be in chaos, but
It is worth noting that these rules are voluntary. If a process is acting randomly - not applying before accessing the resource, then
This may lead to logical fallacies, just like driving a car over a security guard and crashing directly into the parking lot. Although it is not possible to do so emotionally or rationally,
There is nothing physically possible to prevent this behavior.
        
         The semaphore of system-V is very similar to the cards in the parking lot. Imagine a parking lot with N parking spaces. Each
The parking space is three-dimensional and can be lifted and lowered, and can park n cars. Then we can use a semaphore element with N semaphore elements.
The initial value of the number element is equal to the semaphore n to represent the parking space resources of this parking lot - a certain car driver wants to use his m
A car drives into the parking lot. If a parking space is needed, it must apply for resources for the semaphore element representing this parking space.
If n is greater than or equal to m , the application is successful, otherwise the car cannot be driven in.
            

  For the use of shared memory and semaphores 

The sending code is as follows jack.c

#include<stdio.h>
#include <sys/types.h> 
#include <sys/shm.h>
 #include <sys/ipc.h> 
 #include <sys/sem.h>
 #include <unistd.h>
 #include <stdlib.h>

union semun
{
    int val;                 /* 当 cmd 为 SETVAL 时使用 */ 
    struct semid_ds *buf;    /* 当 cmd 为 IPC_STAT 或 IPC_SET 时使用 */
    unsigned short *array;   /* 当 cmd 为 GETALL 或 SETALL 时使用 */
    struct seminfo *__buf;   /* 当 cmd 为 IPC_INFO 时使用 */
};

 
char * shm_init()
{
    //获取KEY值
     int key=ftok("./",'K');
    
     int shm_id=shmget(key, 4096,IPC_CREAT|0666);
     if(shm_id==-1)
     {
        perror("shmget id erorr");
        exit(1);//直接结束进程
     }
    //映射共享内存
    char *shm_map=shmat(shm_id, NULL, 0);
    if(shm_map==(void *)-1)
    {
        perror("shm map error");
         exit(1);//直接结束进程
    }

    return shm_map;
    
}

int sem_init()
{
    //获取新的KEY值
       int key=ftok("./",'X');
    //获取信号量的ID
     int sem_id=semget(key, 2, IPC_CREAT|0644);
     if(sem_id==-1)
     {
        perror("sem get id error ");
        exit(1);
     }
     //初始化信号量的内容 主要是初始化他们的初始化的资源数
      
     //初始化没有数据,有一个空间
     union semun set;
     set.val=0;   
     semctl(sem_id, 0, SETVAL, set);   //0 初始化数据资源
     set.val=1; 
     semctl(sem_id, 1, SETVAL,set );  //1 初始化空间资源

     return sem_id;
}

int main(int argc, char const *argv[])
{

    //配置共享内存并初始化
     char *shm_map=shm_init();
     //初始化信号量
     int  sem_id=sem_init();
    //再写入共享内存之前需要现申请一个空间资源
     /* struct sembuf 
        { 
            unsigned short sem_num;     /* 信号量元素序号(数组下标) 
            short sem_op;               /* 操作参数 *
            short sem_flg;              /* 操作选项 
        };*/
    struct sembuf space={     //设置空间资源 
        .sem_num=1,          //需要设置的空间资源元素下表为1
        .sem_flg=0,          //设置标记为0 啥也不选
        .sem_op=-1           //-1表示资源量即将建议  申请资源
    };
      struct sembuf data={     //设置空间资源 
        .sem_num=0,          //需要设置的空间资源元素下表为0
        .sem_flg=0,          //设置标记为0 啥也不选
        .sem_op=1           //1表示资源量即将加1  释放资源
    };
    while (1)
    {
        
       //等待空间资源  会阻塞 如果资源暂时不能得到则会阻塞等待
        semop(sem_id,  &space, 1);
        printf("请输入需要发送的数据\n"); 
        fgets(shm_map,4096,stdin);
        //设置数据资源为1 
        semop(sem_id,  &data, 1);/* code */
    }

    return 0;
}
Receiver code rocs.c
#include<stdio.h>
#include <sys/types.h> 
#include <sys/shm.h>
 #include <sys/ipc.h> 
 #include <sys/sem.h>
 #include <unistd.h>
 #include <stdlib.h>

union semun
{
    int val;                 /* 当 cmd 为 SETVAL 时使用 */ 
    struct semid_ds *buf;    /* 当 cmd 为 IPC_STAT 或 IPC_SET 时使用 */
    unsigned short *array;   /* 当 cmd 为 GETALL 或 SETALL 时使用 */
    struct seminfo *__buf;   /* 当 cmd 为 IPC_INFO 时使用 */
};

 
char * shm_init()
{
    //获取KEY值
     int key=ftok("./",'K');
    
     int shm_id=shmget(key, 4096,IPC_CREAT|0666);
     if(shm_id==-1)
     {
        perror("shmget id erorr");
        exit(1);//直接结束进程
     }
    //映射共享内存
    char *shm_map=shmat(shm_id, NULL, 0);
    if(shm_map==(void *)-1)
    {
        perror("shm map error");
         exit(1);//直接结束进程
    }

    return shm_map;
    
}

int sem_init()
{
    //获取新的KEY值
       int key=ftok("./",'X');
    //获取信号量的ID
     int sem_id=semget(key, 2, IPC_CREAT|0644);
     if(sem_id==-1)
     {
        perror("sem get id error ");
        exit(1);
     }
     //初始化信号量的内容 主要是初始化他们的初始化的资源数
      
     //初始化没有数据,有一个空间
     union semun set;
     set.val=0;   
     semctl(sem_id, 0, SETVAL, set);   //0 初始化数据资源
     set.val=1; 
     semctl(sem_id, 1, SETVAL,set );  //1 初始化空间资源

     return sem_id;
}

int main(int argc, char const *argv[])
{

    //配置共享内存并初始化
     char *shm_map=shm_init();
     //初始化信号量
     int  sem_id=sem_init();
    //再写入共享内存之前需要现申请一个空间资源
     /* struct sembuf 
        { 
            unsigned short sem_num;     /* 信号量元素序号(数组下标) 
            short sem_op;               /* 操作参数 *
            short sem_flg;              /* 操作选项 
        };*/
    struct sembuf space={     //设置空间资源 
        .sem_num=1,          //需要设置的空间资源元素下表为1
        .sem_flg=0,          //设置标记为0 啥也不选
        .sem_op=1           //1表示资源量即将加以  释放资源
    };
      struct sembuf data={     //设置空间资源 
        .sem_num=0,          //需要设置的空间资源元素下表为0
        .sem_flg=0,          //设置标记为0 啥也不选
        .sem_op=-1          //1表示资源量即将加1  释放资源
    };
    while (1)
    {
        printf("wait 数据\n");
       //等待数据资源  会阻塞 如果资源暂时不能得到则会阻塞等待
        semop(sem_id,  &data, 1);
        printf("Jacl 说:%s\n",shm_map);
        //设置空间资源为1 
        semop(sem_id,  &space, 1);/* code */
    }

    return 0;
}

Guess you like

Origin blog.csdn.net/m0_52467164/article/details/127538937