信号量:
信号量是通过控制通信资源,负责数据的互斥与同步功能实现进程间通信;
信号量本身是一个描述临界资源中资源数目的计数器,防止两个执行流同时访问同一个临界资源,导致数据不一致问题;
当一个信号量的取值非0即1的时候,则称这个信号量是二元信号量;
信号量最常见的操作是P V操作:P操作:计数器减一,表明对应申请者申请到资源;
V操作:计数器加一,表明用户归还资源。
信号量值S:
S>0:表明有可用资源,并且S表示可用资源的数目;
S=0:表示没有可用资源,也没有进程等待;
S<0:|S|表示在等待队列中进程的个数。
信号量的创建:
int semget(key_t key,int nsems,int semflg)
参数:key:信号量标识;
nsems:信号量集中信号量的个数;
semflg:权限标准。
返回值:成功返回信号量集标识码,失败返回-1.
信号量集的控制
int semctl(int semid,int semnum;int cmd,...)
参数:semid:由semget返回的信号量集标识;
semnum:信号量集中信号量的序号
cmd:对信号量集将要采取的动作。SETVAL:设置信号量集中的信号量的计数值,(可以对信号进行初始化);
GETVAL:获取信号量集中的信号量的计数值;
IPC_STAT:把semid_ds结构中的数据设置为信号集的当前关联值;
IPC_SET:在进程有足够的权限的前提下,把信号量的当前关联值设置为semid_ds数据结构中给出的值。
IPC_RMID:删除信号集。…:根据操作的不同而不同,可以自定义
返回值:成功返回0,失败返回-1.
信号量集的创建和访问
int semop(int semid,struct sembuf* sops,unsigned nops)
参数:semid:信号量集的标识;
sops:指向一个信号量结构体指针
struct sembuf
{
short sem_num;//信号量编号
short sem_op;//信号量一次PV操作所加减的数值
short sem_flg;//可缺省,可取IPC_NOWAIT或SEM_UNDO
}nops:信号量的个数
返回值:成功返回0,失败返回-1.
信号量测试:
//comm.h
#ifndef _COMM_H_
#define _COMM_H_
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/sem.h>
#define PATHNAME "."
#define PROJ_ID 0x6666
union semun
{
int val;
struct semid_ds* buf;
unsigned short* array;
struct seminfo* _buf;
};
int creatSem(int nums);
int getSem(int nums);
int initSem(int semid,int num,int _val);
int destorySem(int semid);
int P(int semid,int num);
int V(int semid,int num);
#endif
//comm.c
#include"comm.h"
static int Sem(int nums,int flags)
{
key_t key=ftok(PATHNAME,PROJ_ID);
if(key<0){
perror("ftok");
exit(1);
}
int semid=semget(key,nums,flags);
if(semid<0){
perror("semget");
exit(1);
}
return semid;
}
int creatSem(int nums)
{
return Sem(nums,IPC_CREAT|IPC_EXCL|0666);
}
int getSem(int nums)
{
return Sem(nums,IPC_CREAT);
}
int initSem(int semid,int num,int _val)
{
union semun _un;
_un.val=_val;
if(semctl(semid,num,SETVAL,_un)<0){
perror("semctl");
exit(1);
}
return 0;
}
int destorySem(int semid)
{
if(semctl(semid,0,IPC_RMID)<0){
perror("semctl");
exit(1);
}
return 0;
}
static int PV(int semid,int num,int op)
{
struct sembuf _sf;
_sf.sem_num=num;
_sf.sem_op=op;
_sf.sem_flg=0;
if(semop(semid,&_sf,1)<0){
perror("semop");
exit(1);
}
return 0;
}
int P(int semid,int num)
{
return PV(semid,num,-1);
}
int V(int semid,int num)
{
return PV(semid,num,1);
}
//testSem.c
#include"comm.h"
int main()
{
int semid=creatSem(1);
initSem(semid,0,1);
key_t pid=fork();
if(pid==0){
while(1){
int _semid=getSem(0);
P(_semid,0);
printf("S");
sleep(1);
fflush(stdout);
printf("S ");
sleep(1);
fflush(stdout);
V(_semid,0);
}
}else if(pid>0){
while(1){
P(semid,0);
printf("L");
sleep(1);
fflush(stdout);
printf("L ");
sleep(1);
fflush(stdout);
V(semid,0);
}
}
destorySem(semid);
}