编程中的临界保护
0赞临界保护又称并发保护,分时间保护和空间保护两种,时间保护指的是,在某一段特定的时间内,某个任务必须独占cpu时间;空间保护指的是,共享数据在某段时间内只能由某任务独占访问。
在编程中,临界操作有那么几种:
1、原子操作,可以理解为无条件原语操作,即操作过程中不允许被打断,原子操作虽然可以用在共享数据的保护中,但这不是它的主要功能。它主要用在,某些操作有非常苛刻的时限要求,一旦开始,就必须在规定的时间内完成,比如你用指令输出一个1uS的脉冲,先输出高电平,演示5个周期(假设每周期200nS)后输出低电平,那么,输出高低电平之间就不允许任何人打断。
2、原语操作,可以理解为有限原子操作,主要用在共享数据并发访问的保护中。比如某一段代码,受某互斥量保护,那么,该段代码是允许被中断或被高优先级线程的,但前提是,中断或高优先级线程中不去竞争该互斥量。对于被互斥量保护的数据来说,操作看起来是连续的,没有被打断。
3、“读-修改-写”操作,这个操作无论变量是不是跟cpu字长相同,除非cpu能够在单周期内完成“读-修改-写”,这是不太可能的,因为中间的“修改”可能很复杂,否则都必须关中断(加入ISR有访问)或关调度(假设高优先级任务有访问)来使操作原子化,至于nucleus中为什么不保护,我不清楚,因为没用过nucleus。
4、单边读写操作,即每次操作要么只读,要么只写的操作,这种操作允许有限的不做临界保护,以下文字摘自djyos代码:
//以下是CPU可以用一条指令处理的数据类型,多用于需要保持数据完整性的操作,以及
//需要快速的操作。
//数据完整性和原子操作的异同:
//数据完整性是指在任何时候都能读到正确值的数据,比如下列语句:
// uint32_t b32;
// b32++; //b32的原值是0x0000ffff
//在32位risc机上,执行过程为:
//取b32地址到寄存器0-->取b32的数值到寄存器1-->寄存器1加1-->把寄存器1写入b32.
//上述过程无论在哪里被中断或者被高优先级线程打断,在中断或高优先级线程中读b32,
//要么得到0x0000ffff,要么得到0x00010000,这两都可以认为是正确数据.
//而在16位机上,执行过程是
//1、取0x0000到寄存器r0,取0xffff到寄存器r1
//2、执行加操作,使r0=0x0001,r1=0x0000
//3、把r0写入b32的高16位。
//4、把r1写入b32的低16位。
//如果在第3和第4步骤之间被中断打断,在中断里读b32,将得到错误的0x00001ffff。
//那么原子操作呢?就是整个执行过程不被任何中断或者高优先级线程打断,还看上面代码,
//如果b32被定义为原子变量,则无论在16位还是32位机上,b32都可以得到正确的值。
typedef uint32_t ucpu_t;
#define cn_limit_ucpu cn_limit_uint32
#define cn_min_ucpu (0)
typedef sint32_t scpu_t;
#define cn_limit_scpu cn_limit_sint32
#define cn_min_scpu cn_min_sint32
