system -v 信号量的使用

信号量的作用

信号量是system -v IPC中的一种,通过P、V操作它体现了同步和互斥资源的分配机制。信号量的作用主要可以总结为如下:
image
信号量是system -v中重要的IPC,信号量的使用例程为:
image
首先是总分总结构,即初始化、P_V函数操作、释放资源。其中初始化是利用uion semun结构体,是一个专门就行信号量操作的结构体。具体可以看上图,或者在内核找。在进行P_V操作时,一般是先进行V操作再进行P操作,V操作。因为当资源不够用即等于0的时候,V可以让进程进入休眠状态。
代码示例:
以买卖车为例子,车子和车位是一个互斥的资源。

数据实时监控.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <unistd.h>

#define IPC_MASK      1
#define IPC_PATH      "./"
#define RESOURCE_KIND 2

union semun {
    int              val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                (Linux-specific) */
};


//创建信号量  初始化车:0和车位:3的值
int Demo_Init();

//实时显示资源数据 while(1)
int Real_Time_Show_Resource_Value();


int Demo_Free();



int Demo_Init()
{
    key_t key = ftok(IPC_PATH,IPC_MASK);
    if(key == -1)
    {
        perror("ftok ... ");
        return -1;
    }

    int sem_id = semget(key,RESOURCE_KIND,IPC_CREAT | 0666);
    if(sem_id == -1)
    {
        perror("semget ...");
        return -1;
    }

    printf("信号量ID是:%d\n",sem_id);


    //初始化车和车位的值
    union semun setvalue;
    setvalue.val = 0;
    if(semctl(sem_id,0,SETVAL,setvalue) == -1)  //先设置车的值
    {
        perror("semctl ...");
        return -1;
    }

    setvalue.val = 3;
    if(semctl(sem_id,1,SETVAL,setvalue) == -1)  //先设置车位的值
    {
        perror("semctl ...");
        return -1;
    }

    return sem_id;
}


int Real_Time_Show_Resource_Value(int sem_id)
{
    int car_num   = 0;
    int car_space = 0;
    int old_car_num   = -1;
    int old_car_space = -1;
    while(1)
    {
        if((car_num = semctl(sem_id,0,GETVAL)) == -1)
        {
            perror("获取车数据失败!\n");
            return -1;
        }

        if((car_space = semctl(sem_id,1,GETVAL)) == -1)
        {
            perror("获取车数据失败!\n");
            return -1;
        }

        if(old_car_num != car_num && old_car_space != car_space)
        {
            printf("车:%d-----车位:%d\n",car_num,car_space);
            old_car_num   = car_num;
            old_car_space = car_space;
        }
    }

    return 0;
}



int main()
{
    int sem_id = Demo_Init();
    if(sem_id == -1)
    {
        perror("例程初始化失败!\n");
        return -1;
    }

    Real_Time_Show_Resource_Value(sem_id);

    return 0;
}

买车.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <unistd.h>
 #include <stdlib.h>

//车下标  : 0
//位下标  : 1
int P_V_Ctrl(int sem_id,int sem_num,int ctl_num);
int P_V_Ctrl(int sem_id,int sem_num,int ctl_num)
{
    struct sembuf sb[1];

    sb[0].sem_num = sem_num;//车+1
    sb[0].sem_op  = ctl_num;
    sb->sem_flg   = 0;
    if(semop(sem_id,sb,1) == -1)
    {
        perror("semop ...");
        return -1;
    }

    return 0;
}


int main(int argc, char * argv[])
{
    if(argc != 2) return -1;

    while(1)
    {
        sleep(3);
        //车位v操作 - 1  (当资源值不够用的时候<等于0的时候>),让进程进入休眠态
        P_V_Ctrl(atoi(argv[1]),1,-1);
        //车p操作   + 1
        P_V_Ctrl(atoi(argv[1]),0,1);

    }

    return 0;
}

卖车.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <unistd.h>
 #include <stdlib.h>

//车下标  : 0
//位下标  : 1
int P_V_Ctrl(int sem_id,int sem_num,int ctl_num);
int P_V_Ctrl(int sem_id,int sem_num,int ctl_num)
{
    struct sembuf sb[1];

    sb[0].sem_num = sem_num;//车+1
    sb[0].sem_op  = ctl_num;
    sb->sem_flg   = 0;
    if(semop(sem_id,sb,1) == -1)
    {
        perror("semop ...");
        return -1;
    }

    return 0;
}


int main(int argc, char * argv[])
{
    if(argc != 2) return -1;

    while(1)
    {
        sleep(5);
        //车v操作   - 1
        P_V_Ctrl(atoi(argv[1]),0,-1);

        //车位p操作 + 1  (当资源值不够用的时候<等于0的时候>),让进程进入休眠态
        P_V_Ctrl(atoi(argv[1]),1,1);

    }

    return 0;
}
posted @ 2024-04-29 00:20  Jiangson  阅读(63)  评论(0编辑  收藏  举报