Linux POSIX信号量、实现生产者消费者模型

2023-05-16

posix与system v的区别

之前我们在进程间通信中学到过system v版本的信号量,它和posix的区别在于:
system v版本的用于进程之间,posix版本的用于线程之间。他们的主要区别在于信号量和共享内存。

信号量的区别:
1.system v版本的信号量一般是随内核的,无论有无竞争都要执行系统调用,所以性能上比较差。它的接口是semget,semctl,semop。

2.posix版本的信号量同时支持无命名的信号量和有命名的信号量。它在无竞争的时候是不陷入内核的。所以效率更高。
(1)无命名的信号量一般用于线程同步,它的生命周期是随进程的,它的主要接口有 sem_init,sem_destory,sem_wait,sem_post。
(2)有命名的信号量一般用于进程同步,一般有一个文件关联他们,有命名的信号量是随内核的,它的主要接口有 sem_open,sem_close,sem_unlink。

上述内容参考于:https://blog.csdn.net/mxrrr_sunshine/article/details/80037212

下面我们来学习posix的信号量:

posix信号量

1.功能:主要完成线程或者进程之间的同步、互斥。
2.本质是一个资源计数器、等待队列以及为用户提供的唤醒和阻塞接口。它比条件变量多了一个资源计数器。计数器就是对资源的数量进行一个计数。通过自身的计数器的计数,来判断是否可以对资源进行访问。若不能访问则当前执行流陷入阻塞。
3.使用
在程序初始化的时候,会对posix信号量进行初始化,此时资源计数器中的值为临界资源的数量。当有执行流想访问临界资源时,先调用信号量等待接口,通过计数器判断计数是否大于0,若大于0,则对计数器-1,访问资源即可。若小于0,也对计数器-1,但是执行流进入阻塞。
4.应用接口
定义
sem_t sem;
初始化
sem_init(sem_t* sem,int pshared,in value);
sem:传入信号量的地址
pshared:表示信号量适用于线程还是进程。
0:代表线程
1:代表进程
value:实际资源的数量,初始化计数器。
等待:调用等待接口,直接先将资源计数器的值-1。
sem_wait(sem_t* sem);
功能:没有资源时,阻塞等待。
sem_trywait(sem_t* sem);
功能:没有资源时,直接返回报错,不阻塞。
sem_timedwait(sem_t* sem);
功能:超时时等待,当超过超时时间,直接返回报错。

这里大家也许会有疑问,为什么posix信号量等待接口,不用互斥锁变量?
因为在posix信号量中互斥是通过计数器来实现的,这个后面用posix信号量实现生产者消费者模型代码中会说到。

唤醒
功能:
1.同步方面:
代表生产者已经生产了资源,唤醒消费者,对资源计数器+1。
2.互斥方面(资源数量为1):
说明此时一个执行流已经访问完资源了,归还资源,对计数器+1。
int sem_post(sem_t* sem);

销毁
int sem_destroy(sem_t* sem);

我们来看看信号量如何实现互斥?
初始化计数器的时候,将资源数量设置为1,这样就可以满足,只能有一个执行流访问临界资源。

那么当一个线程生产了一个资源后需不需要唤醒一个线程来消费?或者说什么情况下唤醒?
当一个线程产生一个资源时候,计数器+1,先判断此时计数器是否小于0,若小于0则唤醒一个线程来消费。

用posix信号量实现生产者消费者模型

实现此模型,是要用一个线程安全的循环队列,此处我们采用的是数组的方式,实现一个环形队列,主要的达到先进先出的目的即可。
在这里插入图片描述
实现代码:https://github.com/CR7MZ/Linux/blob/master/work/sem.cpp

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux POSIX信号量、实现生产者消费者模型 的相关文章

随机推荐