当前位置:网站首页>RTT学习笔记10- 设备IPC 完成量-ringbufffer-workwueue
RTT学习笔记10- 设备IPC 完成量-ringbufffer-workwueue
2022-08-07 14:55:00 【Car12】
1.completion完成量
轻量级的IPC通信机制
1.1完成量和信号量对比
- 信号量是一种非常灵活的同步方式,可以运用在多种场合中。形成锁、同步、资源计数等关系,也能方便的用于线程与线程、中断与线程间的同步中。
- 完成量,是一种更加轻型的线程间同步的一种实现,可以理解为轻量级的二值信号,可以用于线程和线程间同步,也可以用于线程和中断之间的同步。
- 完成量不支持在某个线程中调用 rt_completion_wait,还未唤醒退出时,在另一个线程中调用该函数。–只可以多个线程调用done,但是不可以多个线程调用wait
- 当完成量应用于线程和中断之间的同步时,中断函数中只能调用 rt_completion_done 接口,而不能调用 rt_completion_wait 接口,因为 wait 接口是阻塞型接口,不可以在中断函数中调用
1.2 完成量结构
struct rt_completion
{
rt_uint32_t flag;
/* suspended list */
rt_list_t suspended_list;
};
flag可选参数:
#define RT_COMPLETED 1
#define RT_UNCOMPLETED 0
1.3 函数接口
1.3.1 初始化完成量
只支持静态对象初始化,不支持动态生成对象
void rt_completion_init(struct rt_completion *completion)
1.3.2 等待完成
rt_err_t rt_completion_wait(struct rt_completion *completion,
rt_int32_t timeout)
//rt_err_t 执行正确时,返回 RT_EOK ,执行错误时,返回错误码
函数执行流程:
1.3.3 初始化完成量
void rt_completion_done(struct rt_completion *completion)
1.4 示例代码
/* * 程序清单:完成量例程 * * 程序会初始化 2 个线程及初始化一个完成量对象 * 一个线程等待另一个线程发送完成量 */
#include <rtthread.h>
#include <rtdevice.h>
#define THREAD_PRIORITY 9
#define THREAD_TIMESLICE 5
/* 完成量控制块 */
static struct rt_completion completion;
ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;
/* 线程 1 入口函数 */
static void thread1_completion_wait(void *param)
{
/* 等待完成 */
rt_kprintf("thread1: completion is waitting\n");
rt_completion_wait(&completion, RT_WAITING_FOREVER);
rt_kprintf("thread1: completion waitting done\n");
rt_kprintf("thread1 leave.\n");
}
ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 线程 2 入口 */
static void thread2_completion_done(void *param)
{
rt_kprintf("thread2: completion done\n");
rt_completion_done(&completion);
rt_kprintf("thread2 leave.\n");
}
int completion_sample(void)
{
/* 初始化完成量对象 */
rt_completion_init(&completion);
rt_thread_init(&thread1,
"thread1",
thread1_completion_wait,
RT_NULL,
&thread1_stack[0],
sizeof(thread1_stack),
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
rt_thread_startup(&thread1);
rt_thread_init(&thread2,
"thread2",
thread2_completion_done,
RT_NULL,
&thread2_stack[0],
sizeof(thread2_stack),
THREAD_PRIORITY, THREAD_TIMESLICE);
rt_thread_startup(&thread2);
return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(completion_sample, completion sample);
2.ringbufffer 环形缓冲区
2.1.基本知识
导入头文件
#include<ipc/ringbuffer.h>
2.2 数据结构
struct rt_ringbuffer
{
rt_uint8_t *buffer_ptr;
rt_uint16_t read_mirror : 1;
rt_uint16_t read_index : 15;
rt_uint16_t write_mirror : 1;
rt_uint16_t write_index : 15;
rt_int16_t buffer_size;
};
- buffer_ptr 是指向缓冲区的指针,
- buffer_size 是缓冲区的大小,
- read_index 是读索引,
- write_index 是写索引,
- read_mirror 和 write_mirror 可以理解为一种镜像值,每次向缓冲区写入数据,碰到缓冲区末尾时,切换到另一个镜像的缓冲区头部写入剩余数据。这种镜像操作可用于判断缓冲区内数据是满还是空
2.3.函数接口
2.3.1创建和销毁 ringbuffer
struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t length);
void rt_ringbuffer_destroy(struct rt_ringbuffer *rb);
2.3.2初始化和复位 ringbuffer
void rt_ringbuffer_init(struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int16_t size);
void rt_ringbuffer_reset(struct rt_ringbuffer *rb);
2.3.3写入数据
rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch);
2.3.4ringbuffer 满了之后也能够成功写入一个字节或数据块
执行的是数据的覆盖
rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t ch);
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length);
2.3.5读取数据
2.3.5.1读数据并取出数据
rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch);
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb, rt_uint8_t *ptr, rt_uint16_t length);
2.3.5.2读数据但不取出数据
rt_size_t rt_ringbuffer_peak(struct rt_ringbuffer *rb, rt_uint8_t**ptr);
该接口建议只用来访问一个字节,否则极有可能造成数组越界
2.3.6获取 ringbuffer 内存储的数据大小
rt_inline rt_uint16_t rt_ringbuffer_get_size(struct rt_ringbuffer *rb);
3.workwueue 工作队列
3.1 介绍
- 工作队列(workqueue)是一种转移任务执行环境的工具 (中断处理函数里做一些紧急地操作,然后将另外一些不那么紧急,而且需要一定时间的任务封装成函数交给工作队列执行,此时该函数的执行环境就从 中断环境 变成了 线程环境,)
- RT-Thread 内有 workqueue 组件,导入头文件 #include <ipc/workqueue.h>
- 工作项里最好不要有会导致线程阻塞的代码,否则会影响后续工作项的执行
- 可以使用系统工作队列,我们也可以创建属于自己的工作队列
消息队列结构介绍
struct rt_workqueue
{
rt_list_t work_list;
rt_list_t delayed_list;
struct rt_work *work_current; /* current work */
struct rt_semaphore sem;
rt_thread_t work_thread;
};
工作项
struct rt_work
{
rt_list_t list;
void (*work_func)(struct rt_work *work, void *work_data);
void *work_data;
rt_uint16_t flags;
rt_uint16_t type;
struct rt_timer timer;
struct rt_workqueue *workqueue;
};
list 用于将该工作项挂载到工作链表上去,
work_func 就是该工作项绑定的函数指针
work_data 是用户自定义数据,当工作项被执行时就会调用该函数。
3.2 函数接口-使用系统工作队列
3.2.1初始化工作项
rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_work *work, void *work_data), void *work_data);
3.2.2提交一个工作项
rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time);

