信号量的本质是描述临界资源数目的信号量,是一种数据操作锁,对信号量进行的增减操作均为原子的;
为什莫使用信号量:为了防止多个进程同时访问一个共享资源而引起的一系列问题;让一个临界区同一时间只能有一个线程访问它;
工作原理:举例说明,若两个进程共享信号量sv,一旦其中一个进程执行P操作,使得sv减1,它将得到信号量,并且进入临界区,若另一进程此时再执行p操作将会被挂起,直到第一个进程离开临界区执行v操作;
//comm.h
#include<sys/ipc.h>
#include<stdio.h>
#include<sys/sem.h>
#include<sys/types.h>
#include <stdlib.h>
#define PATHNAME "."
#define PROJ_ID 0x6666
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int creatSem();
int initSem();
int getSem();
int destorySem();
int P();
int V();
//comm.c
#include"comm.h"
int commSem(int num,int flags)
{
int semid;
key_t _key=ftok(PATHNAME,PROJ_ID);
if(_key<0)
{
perror("ftok");
return -1;
}
if((semid=semget(_key,num,flags))<0)
{
perror("semget");
return -2;
}
return semid;
}
int creatSem(int num)
{
return commSem(num,IPC_CREAT|IPC_EXCL|0666);
}
int initSem(int semid,int semnum,int value)
{
union semun un;
un.val=value;
if(semctl(semid,semnum,SETVAL,un)<0)
{
perror("init _semctl");
return -3;
}
return 0;
}
int getSem(int num)
{
return commSem(num,IPC_CREAT);
}
int destorySem(int semid)
{
if(semctl(semid,0,IPC_RMID)<0)
{
perror("destory _semid");
return -3;
}
return 0;
}
int operatSem(int semid,int op)
{
struct sembuf buf;
buf.sem_num=0;
buf.sem_op=op;
buf.sem_flg=0;
int oop=semop(semid,&buf,1);
if(oop<0)
{
perror("semop");
return -4;
}
}
int P(int semid)
{
operatSem(semid,-1);
}
int V(int semid)
{
operatSem(semid,1);
}
//test.c
#include"comm.h"
int main()
{
int semid=creatSem(1);
initSem(semid,0,1);
pid_t id=fork();
if(id<0)
{
perror("fork()");
return 5;
}
else if(id==0)
{//child
int semid=getSem(1);
P(semid);
int count=0;
while(count++<5)
{
// sleep(1);
printf("A\n");
sleep(1);
printf("A\n");
}
V(semid);
// exit(0);
}
else
{//father
P(semid);
int count=0;
while(count++<5)
{
sleep(1);
printf("B\n");
sleep(1);
printf("B\n");
}
V(semid);
waitpid(id,NULL,0);
}
destorySem(semid);
return 0;
}