RTthread线程间通信(邮箱,消息队列,信号/软件中断)---03信号(软件中断)源码分析

本文主要是介绍RTthread线程间通信(邮箱,消息队列,信号/软件中断)---03信号(软件中断)源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

信号

实际使用看这一个

#if defined(RT_USING_SIGNALS)rt_sigset_t     sig_pending;                        /**< the pending signals 记录来了的信号 */rt_sigset_t     sig_mask;                           /**< the mask bits of signal 记录屏蔽的信号 */rt_sighandler_t *sig_vectors;                       /**< vectors of signal handler 记录处理函数 */void            *si_list;                           /**< the signal infor list 挂起的信号的信息链表 */
#endif

线程管理结构体

typedef void (*rt_sighandler_t)(int signo);

处理函数

struct siginfo_node
{siginfo_t si;struct rt_slist_node list;
};

这一个是用来记录挂起的信号的的信息

信号的处理除了会在这里面显示的位置进行, 还会在切换任务的时候处理

安装

rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
{rt_base_t level;rt_sighandler_t old = RT_NULL;rt_thread_t tid = rt_thread_self();//看一看是不是有效的值if (!sig_valid(signo)) return SIG_ERR;level = rt_hw_interrupt_disable();if (tid->sig_vectors == RT_NULL){//这一个线程之前没有安转过rt_thread_alloc_sig(tid);}if (tid->sig_vectors){old = tid->sig_vectors[signo];if (handler == SIG_IGN) tid->sig_vectors[signo] = RT_NULL;else if (handler == SIG_DFL) tid->sig_vectors[signo] = _signal_default_handler;else tid->sig_vectors[signo] = handler;}rt_hw_interrupt_enable(level);return old;
}
void rt_thread_alloc_sig(rt_thread_t tid)
{int index;rt_base_t level;rt_sighandler_t *vectors;//获取一个足以记录处理所有信号的函数的数组vectors = (rt_sighandler_t *)RT_KERNEL_MALLOC(sizeof(rt_sighandler_t) * RT_SIG_MAX);RT_ASSERT(vectors != RT_NULL);for (index = 0; index < RT_SIG_MAX; index ++){//初始化为默认的函数vectors[index] = _signal_default_handler;}//把这一个数组记录在线程里面level = rt_hw_interrupt_disable();tid->sig_vectors = vectors;rt_hw_interrupt_enable(level);
}
//默认的函数
static void _signal_default_handler(int signo)
{LOG_I("handled signo[%d] with default action.", signo);return ;
}

删除(屏蔽)

//实际上是更新一下线程里面的屏蔽值
void rt_signal_mask(int signo)
{rt_base_t level;rt_thread_t tid = rt_thread_self();level = rt_hw_interrupt_disable();tid->sig_mask &= ~sig_mask(signo);rt_hw_interrupt_enable(level);
}

解除