3.2.3取消之前提交过的工作项
rt_err_t rt_work_cancel(struct rt_work *work);

3.3 使用自己创建的消息队列
3.3.1创建工作队列
struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority);
3.3.2销毁工作队列
rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue);
3.3.3延时提交提交工作项
rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time);

3.3.4不允许 工作项延时提交
rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work);
3.3.5紧急提交
rt_err_t rt_workqueue_critical_work(struct rt_workqueue *queue, struct rt_work *work);
3.3.6取消提交
rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work);
3.3.7同步提交
等待任务执行结束才返回
rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_work *work);
3.4示例代码
#include <rtthread.h>
#include <ipc/workqueue.h>
struct rt_work work1;
int work1_data = 1;
struct rt_work work2;
int work2_data = 2;
void work_func(struct rt_work *work, void *work_data)
{
int data = *(int *)work_data;
rt_kprintf("recv work data: %d\n", data);
}
int workqueue_example(void)
{
printf("hello rt-thread!\n");
struct rt_workqueue *wq = rt_workqueue_create("my_wq", 2048, 20);
RT_ASSERT(wq);
rt_work_init(&work1, work_func, &work1_data);
rt_work_init(&work2, work_func, &work2_data);
rt_workqueue_submit_work(wq, &work1, 2);
rt_workqueue_submit_work(wq, &work2, 0);
return 0;
}
MSH_CMD_EXPORT(workqueue_example, workqueue example);
边栏推荐
- Acwing/3359. 更多奇怪的照片
- 线程的控制与同步
- (imdb数据集)电影评论分类实战:二分类问题
- LeetCode 热题 HOT 100(7.盛最多水的容器)
- 深度之眼(二十一)——概率论
- Summary of the open surface
- LeetCode Hot Questions HOT 100 (6. Regular Expression Matching)
- The ADC external RC circuit resistance and capacitance selection calculation method
- 66:第五章:开发admin管理服务:19:开发【查看用户详情,接口】;
- LeetCode Hot Question HOT 100 (7. The container that holds the most water)
猜你喜欢

Lianshengde W801 series 1-flash save data routine: save wifi distribution network information

俩日总结(【18】、【19】)

【数据库系统原理】第四章 高级数据库模型:弱实体集、E/R 联系到关系的转化、子类结构到关系的转化

深度之眼(二十一)——概率论

001_微服务框架学习分类总结

005_Ribbon负载均衡

亚马逊云科技 Build On 参与心得

哈希表 | 三数之和、四数之和 | 用`双指针法`最合适 | leecode刷题笔记

触摸屏如何利用无线PPI通信模块远程采集PLC数据?

基于RK3566中RTL8201F网口百兆调试笔记
随机推荐
我住得比较远,有好的开户途径么?手机开户股票开户安全吗?
小技巧——postman配置token
C专家编程 第8章 为什么程序员无法分清万圣节和圣诞节 8.5 原型在什么地方会失败
哈希表 | 1. 两数之和、454. 四数相加 | 用`字典key-value`最合适 | leecode刷题笔记
WeChat automatic card issuance robot description
【PTA】L2-002 链表去重(25分)
03 "commonly used types (below)"
mysql query the last data in the table
处理乱码的问题oracle字符集WE8MSWIN1252和WE8ISO8859P1
微信小程序——swiper内容水平垂直居中
【通信原理】第三章 -- 随机过程[补充]
The ADC external RC circuit resistance and capacitance selection calculation method
【高等数学】高数整理:常见等价无穷小、导数和微分、微分方程
IPV6的内容
win10 uwp 圆角按钮
05 【接口 interface VS type】
X64 assembly language instruction encoding
苹果,设计思维的“布道者”
牛客面试高频榜单(第二组)难度:简单&中等
005_Ribbon负载均衡