linux之信号量,PV操作

一、信号量是啥?PV操作是啥?

信号量用一句话来总结就是带有等待队列的计数器。信号量也就是对我们的临界资源进行计数。
就像我们去车站买票一样:
当取票机有票的时候,也就是资源计数 >0,那我们就可以直接取票,并且取票机的票数-1;
当取票机没有票的时候,也就是资源计数 <= 0,那我们就得等待取票机补上票,我们才能取票
当票机补一张票,资源计数也就+1,就是多了一份资源。

当信号量S > 0, S表示可用的临界资源数
当信号量S == 0,S表示目前无临界资源数,等待队列中无等待进程
当信号量S < 0, |S| 表示等待队列中的等待资源的进程个数

那么我们的PV操作又是啥?
P操作表示申请一份资源,申请了一份资源代表临界资源数就减少一份,信号量-1;也就是我们取了一张票
V操作表示释放一份资源,释放了一份资源代表临界资源数就增加一份,信号量+1;也就是补票机补了一张票
要注意:P 操作和 V 操作是搭配使用的,有 P 必有 V,有 V 必有 P

二、PV操作为啥是安全的?

为啥我们的PV操作没有加锁也不用考虑线程安全问题呢?
因为PV操作是原子性的。
P原语:

P(s)
{
   
	s.value = s.value--;
	if (s.value < 0)
	{
   
		该进程状态置为等待状状态
		将该进程的PCB插⼊相应的等待队列s.queue末尾
	}
}

V原语:

V(s)
{
   
	s.value = s.value++;
	if (s.value < =0)
	{
   
		唤醒相应等待队列s.queue中等待的⼀个进程
		改变其状态为就绪态
		并将其插⼊就绪队列
	}
}

三、啥是临界资源?啥是临界区?

临界资源(互斥资源):一次只允许一个进程使用的资源就是临界资源
临界区:在进程中涉及到临界资源的程序代码部分就是临界区
像我们的PV操作都是临界区,因为是对临界资源进行控制。

使用信号量就可以协调多个进程访问一份临界资源。保护临界资源的使用。任意时刻只能有一个线程进入临界区。


信号量其实就是由一个计数器和一个等待队列组成
信号量结构体:

struct semaphore
{
   
	int num;			//计数器
	pointer_PCB queue;	//等待队列
};

信号量集函数:
1、创建/访问一个信号量集

int semget(key_t key, int nsems, int semflg);
参数:
key:集合的名字
nsems:信号集中信号量的个数
semflg:由九个权限标志构成
返回值:成功返回该信号集的标识码;失败返回-1

2、控制信号量集

int semctl(int semid, int semnum, int cmd, …);
参数:
semid:由semget返回的信号集标识码
semnum:信号集中信号量的序号
cmd:将要采取的动作(有三个可取值)
最后⼀个参数根据命令不同⽽不同
返回值:成功返回0;失败返回-1

3、创建和访问一个信号量集

int semop(int semid, struct sembuf *sops, unsigned nsops);
参数:
semid:是该信号量的标识码,也就是semget函数的返回值
sops:是个指向⼀个结构数值的指针
nsops:信号量的个数
返回值:成功返回0;失败返回-1

sops指向的结构体

struct sembuf {
   
	short sem_num;	//信号量的标识码,也就是semget返回值
	short sem_op;	//PV操作
	short sem_flg;	//两个取值IPC_NOWAIT或SEM_UNDO
};

sem_op:
① 如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;
② 如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用权;
③ 如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。
sem_flg:
IPC_NOWAIT:对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值