您好, 登录| 注册|
论坛导航
您好, 登录| 注册|
子站:
论坛首页    单片机MCU/嵌入式
  •  发帖
  • 收藏

【RT-thread学习记】:线程间的同步:
阅读: 95 |  回复: 6 楼层直达

2018/12/04 10:25:15
1
s453208[版主]
电源币:810 | 积分:103 主题帖:43 | 回复帖:114
LV7
旅长

QQ截图20160321155901  玩大发了! 英飞凌最新无人机套件LARIX免费试用 招募中

QQ截图20160321155901  想学你就来!DSP学习板免费试用 限时申请


继续我们的学习之路,前面讲了线程相关的应用方面的一些概念,其实OS的核心就是依靠线程来实现的,但是线程只是os底层实现的基本单位,一个应用往往需要很多的线程协调工作,这里就涉及到多线程间通信的问题。在原有的裸机时代,是没有什么线程概念的,但是往往可以将线程类比函数的概念,实际上本质上并无太大差别,只是对于函数的控制往往都很弱,你只能控制它开始,然后等待它自行走完一个周期,然后才去干别的活,当你需要对函数进行控制时,你的第一考虑是中断,其实这部分所实现的功能就和os对线程的管理就很像了,但是你用中断以后,如果有其它函数需要抢占执行呢,这时候你会说,嵌套中断嘛,的确可以通过嵌套中断的方式来实现对于中断级的抢占,而且从这一方面来讲它和os就更像了,但是要注意一点问题,中断时舒服前台操作的,而函数才是后台的服务,那么问题来了,你能把所有的功能都放进前台实现吗?答案肯定是不能前台中断有几个条件决定了这样做不可行,其一中断入口的条件判断是特定的,比如定时中断,外部触发中断,串口中断,都是发生在特定条件下才能进入,其二中断的数量是有限的,你有100个函数功能要执行,但不一定有一百个中断给你用,其三,涉及到系统栈的问题了,中断抢占函数执行,中断抢占中断执行,这些临时场景的保存,只有一个地,那就是系统栈,默认大小是0x400,不论发生何种抢占问题都会消耗系统栈的开销,一旦发生中断嵌套或函数嵌套调用,那么多大的系统栈才够用呢,单片机本身RAM就金贵,栈定义大了,应用级就不够用,定义小了又容易发生中断溢出,os则从另一个角度尝试解决这个问题,依然会导致RAM开销比传统裸机的大,但相对于溢出问题得到了有效的控制,总体来讲还是一个不错的选择。扯了很多,好像又有点偏了,接下来还是进入正题讲下线程间同步的问题。

标签 STM32 MCU C语言

电源网-璐璐在2018-12-04打赏该贴 +10 电源币 打赏理由:

电源网-璐璐在2018-12-04打赏该贴 +10 电源币 打赏理由:

2018/12/04 10:45:43
2
s453208[版主]
电源币:810 | 积分:103 主题帖:43 | 回复帖:114
LV7
旅长
线程间为什么需要同步,这里以生产一台空调为例进行讲解,一台空调需要外壳,压缩机等核心零部件,冷媒铜管
冷媒,控制板,线束等一堆的东西,这些都可以交给各个线程去做,有人做外壳,有人做核心零部件,有人做控制板等等。
但是做好了这些零部件并不代表你就拥有了一台空调,你需要一个主线程把各个的零部件进行组装,然后测试合格,这
时候你才拥有了一台真正意义上的线程,但是组装的流程又是一个特定,比如你肯定不能先安装外壳,而是要先把核心部件
与冷媒铜管先焊接起来,然后绑定各种传感器,固定控制板,充入冷媒,拉入实验室进行性能测试,没问题后,安装外壳,包装出厂
这里问题就来了,当你要安装控制板的时候,发现某个线程没有送来咋整,没法子只能中断生产,等待它先送来以后,这就是线程同步了
只有它完成了它的使命,才能进行下一步,在这个过程中,各个线程之间可能都或多或少的存在一些同步问题,不一定是只有主线程和其它
线程之间,比如线程A借了线程B钱,结果到A要生产的时候B还没还钱,这时候A不得不放下生产任务,先去催债,要到钱才能继续开工成产,
大概就扯这么多吧,接下来讲讲线程间同步的方式,这里可就涉及到不同类型的场景应用不同的通信方式,最有效,系统开销最小的问题。
2018/12/04 11:13:11
3
s453208[版主]
电源币:810 | 积分:103 主题帖:43 | 回复帖:114
LV7
旅长
在继续详细介绍这个同步方式之前,先来看看实现同步的原理,其实类似裸机的全局变量传递,
但又有不同,虽然我是全局的,但并不代表所有人都可以访问,只有内部人员才能使用,
打个比方,裸机时代,造物主U创造了函数A,函数B,水缸,函数A负责往水缸中倒水,函数B往水缸
中取水,这时候造物主来兴致了,干脆再造一个函数C,这时候直接让函数C也往缸中取水,那么问题
来了,一时的兴致,可能不会考虑水缸的供水量问题,最终可能导致大家都吃不上水。
而在os来临之后,造物主U创造了函数A,函数B,函数C,水缸,另外创造了一个管理员os,os负责对
水缸管理,这时候函数ABC,必须去管理员那里注册,谁负责倒水谁可以取水,如果没注册,直接找
造物主都不好使,函数D是造物主的大表哥,觉着这里进要来这里吃水,结果管理员估算用水量后不让他吃
,造物主也只好请大表哥。。。,管理员会按照水缸的情况适当的开放或缩减水缸的使用者,以保证各个使用
者都可以满足自身需求,至于造物主大人只需在家睡觉就好。
2018/12/04 11:21:56
4
s453208[版主]
电源币:810 | 积分:103 主题帖:43 | 回复帖:114
LV7
旅长
接下来还是举个栗子,以一个事件信号(简体版)的实现机制来看下,其内部具体的实现细节。
//消息类型定义
enum
{
    MSG_NONE = 0,        //无消息
    MSG_TIMER_1MS,    //事件
    MSG_WIFIMODULE_LOOP, //事件
    MSG_WIFICONNECT_OK,  //事件
    MSG_CLOSED_CHAIR,    //事件
    MSG_WIFIRESET,       //事件
    MSG_COUNT            //事件查询机制使用
};
2018/12/04 11:23:34
5
s453208[版主]
电源币:810 | 积分:103 主题帖:43 | 回复帖:114
LV7
旅长

