本文共 3066 字,大约阅读时间需要 10 分钟。
在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实像多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作、信号量(semaphore)、读写信号量(rw_semaphore)、自旋锁(spin_lock)、BKL(大内核锁)、读写锁(rwlock)、brlock(只包含在2.4内核中)、RCU(只包含在2.6内核中)和seqlock(只包含在2.6内核中)。
linux2.6.4 + i386
原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,它的最小的执行单位,不可能有比它更小的执行单位,因此这里的原子实际是使用了物理学里的物质微粒的概念。
原子操作需要硬件的支持,因此是架构相关的,它们都使用汇编语言实现,因为C语言并不能实现这样的操作。
typedef struct { volatile int counter; } atomic_t;
通过上面的定义我们可以发现,该原子类型就是简单的封装了一个整形变量。其中volatile修饰字段告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问。
atomic_read
#define atomic_read(v) ((v)->counter)
该函数对原子类型的变量进行原子读操作,因为是从内存中直接读取counter的值,因此可以保证原子性。它返回原子类型的变量v的值。
atomic_set
#define atomic_set(v,i) (((v)->counter) = (i))
该函数设置v->counter的值为i,同样可以保证原子性。
atomic_add
static __inline__ void atomic_add(int i, atomic_t *v){ __asm__ __volatile__( LOCK "addl %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter));}
上面的代码中含有内联汇编,内联汇编格式:
__asm__(assembler template /*汇编指令*/ :output operands /*输出数 */ :input operands /*输入数 */ :list of clobbered registers /*被污染的寄存器 */ );
LOCK定义
#ifdef CONFIG_SMP#define LOCK "lock ; "#else#define LOCK ""#endif
如果当前的处理器是对称多内核的处理器,LOCK被定义为"lock:",避免其他进程修改数据。否则,定义为空。
对于atomic_add函数,从寄存器中读取i和内存中读取counter,进行相加,然后存入内存中。
atomic_sub
static __inline__ void atomic_sub(int i, atomic_t *v){ __asm__ __volatile__( LOCK "subl %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter));}
从寄存器中读取i和内存中读取counter,进行相减,然后存入内存中。
atomic_sub_and_test
static __inline__ int atomic_sub_and_test(int i, atomic_t *v){ unsigned char c; __asm__ __volatile__( LOCK "subl %2,%0; sete %1" :"=m" (v->counter), "=qm" (c) :"ir" (i), "m" (v->counter) : "memory"); return c;}
该函数从原子类型的变量v中减去i,并判断结果是否为0,如果为0,返回真,否则返回假。
atomic_inc
static __inline__ void atomic_inc(atomic_t *v){ __asm__ __volatile__( LOCK "incl %0" :"=m" (v->counter) :"m" (v->counter));}
该函数对原子类型变量v原子地增加1。
atomic_dec
static __inline__ void atomic_dec(atomic_t *v){ __asm__ __volatile__( LOCK "decl %0" :"=m" (v->counter) :"m" (v->counter));}
该函数对原子类型的变量v原子地减1。
atomic_dec_and_test
static __inline__ int atomic_dec_and_test(atomic_t *v){ unsigned char c; __asm__ __volatile__( LOCK "decl %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0;}
该函数对原子类型的变量v原子地减1,并判断结果是否为0,如果为0,返回真,否则返回假。
atomic_inc_and_test
static __inline__ int atomic_inc_and_test(atomic_t *v){ unsigned char c; __asm__ __volatile__( LOCK "incl %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0;}
该函数对原子类型的变量v原子地增加1,并判断结果是否为0,如果为0,返回真,否则返回假。
atomic_add_negative
static __inline__ int atomic_add_negative(int i, atomic_t *v){ unsigned char c; __asm__ __volatile__( LOCK "addl %2,%0; sets %1" :"=m" (v->counter), "=qm" (c) :"ir" (i), "m" (v->counter) : "memory"); return c;}
该函数对原子类型的变量v原子地增加I,并判断结果是否为负数,如果是,返回真,否则返回假。
转载地址:http://fnrai.baihongyu.com/