訊號量的作用
訊號量是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;
}