简述信号量的创建、初始化、定义原子操作结构体、pv使用。
1.信号量创建
类似于共享内存的创建方式
int semid = semget(key,size,flag)
例如: int semid = semget(1000,1,IPC_CREAT|0600);
2.信号量的初始化
类似于解锁操作,先把锁释放
int ret = semctl(semid,0,SETVAL,1);
3.原子操作结构体
struct sembuf sopp,sopv;
memset(&sopp,0,sizeof(sopp));
memset(&sopv,0,sizeof(sopv));
//P -1操作结构体
sopp.sem_num=0;
sopp.sem_op=-1;
sopp.sem_flg=SEM_UNDO;
//V +1操作结构体
sopv.sem_num=0;
sopv.sem_op=1;
sopv.sem_flg=SEM_UNDO;
4.实例:
fork创建父子进程,分别计算加法,模拟并发操作,在使用信号量的情形下结果符合预期。如果不加入信号量,那么就没有原子操作结果不会符合预期
#include "func.h"
#define N 1
int main(int argc,char* argv[])
{
int sem;
sem=semget(IPC_PRIVATE,1,IPC_CREAT|0600);
int ret=semctl(sem,0,SETVAL,1);
int shmid;
shmid=shmget(1000,4096,IPC_CREAT|0600);
int* p;
p=(int*)shmat(shmid,NULL,0);
*p=0;
int i;
struct sembuf sopp,sopv;
memset(&sopp,0,sizeof(sopp));
memset(&sopv,0,sizeof(sopv));
sopp.sem_num=0;
sopp.sem_op=-1;
sopp.sem_flg=SEM_UNDO;
sopv.sem_num=0;
sopv.sem_op=1;
sopv.sem_flg=SEM_UNDO;
if(!fork())
{
for(i=0;i<N;i++)
{
//通知信号量执行sopp结构体定义的操作,p -1操作,singal变为0
semop(sem,&sopp,1);
int singal=semctl(sem,0,GETVAL);
printf("c: p=%d v=%d singal=%d\n",sopp.sem_op,sopv.sem_op,singal);
*p=*p+1;
//通知信号量执行sopv结构体 , v +1 ,singa变为1
semop(sem,&sopv,1);
singal=semctl(sem,0,GETVAL);
printf("c: p=%d v=%d singal=%d\n",sopp.sem_op,sopv.sem_op,singal);
}
exit(0);
}else{
for(i=0;i<N;i++)
{
semop(sem,&sopp,1);
*p=*p+1;
semop(sem,&sopv,1);
}
wait(NULL);
printf("the value %d\n",*p);
return 0;
}
}