/*  消息机制
 * 消息采用32位缓冲存储,每次消息产生都按位配置。
 * 按位检测消息,同时复位此消息位。
 * 循环等待检测消息缓冲。
 *
 */

static   int g_signal = 0;

//判断消息
int judge_msg_signal(int i)
{
    if((g_signal >> i) & 0x01)      //检测到消息
    {
        g_signal &= ~(0x01<<i);     //修改消息位
        return i;
    }
    else
    {
        return 0;
    }
}

/*
*  设置事件
*/
void set_msg_signal(int msg)
{
    if(msg > MSG_COUNT)
      return;
   
    g_signal |= (0x01<<msg);
}

/*
*  事件接收机制,遍历整个事件,找到有效事件
*  通过return返回事件,每次只能处理一个事件
*/
int wait_msg_signal(void)
{
    int temp = 0, i;
   
    for(i = MSG_COUNT; i>0; i--)
    {
        if(judge_msg_signal(i) == i)
        {
            temp = i;
            return temp;
        }
    }
    return temp;
}

2018/12/04 11:29:48
6
s453208[版主]
电源币:810 | 积分:103 主题帖:43 | 回复帖:114
LV7
旅长
这个栗子相对简单一些,看看注释就明白啦,就不过多解释了,
接下来在末尾介绍一下,本篇的主角吧,同步方式的类型,
信号量:事件:邮箱:消息队列:等,这么看还是挺多的,
一个一个看,信号量最多用于资源计数,比如一个停车场的车位数,
当有车子来的时候信号量就减一,有车子走的时候信号量就加1,当信号量为
0时,停车场满,需要或许信号量的线程等待挂起。
信号量的衍生品:二值信号量,互斥信号量,一个一个看。
二值信号量就是信号量的值只有0和1两种状态,例如车位只有一个。
互斥信号量就是信号量谁获取的必须谁释放掉,例如一辆共享单车,
只有被借车人归还以后,其它人才能申请使用。
2018/12/04 11:41:11
7
s453208[版主]
电源币:810 | 积分:103 主题帖:43 | 回复帖:114
LV7
旅长
事件:比如有人叫你去吃饭,这是一个你接收到的一个事件,但是你还不能走,
你需要等待下班事件到来以后才能去吃饭,这就是事件的一个典型应用,实现
请参考那个栗子。
邮箱:理解最传统的信件和邮箱,邮箱都是固定的,入口很窄,只能塞信件,
你要是想写信寄把锤子,这个真有点难,但是你可以在信里面告诉他我家的地址,
让他上门来取锤子,这是可以的,这就是邮箱的优点和缺点了,邮件的大小只能
是四个字节,看似很难传输很大的东西,但是别忘了指针的大小也刚好是四个字节,
是不是天意呢。
消息队列:这个玩意就更好理解了,快递,你可以寄一封信,也可以寄一吨煤,唯一
的问题二者需要的成本不一样,只要钱给够,你说你要寄啥吧,只要不违法。消息队列
的存在,你可以自定义类型发送,但是问题是不同类型的系统开销还是不太一样的,能用
邮箱还是邮箱好,毕竟我们的资源有限,能省就省。此篇到这里啦,希望对大家有所帮助。
客服热线
服务时间:周一至周五9:00-18:00
微信关注
免费技术研讨会
获取一手干货分享

互联网违法不良信息举报

Reporting Internet Illegal and Bad Information
editor@netbroad.com
022-58392381