打印

不使用开关中断,还有什么方法来实现临界区的保护机制?

[复制链接]
3033|18
手机看帖
扫描二维码
随时随地手机跟帖
沙发
GZZXB|  楼主 | 2017-4-7 14:59 | 只看该作者
抛砖引玉
uint8_t g_Lock=0;
if(!g_Lock)
{
     g_Lock = 1;

     //DoSomething();  

     g_Lock = 0;
}
临界区经常存在UART中断接收入队,和其他线程对接收队列解析类似的应用中。
将以上代码任意放置在任何需要访问共享资源的地方,例如循环和中断中,
这段代码可以实现对共享资源的有效保护,确保只有一个线程访问。但是可能会
在某个线程中漏掉一些动作,例如在循环中加锁后,中断立即到来但是因为是在加锁
状态所以中断就不DoSomething()了,这个DoSomething()如果是个将数据压入队列
的操作,那么显然就丢了一个数据了。

使用特权

评论回复
板凳
feelhyq| | 2017-4-7 17:35 | 只看该作者
你这个叫 “掩耳盗铃” 即便是一个变量的操作也会存在临界区 ,  汇编伪代码给 如下
  ldr r0, =g_lock      
  mov r1, #1
str r1, [r0]

C语言给g_lock赋值看起来是一条语句,实际上对应还几条汇编,有可能在汇编操作的时候发生被抢占了

使用特权

评论回复
地板
GZZXB|  楼主 | 2017-4-7 21:57 | 只看该作者
feelhyq 发表于 2017-4-7 17:35
你这个叫 “掩耳盗铃” 即便是一个变量的操作也会存在临界区 ,  汇编伪代码给 如下
  ldr r0, =g_lock     ...

4位机不懂不探讨,8/32位机对于字节变量来说,是原子操作,尽管抢占不影响。

使用特权

评论回复
5
feelhyq| | 2017-4-7 22:45 | 只看该作者
GZZXB 发表于 2017-4-7 21:57
4位机不懂不探讨,8/32位机对于字节变量来说,是原子操作,尽管抢占不影响。 ...

针对楼主的回答,我去写了个汇编和C,C通过反汇编后,再看bin文件的机器代码,对于单个变量不是源自操作噢

使用特权

评论回复
6
feelhyq| | 2017-4-7 22:48 | 只看该作者

使用特权

评论回复
7
GZZXB|  楼主 | 2017-4-7 23:07 | 只看该作者
feelhyq 发表于 2017-4-7 22:45
针对楼主的回答,我去写了个汇编和C,C通过反汇编后,再看bin文件的机器代码,对于单个变量不是源自操作 ...

写代码验证,为你的认真点赞   所谓原子操作并不是说c语句一定要一条汇编指令完成,c转成汇编肯定是多条指令了,除非无分页和分bank机制的低端片子,例如PIC的16f5x系列 HT的66f00x系列,一句SET 就搞定。 我说原子的意思是指g_Lock 赋值的过程,也就是向这个字节地址赋值和读取的值是不会错的,1就是1 0就是0 写什么进去就是什么,读取也不会错。你可以假设在任意位置被抢占然后你看看有什么影响。 如果g_Lock变量是双字节而芯片是8位片子,才需要考虑抢占。多多交流本人小白一枚

使用特权

评论回复
8
hgjinwei| | 2017-4-8 08:01 | 只看该作者
uint8_t g_Lock=0;
if(!g_Lock)
{
     g_Lock = 1;

     //DoSomething();  

     g_Lock = 0;
}


这貌似只能用于绝对优先级的环境下,比如中断就是比线程优先级高。
确保A执行完"if(!g_Lock)"后,如果被B打断,B不会在执行完“if(!g_Lock)”后,又被打断而继续执行A

使用特权

评论回复
9
feelhyq| | 2017-4-8 10:09 | 只看该作者
GZZXB 发表于 2017-4-7 23:07
写代码验证,为你的认真点赞   所谓原子操作并不是说c语句一定要一条汇编指令完成,c转成汇编肯 ...

那这个 uint8_t g_lock 是不是需要加volatile去修饰呢?

使用特权

评论回复
10
feelhyq| | 2017-4-8 10:10 | 只看该作者
GZZXB 发表于 2017-4-7 23:07
写代码验证,为你的认真点赞   所谓原子操作并不是说c语句一定要一条汇编指令完成,c转成汇编肯 ...

老师常教我们 打破砂锅问到底呀

使用特权

评论回复
11
cuya| | 2017-4-9 20:50 | 只看该作者
这是多线程程序中的基本问题, 用互斥锁。对于嵌入式的中断,亦是如此。

使用特权

评论回复
12
GZZXB|  楼主 | 2017-4-10 08:43 | 只看该作者
feelhyq 发表于 2017-4-8 10:09
那这个 uint8_t g_lock 是不是需要加volatile去修饰呢?

必须

使用特权

评论回复
13
GZZXB|  楼主 | 2017-4-10 08:44 | 只看该作者
cuya 发表于 2017-4-9 20:50
这是多线程程序中的基本问题, 用互斥锁。对于嵌入式的中断,亦是如此。

请给出示例

使用特权

评论回复
14
GZZXB|  楼主 | 2017-4-10 08:49 | 只看该作者
cuya 发表于 2017-4-9 20:50
这是多线程程序中的基本问题, 用互斥锁。对于嵌入式的中断,亦是如此。

多线程下轻而易举地可以实现,比如MFC下实现自旋锁,互拆锁,创建临界变量等,在嵌入式中不关中断实现类似机制还不得头绪,如果你有好的思想期待你的分享

使用特权

评论回复
15
cuya| | 2017-4-10 10:29 | 只看该作者
嵌入式里, 开关中断是最简单而且最方便的临界区控制方式, 其他的方式不是不能做到, 而是麻烦一些, 即自己得做 Lock 机制之类的控制。舍近求远没有什么必要, 除非是理论探讨。

使用特权

评论回复
16
GZZXB|  楼主 | 2017-4-10 13:13 | 只看该作者
cuya 发表于 2017-4-10 10:29
嵌入式里, 开关中断是最简单而且最方便的临界区控制方式, 其他的方式不是不能做到, 而是麻烦一些, 即自 ...

如果只是麻烦一些,我觉得很有必要分享你的思想,毕竟有些应用是不太希望频繁开关中断的

使用特权

评论回复
17
renxiaolin| | 2017-4-10 17:21 | 只看该作者
看到你们的讨论,我就想到啦群主,

使用特权

评论回复
18
GZZXB|  楼主 | 2017-4-12 20:27 | 只看该作者
renxiaolin 发表于 2017-4-10 17:21
看到你们的讨论,我就想到啦群主,

真心看不懂 “啦群主”这三字金言“里含的玄机哦

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

96

主题

331

帖子

10

粉丝