目的
1 了解除了全局变量之外更加安全的通信方式
正文
1 邮箱
特点:开销低,效率高,非堵塞,可用于中断
一个邮件大小是 4 个字节针对 32 bit处理系统,用于存储一个字节的大小
对于收 / 发线程而言,可以选择挂起等待或则直接返回,直到由邮箱唤醒
rt_mailbox 对象从 rt_ipc_object 中派生,由 IPC 容器所管理
邮箱控制块是操作系统用于管理邮箱的数据结构 rt_mailbox_t
struct rt_mailbox
{
struct rt_ipc_object parent; rt_uint32_t* msg_pool; /* 邮箱缓冲区的开始地址 */
rt_uint16_t size; /* 邮箱缓冲区的大小 */
rt_uint16_t entry; /* 邮箱中邮件的数目 */
rt_uint16_t in_offset, out_offset; /* 邮箱缓冲的进出指针 */
rt_list_t suspend_sender_thread; /* 发送线程的挂起等待队列 */
};
typedef struct rt_mailbox* rt_mailbox_t;
结构部分依旧
控制方式与之前一样
创建/初始化 rt_mb_create/init()
获取 rt_mb_send/send_wait()
释放 rt_mb_recv()
删除/脱离 rt_mb_delete/detach()
特别说明: 邮件进入方式
RT_IPC_FLAG_FIFO 先入先出
RT_IPC_FLAG_PRIO 优先级模式
举例:
就像电子邮箱,理论上应该只有一个拥有者(读取权限),其它线程只能够向目标邮箱发送数据,仅此而已
2 消息队列
特点:邮箱的拓展可以接收串口不定长数据,能够用于中断;
异步,FIFO 原则
控制块 rt_mq_t / rt_messagequeue
struct rt_messagequeue
{
struct rt_ipc_object parent; void* msg_pool; /* 指向存放消息的缓冲区的指针 */
rt_uint16_t msg_size; /* 每个消息的长度 */
rt_uint16_t max_msgs; /* 最大能够容纳的消息数 */
rt_uint16_t entry; /* 队列中已有的消息数 */
void* msg_queue_head; /* 消息链表头 */
void* msg_queue_tail; /* 消息链表尾 */
void* msg_queue_free; /* 空闲消息链表 */
rt_list_t suspend_sender_thread; /* 发送线程的挂起等待队列 */
};
typedef struct rt_messagequeue* rt_mq_t;
控制方式与之前一样
创建/初始化 rt_mq_create/init()
获取 rt_mq_send/urgent()/send_wait()
释放 rt_mq_recv()
删除/脱离 rt_mq_delete/detach()
特别说明: 邮件进入方式
RT_IPC_FLAG_FIFO 先入先出
RT_IPC_FLAG_PRIO 优先级模式
rt_mq_send / rt_mq_send_wait 两种
rt_mq_urgetn() 发送紧急消息是将消息直接插入消息队列的头部
应用:
消息队列可以应用于发送不定长消息的场合,包括线程与线程间的消息交换,以及中断服务例程中给线程发送消息(中断服务例程不能接收消息)
3 信号
特点:采用 linux 消息机制使用异步,POSIX 标准定义 sigset_t 信号集 (RT-Thread 中是 unsigned long)
应用程序可用的 SIGUSR1(10) 和 SIGUSR2(12)
本质:软中断,这就意味着信号被接收到并处理的时间是无法确定的,线程之间可以互相通过调用 rt_thread_kill() 发送软中断信号
处理方法:
1 中断:就是指定处理函数
2 忽略信号
3 保留信号系统的默认值
控制方式与之前一样
安装 rt_signal_install()
堵塞/接触堵塞 rt_signal_mask() / unmask()
发送 rt_thread_kill()
等待 rt_signal_wait()
rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t[] handler);
参数 | 描述 |
---|---|
signo | 信号值(只有 SIGUSR1 和 SIGUSR2 是开放给用户使用的) |
handler | 设置对信号值的处理方式 |
1 安装信号,就是建立线程和某一信号的映射关系
1)类似中断的处理方式,参数指向当信号发生时用户自定义的处理函数,由该函数来处理。
2)参数设为 SIG_IGN,忽略某个信号,对该信号不做任何处理,就像未发生过一样。
3)参数设为 SIG_DFL,系统会调用默认的处理函数_signal_default_handler()。
2 判断什么信号要被传递
void rt_signal_mask(int signo);
//被屏蔽的信号就不会传递给安装此信号的线程,不会引发中断
void rt_signal_unmask(int signo);
//接触屏蔽的信号
3 通知信号 / 等待消息
int rt_thread_kill(rt_thread_t tid, int sig);
int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t[] *si, rt_int32_t timeout);