【Linux】消息队列和信号量
文章目录
- 消息队列
- 什么是消息队列
- 消息队列的相关函数
- 获取消息队列
- 控制消息队列
- 接收和发送消息(msgsnd,msgrcv)
- 信号量
- 什么是信号量
- 信号量的函数接口
- 获取信号量
- 控制信号量
- 查看信号量
- 总结
消息队列
什么是消息队列
消息队列是一种 进程间通信机制,允许不同进程通过 消息(数据块) 进行异步通信。消息队列中的消息按照先进先出(FIFO) 的方式存储,并由一个进程写入(发送),另一个进程读取(接收)。
DATA需要用结构体包装起来,不能裸发数据,因为需要标识生产者和消费者的属性。
消息队列的相关函数
获取消息队列
由于消息队列和共享内存还有信号量都是System V标准下的,所以函数接口都大差不差,key表示获取的消息队列的键值,也可以通过函数ftok
来获取。msgflg表示标志位,可以设置消息队列的权限和获取消息队列还是创建消息队列。
控制消息队列
msgctl可以通过cmd传递的宏来控制msgctl的行为。
比如我们传递IPC_RMID就是删除消息队列。
接收和发送消息(msgsnd,msgrcv)
首先从msgsnd讲起,msgsnd表示发送消息,第一个参数是msqid是msgget的返回值,第二个参数是一个结构体需要我们自己定义。
第一个用来标识传递的不同的消息,第二个参数表示用来存储实际的数据,这个数组一般被视为柔性数组,第三个参数,表示正文部分的大小,告诉另一端需要受到多大的消息,第四个参数用来控制消息发送的行为,默认情况下没有特殊需求一般默认设置为0.
接收消息唯一有区别的地方就是msgtyp,msgtyp表示接收消息的行为,当msgtyp==0时接收消息队列中的第一条消息,当msgtyp>0时表示接收类型等于msgtyp的消息,当msgtyp<0时表示接收消息类型小于msgtyp的最小类型消息。
信号量
什么是信号量
信号量是一种用于进程同步和互斥的机制,常用于控制多个进程或线程对共享资源的访问。它可以防止竞争条件(race condition)导致的数据不一致问题。
什么是同步?
多个执行流在访问临界资源的时候,具有一定的顺序性,这就叫做同步。
做个比喻,好比一个管道,当写端向管道发送消息的时候,读端是不能读取的,而只能阻塞等待写端写完之后读端才能读取消息,而在读端读取消息的时候,写端也不能在读端还没有读完就继续写,这就产生了顺序性,这就是同步机制
什么是互斥?
任何时刻只允许一个执行流访问资源这就叫做互斥
什么又叫做临界资源?
被保护起来的数据叫做临界资源。
临界区和非临界区的定义
临界区:在进程中涉及到互斥的资源的代码段叫做临界区
非临界区:和上面相反的,在进程中,没有涉及到互斥资源的代码段叫做非临界区
一般从临界区到非临界区,我们把他叫做加锁操作,从临界区到非临界区叫做解锁操作。
说完这些我们可以来说说信号量的概念了。
从定义上来看信号量很抽象,可以用图抽象出来:
当我们把资源当成一个整体的时候,由于互斥机制的影响,当A进程访问临界资源的时候,B进程数你不能访问的,只有当A进程访问完之后,B进程才能访问临界资源,我们学过共享内存我们知道,临界资源我么可以将其划分成若干个,假如我们开辟了4096个字节,我们可以将其划分为16*256个字节,也就是每块16字节一共有256块。
这样不同进程可以访问不同的进程块,这个共享资源容纳的最大进程数是划分的进程块的个数,我们可以将信号量理解为一个count也就是计数器,信号量是为了防止由于竞争导致数据不一致的情况,所以这个count会记录资源中的进程数,当一个新的进程数需要进入共享资源的时候,信号量需要做判断,判断一下资源中的进程数是否大于整个划分过的进程块,如果大于等于说明不能进入了,如果小于说明还可以进入,所以进程访问临界资源不是变成了去占空间,而是先预定一个信号量,当我们预定了一个信号量就算我们不访问这个数据块,这个位子也是我们的。
总结:信号量可以表示对资源预定的计数器。
信号量的函数接口
获取信号量
第一个是key,第二个是需要获取的信号量集中的信号量个数,第三个是标志位,用来控制信号量的权限和如何获取信号量。
控制信号量
第一个参数是获取信号量的返回值,第二个参数表示我们需要操作信号量集中的哪一个信号量,第三个是做什么操作。
查看信号量
ipcs -s
总结
消息队列和信号量是 Linux 进程间通信(IPC)中重要的同步与数据传输机制。消息队列提供了灵活的异步通信方式,适用于进程间的结构化数据交换,而信号量则用于进程同步与资源管理,避免竞态条件的发生。合理运用这两种机制,可以有效提升多进程程序的稳定性与效率。在实际开发中,根据应用场景选择合适的 IPC 方式,结合其他同步手段,如共享内存和管道,可进一步优化系统性能。