system -v 信号量的使用
信号量的作用
信号量是system -v IPC中的一种,通过P、V操作它体现了同步和互斥资源的分配机制。信号量的作用主要可以总结为如下:
信号量是system -v中重要的IPC,信号量的使用例程为:
首先是总分总结构,即初始化、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;
}