由通讯提出的问题编程
在裸机编程的过程当中,咱们常常会遇到函数须要另外一些函数的数据信息,也就是通讯,这时咱们会怎么作呢?进行裸机开发的同窗确定都会说:使用全局变量,经过指针实现之类。使用全局变量快捷且高效。 服务器
可是在RTOS系统中,这会遇到一些问题:怎样防止许多线程同时进行对这个变量的访问?怎样观测通讯是否已经发生,从而进行通讯以后的工做?(例如:进行优先级转换,或者进行数据的处理)若是有个线程比较磨蹭,通讯迟迟不发生,CPU岂不是要尴尬地等待很久。。多线程
对于这些问题,操做系统给出了本身的通讯方法与函数供使用者调用,固然,也最好使用操做系统的通讯机制。函数
咱们打开RTT 的IDE,而后打开内核的Setting,会看到RTT的一些设定:学习
能够看到,线程间通讯一栏,这就是RTT给开发者提供的通讯机制,在实际开发中,这些机制能够知足绝大部分需求。RTT系统默认打开了信号量,互斥量,事件集,邮箱,消息队列五种机制。网站
信号量:spa
二值信号量:操作系统
在咱们的裸机开发过程当中,常常会使用一个变量:Flag,大多数时候,这个叫作Flag的变量会在0和1之间反复横跳,用于标记某一件事情是否发生,并常常被用于中断。这个Flag就是一个信号量,实际上,它是咱们最常使用的通讯方式之一。线程
在RTT系统中,信号量会被获取或者释放(由获取/释放函数实现),当它被获取时,就为0,当它被释放,就为1。这样的信号量被称为二值信号量。指针
举一个例子(伪代码):
static void xxx1() { while(1) { /*一个传感器采集一个特别复杂的数据,须要3S,不须要CPU参与*/ xxx } } static void xxx2() { while(1) { /*将这个数据交给CPU进行分析,数据无效就舍弃*/ xxx
rt_thread_mdelay(xx) } }
在这个例子中,有两个线程,线程2中,CPU一直在等待数据,但数据却老是无效的(由于传感器还没采集到数据),这让CPU一直在进行数据验证,虽然CPU中间进行了一些延时,但仍然在无效数据上浪费了时间,这时,就须要信号量出马了
改良后数据以下(伪代码):
rt_sem_create(xxx); //信号量建立函数,参数中默认为1,表示是释放的,具体参数不赘述 static void xxx1() { while(1) { rt_sem_take(xxx) //获取信号量,这时信号量被置0 /*一个传感器采集一个特别复杂的数据,须要3S,不须要CPU参与*/ xxx rt_sem_release(xxx) //释放信号量,这时信号量被置1 } } static void xxx2() { while(1) { rt_sem_take(xxx) //获取信号量,当信号量已经被其余线程获取,就进入阻塞态等待,等待时间自定,这里不赘述 /*将这个数据交给CPU进行分析,数据无效就舍弃*/ xxx rt_sem_release(xxx) //释放信号量 rt_thread_mdelay(xx) } }
这里咱们看到,当传感器开始工做时,信号量已经被获取了,这时进入线程二想要处理数据,就会进入阻塞态,让出CPU去作其余的事情,当传感器得到数据后,就会释放信号量,这时,线程二就从阻塞态中退出,从而去处理有效的数据。(注意:获取信号量进行相关操做后应马上释放信号量,若是不进行释放,可能会致使其余线程没法运行)
通过这一番操做,无效数据不会被一次又一次的处理了,而是在传感器得到数据后,CPU直接去处理有效的数据,节省了许多无效操做。
计数型信号量:
计数型信号量与二值信号量相似,只不过范围从二值的[0,1],变为了[0,65535],这样它就能够被多个线程获取,获取的最大数目由使用者自定,使用的系统函数与二值信号量相同。
计数信号量常常被用于控制一些公共资源的访问数量,例如一个资源最多能够被x个线程同时访问,多于x时效率大大降低或者会出现错误(有点像网站服务器限制访客数量)。
互斥量:
互斥量是一种特殊的二值信号量,其与二值信号量的最大区别为引入了优先级继承机制。
优先级继承机制:若是一个高优先级的线程去申请一个已经被低优先级得到的互斥量,高优先级会进入到阻塞态,而持有这个互斥量的线程地位会瞬间与高优先级同样,取得高优先级相同的优先等级,这就是“优先级继承”
这样有什么好处呢?这里依然是一个栗子。
static void HIGH() { xxx } static void MIDDLE() { xxx } static void LOW() { xxx }
假设有三个线程,优先度分别为高,中,低。理所固然,开发者但愿高优先级的越快处理越好,低优先级的则不是很紧要。
这时,若是有个二值信号量,被低优先级(LOW)获取。而后高优先级(HIGH)的也想要获取这个信号量,因而进入了阻塞等待。
可是当LOW准备用CPU运行时,MIDDLE却发话了:我有更紧要的任务,你让开。LOW小弟就被挤到了一边,毕竟它是优先级最低的。
这就产生了一个问题,开发者最但愿运行的HIGH在等待信号量,而MIDDLE却在运行(假设MIDDLE和HIGH无关联,此时HIGH就要等待MIDDLE运行+LOW运行,而不是只等待LOW运行),LOW在等待CPU让出。这显然违背了开发者“高优先级越快越好”的想法。
怎样解决这个问题,这时就引入互斥量来解决这个问题,当HIGH进入阻塞态以后,LOW瞬间“继承”了HIGH的优先级,LOW小弟也暂时体验了当大哥的感受,并把MIDDLE挤到一边,快速的处理起了数据,并在处理完后变回原来的优先级,将互斥量释放,HIGH得以继续运行。这样,经过暂时提升LOW的优先级,开发者所但愿的HIGH处理越快越好的想法得以实现。
(暂时记录信号量和互斥量的学习笔记,文中可能有些理解和想法有略微的误差,请注意=))