void rt_signal_unmask(int signo)
{rt_base_t level;rt_thread_t tid = rt_thread_self();level = rt_hw_interrupt_disable();//改一下标志tid->sig_mask |= sig_mask(signo);/* let thread handle pended signals */if (tid->sig_mask & tid->sig_pending){//有需要处理的标志rt_hw_interrupt_enable(level);_signal_deliver(tid);}else{rt_hw_interrupt_enable(level);}
}
//根据要处理的有信号的线程的状态进行分支处理
static void _signal_deliver(rt_thread_t tid)
{rt_ubase_t level;level = rt_hw_interrupt_disable();/* thread is not interested in pended signals */if (!(tid->sig_pending & tid->sig_mask)){//没有待处理的信号rt_hw_interrupt_enable(level);return;}if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND){//这一个任务挂起了(他在等待这一个信号)/* resume thread to handle signal */rt_thread_resume(tid);/* add signal state */tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);rt_hw_interrupt_enable(level);//恢复这一个任务/* re-schedule */rt_schedule();//这时候已经看完是不是这一个信号待处理了}else{//这一个任务运行或ready中if (tid == rt_thread_self()){//是当前的在运行的任务/* add signal state */tid->stat |= RT_THREAD_STAT_SIGNAL;rt_hw_interrupt_enable(level);/* do signal action in self thread context */if (rt_interrupt_get_nest() == 0){//直接开启这一个软件线程rt_thread_handle_sig(RT_TRUE);}}else if (!((tid->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL)){//不是在运行的任务, 这个时候会为这一个任务开启一个新的栈/* add signal state 更新一下标志 */tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);/* point to the signal handle entry */tid->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;tid->sig_ret = tid->sp;//记录一下之前的栈//这一个看线程处理篇//实际处理使用的之前栈下面的一部分tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL,(void *)((char *)tid->sig_ret - 32), RT_NULL);//设置一下这一个线程返回以后的处理rt_hw_interrupt_enable(level);LOG_D("signal stack pointer @ 0x%08x", tid->sp);/* re-schedule */rt_schedule();}else{rt_hw_interrupt_enable(level);}}
}
//这是一个软件中断的线程, 如果需要执行这一个的线程不在runing状态, 会使用一个新的栈空间执行这一个线程
void rt_thread_handle_sig(rt_bool_t clean_state)
{rt_base_t level;rt_thread_t tid = rt_thread_self();struct siginfo_node *si_node;level = rt_hw_interrupt_disable();if (tid->sig_pending & tid->sig_mask){/* if thread is not waiting for signal 等一个信号的话直接返回 */if (!(tid->stat & RT_THREAD_STAT_SIGNAL_WAIT)){//这个时候不是在等一个信号while (tid->sig_pending & tid->sig_mask){//依次处理信号int signo, error;rt_sighandler_t handler;//获取一个待处理的信号si_node = (struct siginfo_node *)tid->si_list;if (!si_node) break;/* remove this sig info node from list  */if (si_node->list.next == RT_NULL)tid->si_list = RT_NULL;//这是最后一个信号elsetid->si_list = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);//记录下一个信号signo   = si_node->si.si_signo;//获取标号handler = tid->sig_vectors[signo];//获取处理函数tid->sig_pending &= ~sig_mask(signo);//更新挂起的标志rt_hw_interrupt_enable(level);LOG_D("handle signal: %d, handler 0x%08x", signo, handler);if (handler) handler(signo);//执行处理函数level = rt_hw_interrupt_disable();error = -RT_EINTR;rt_mp_free(si_node); /* release this siginfo node 从内存池里面释放 *//* set errno in thread tcb */tid->error = error;}/* whether clean signal status *///这一个标志需要清除if (clean_state == RT_TRUE){tid->stat &= ~RT_THREAD_STAT_SIGNAL;}else{return;}}}rt_hw_interrupt_enable(level);
}
//非当前线程的时候线程返回时候的处理函数(软件中断)
static void _signal_entry(void *parameter)
{rt_thread_t tid = rt_thread_self();/* handle signal 处理一下信号 */rt_thread_handle_sig(RT_FALSE);/* return to thread 返回之前的在处理的任务状态 */tid->sp = tid->sig_ret;//改变栈tid->sig_ret = RT_NULL;LOG_D("switch back to: 0x%08x\n", tid->sp);tid->stat &= ~RT_THREAD_STAT_SIGNAL;//线程处理的里面分析了, 主要是切换一下运行位置以及栈rt_hw_context_switch_to((rt_ubase_t)&(tid->sp));
}

发送信号

#define sig_mask(sig_no)    (1u << sig_no)
int rt_thread_kill(rt_thread_t tid, int sig)
{siginfo_t si;rt_base_t level;struct siginfo_node *si_node;if (!sig_valid(sig)) return -RT_EINVAL;LOG_I("send signal: %d", sig);si.si_signo = sig;si.si_code  = SI_USER;si.si_value.sival_ptr = RT_NULL;level = rt_hw_interrupt_disable();if (tid->sig_pending & sig_mask(sig)){//这一个信号标志已经挂起了, 用这一个新的信息队列覆盖之前的信息/* whether already emits this signal? */struct rt_slist_node *node;struct siginfo_node  *entry;//获取挂起的信号的信息链表si_node = (struct siginfo_node *)tid->si_list;if (si_node)node = (struct rt_slist_node *)&si_node->list;elsenode = RT_NULL;/* update sig info */for (; (node) != RT_NULL; node = node->next){//遍历当前任务待处理的所有信号信息entry = rt_slist_entry(node, struct siginfo_node, list);if (entry->si.si_signo == sig){//用新的信息覆盖memcpy(&(entry->si), &si, sizeof(siginfo_t));rt_hw_interrupt_enable(level);return 0;}}}rt_hw_interrupt_enable(level);//这时候是标志没有挂起, 或者挂起了但是没有信息处理的链表项//获取一个内存块si_node = (struct siginfo_node *) rt_mp_alloc(_rt_siginfo_pool, 0);if (si_node){rt_slist_init(&(si_node->list));//更新一下信息memcpy(&(si_node->si), &si, sizeof(siginfo_t));level = rt_hw_interrupt_disable();//把这个挂入链表里面if (tid->si_list){struct siginfo_node *si_list;//这个里面前面有节点si_list = (struct siginfo_node *)tid->si_list;rt_slist_append(&(si_list->list), &(si_node->list));}else{//前面没有, 这就是第一个tid->si_list = si_node;}/* a new signal 记录一下标志 */tid->sig_pending |= sig_mask(sig);rt_hw_interrupt_enable(level);}else{LOG_E("The allocation of signal info node failed.");}/* deliver signal to this thread */_signal_deliver(tid);return RT_EOK;
}
int rt_system_signal_init(void)
{//这一个会设置rt_mp_alloc返回的大小_rt_siginfo_pool = rt_mp_create("signal", RT_SIG_INFO_MAX, sizeof(struct siginfo_node));if (_rt_siginfo_pool == RT_NULL){LOG_E("create memory pool for signal info failed.");RT_ASSERT(0);}return 0;
}

等待信号

这一个实际是一直在等待那一个信号, 那一个信号来之前一直挂起, 不会处理其他信号

int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
{int ret = RT_EOK;rt_base_t   level;rt_thread_t tid = rt_thread_self();struct siginfo_node *si_node = RT_NULL, *si_prev = RT_NULL;/* current context checking */RT_DEBUG_IN_THREAD_CONTEXT;/* parameters check */if (set == NULL || *set == 0 || si == NULL ){ret = -RT_EINVAL;goto __done_return;}/* clear siginfo to avoid unknown value 清空一下, 用于记录 */memset(si, 0x0, sizeof(rt_siginfo_t));level = rt_hw_interrupt_disable();/* already pending */if (tid->sig_pending & *set) goto __done;if (timeout == 0){ret = -RT_ETIMEOUT;goto __done_int;}/* suspend self thread 把自己挂起 */rt_thread_suspend(tid);/* set thread stat as waiting for signal */tid->stat |= RT_THREAD_STAT_SIGNAL_WAIT;/* start timeout timer */if (timeout != RT_WAITING_FOREVER){/* reset the timeout of thread timer and start it */rt_timer_control(&(tid->thread_timer),RT_TIMER_CTRL_SET_TIME,&timeout);rt_timer_start(&(tid->thread_timer));}rt_hw_interrupt_enable(level);/* do thread scheduling */rt_schedule();//返回, 可能超时或者有信号来了level = rt_hw_interrupt_disable();/* remove signal waiting flag */tid->stat &= ~RT_THREAD_STAT_SIGNAL_WAIT;/* check errno of thread */if (tid->error == -RT_ETIMEOUT){//是超时tid->error = RT_EOK;rt_hw_interrupt_enable(level);/* timer timeout */ret = -RT_ETIMEOUT;goto __done_return;}__done://是信号来了/* to get the first matched pending signals */si_node = (struct siginfo_node *)tid->si_list;while (si_node){//遍历一下所有的节点int signo;signo = si_node->si.si_signo;if (sig_mask(signo) & *set){//是在等的这一个*si  = si_node->si;LOG_D("sigwait: %d sig raised!", signo);if (si_prev) si_prev->list.next = si_node->list.next;//这一个信号的链表不在第一个else{//是第一个struct siginfo_node *node_next;if (si_node->list.next){//不是最后一个node_next = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);tid->si_list = node_next;}else{//唯一的信号tid->si_list = RT_NULL;}}/* clear pending */tid->sig_pending &= ~sig_mask(signo);//记录为这一个链表处理完了rt_mp_free(si_node);//释放一下break;}si_prev = si_node;if (si_node->list.next){//后面还有, 获取下一个si_node = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);}else{si_node = RT_NULL;}}//while__done_int:rt_hw_interrupt_enable(level);__done_return:return ret;
}

其他

#ifdef RT_USING_SIGNALS/* check stat of thread for signal */level = rt_hw_interrupt_disable();if (rt_current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING){extern void rt_thread_handle_sig(rt_bool_t clean_state);rt_current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;rt_hw_interrupt_enable(level);/* check signal status 处理信号 */rt_thread_handle_sig(RT_TRUE);}else{rt_hw_interrupt_enable(level);}
#endif

在任务切换的时候rt_schedule里面

这篇关于RTthread线程间通信(邮箱,消息队列,信号/软件中断)---03信号(软件中断)源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/684563

相关文章

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

软件设计师备考——计算机系统

学习内容源自「软件设计师」 上午题 #1 计算机系统_哔哩哔哩_bilibili 目录 1.1.1 计算机系统硬件基本组成 1.1.2 中央处理单元 1.CPU 的功能 1)运算器 2)控制器 RISC && CISC 流水线控制 存储器  Cache 中断 输入输出IO控制方式 程序查询方式 中断驱动方式 直接存储器方式(DMA)  ​编辑 总线 ​编辑

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者