欢迎光临散文网 会员登陆 & 注册

利用信号量实现简单进程内消息队列

2021-10-28 17:00 作者:奥大梨呀  | 我要投稿

        前几天学习了线程和线程的通信方式,线程的通信方式与进程有部分类似,比如自旋锁、信号量等。但进程间还有一个消息队列的通信方式,用于进程内线程的一些轻量级应用场合显得过于大材小用。如果要做到进程内线程之间类似于消息队列的数据传输通信,尽管可以使用条件变量加上全局数据的方式,但这样未免线程间的耦合性太强了。因此打算以信号量为基础在应用层实现一个简单的消息队列机制。

        引入信号量的目的是为了令等待(接收)消息的线程在队列中没有消息的情况下陷入阻塞,或者在队列中存在多个消息时,可以多次获取到信号量,这里的信号量是计数型信号量。

有了信号量为基础,就可以得出编程思路:

①消息队列结构:包含一个信号量、一个自旋锁和一个先进先出的队列结构。

②队列结构:一个单向链表,包含一个头节点指针、下一个节点指针、一个数据指针、一个数据长度变量。

③消息队列的初始化:内存空间清0,即将所有指针设为NULL。

④发送消息:申请一个消息节点的内存空间,再向队列里添加该消息节点,然后释放1个信号量。

⑤接受消息:阻塞请求信号量,获取到信号量后,从队列里取出第一个消息节点,拷贝数据后,释放该节点的内存空间。

⑥消息队列的销毁:循环移出队列里剩余的消息并释放内存空间,最后销毁信号量和自旋锁。

下面就开始逐一实现:

·首先是队列结构类型的声明:

消息队列结构类型

·消息队列的初始化

消息队列的初始化

        初始化做的事情比较少,只需要进行空指针判断、消息队列结构清0和信号量的初始化。

·向队列添加消息节点

向队列添加节点

         在消息队列结构初始化好后,其中的队列是一个空链表。因此每次在添加节点时都需要判断当前队列是否为空,若为空则新节点插入表头并设置新的表头,若不为空则插入表尾。

           这是一个文件内部调用的函数,因此定义成静态static。

·从队列移出一个节点

从队列移出一个节点

        根据先进先出的原则,从队列中移除一个节点应从链表的第一个节点开始移除,所谓移除节点仅仅是将其从链表中移出,其所占的内存空间还不能释放,需要等该节点的消息数据被读取后才可以释放。因此通过指向指针的指针将该节点返回以便处理。

        这是也一个文件内部调用的函数。

·发送消息

发送消息

        发送消息函数有3个形式参数,第一个msg就是指向需要请求消息的消息队列,第二个参数buf是指向发送线程要发送的数据缓冲区,第三个参数size指示数据的大小,单位字节。

        发送消息首先要申请一个队列节点占用的内存空间,然后将该节点添加进队列中,对该节点添加消息数据和消息大小。最后再释放1个信号量即可。

·接收(等待)消息

接收消息

        接收消息函数有4个形式参数,第一个msg与发送消息相同,也是指向需要请求消息的消息队列;第二个参数buf是指向接收线程要存放数据的缓冲区;第三个参数buf_size指示接收线程数据缓冲区的大小,防止消息长度超过该数据缓冲区而导致的非法访问;第四个参数msg_size指向保存消息长度的变量,需要由接收线程提供。

        发送数据首先要对参数有效性进行判断,之后请求一个信号量,若此时信号量为0,则表示队列中没有消息,此时线程应陷入阻塞。若有一个线程向此消息队列中添加了一个消息,

则接收数据的线程因为请求到了信号量而被唤醒,之后应从队列中移出一个消息节点,并将节点的数据拷贝到接收线程,最后释放该节点的内存空间。

注:在向队列添加和移除节点时,应该有保护机制,这里使用的是自旋锁spinlock,以确保多个线程并发访问队列时不存在数据一致性问题。

·测试:        

        最后编写一个测试程序测试该消息队列是否可以使用,判断是否可以使用的标准有:

①是否可以在2个线程之间实现1对1单向通信(1收1发)。

②是否可以在多个线程之间实现1对多单向通信(1收多发)。

测试程序:

消息队列测试程序

        测试程序中创建了3个入口地址相同的线程,通过传入线程的参数来令他们每隔1秒向主线程发送不同的消息,而主线程一直循环等待消息并打印。执行结果如下:

测试程序执行结果

        可以看出这个消息队列在“3个线程发送,1个线程接收”的情况下是没有问题的。可以用作一些简单应用场合。

最后附上源码文件:

链接:https://pan.baidu.com/s/1YDZLqxm3elmG2gf3sNkNqQ 

提取码:1234


利用信号量实现简单进程内消息队列的评论 (共 条)

分享到微博请遵守国家法律