现在的位置: 首页 > 综合 > 正文

关于linux同步机制及代码解析

2013年01月30日 ⁄ 综合 ⁄ 共 4821字 ⁄ 字号 评论关闭

关于linux同步机制

定义

 

确保多个进程安全操作共享数据的安全机制,常用的有以下几类:

 

名称

定义

优点

缺点

原子操作

保证指令以原子的方式执行,即不能被打断

简单易用

使用面窄,只适用于计数器场合

自旋锁

最多只能被一个执行线程占有,其它试图占用此锁的线程将循环等待

可以用于中断处理程序中

循环等待占用CPU的时间,适用于快速任务(锁占用时间<线程切换时间)

信号量

睡眠锁,有任务试图获取已被占用的锁时,会才采用睡眠等待的方式

睡眠挂起释放了CPU的控制权,提高程序执行效率

不能用于中断处理程序,会导致睡眠

 

代码分析

内核版本:2.6.28.8

 

原子锁

代码出处: /arch/x86/include/asm/atomic_32.h

 

数据结构

typedef struct {

    int counter;

} atomic_t;  

 

仅例举原子整数操作列表

在声明一个atomic_t变量时,将它初始化为i

#define ATOMIC_INIT(i)  { (i) }

 

原子的读取整数变量v

#define atomic_read(v)      ((v)->counter)

 

原子地设置v值为i

#define atomic_set(v, i)    (((v)->counter) = (i))

 

原子地给Vi

static inline void atomic_add(int i, atomic_t *v)

{

    asm volatile(LOCK_PREFIX "addl %1,%0"

             : "+m" (v->counter)

             : "ir" (i));

}

 

原子地给Vi

static inline void atomic_sub(int i, atomic_t *v)

{

    asm volatile(LOCK_PREFIX "subl %1,%0"

             : "+m" (v->counter)

             : "ir" (i));

}

 

原子地给V1

static inline void atomic_inc(atomic_t *v)

{

    asm volatile(LOCK_PREFIX "incl %0"

             : "+m" (v->counter));

}

 

原子地给V1

static inline void atomic_dec(atomic_t *v)

{

    asm volatile(LOCK_PREFIX "decl %0"

             : "+m" (v->counter));

}

 

原子地给Vi,如果结果等于0,返回真,反之为假

static inline int atomic_sub_and_test(int i, atomic_t *v)

{

    unsigned char c;

 

    asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"

             : "+m" (v->counter), "=qm" (c)

             : "ir" (i) : "memory");

    return c;

}

 

原子地给Vi,如果结果为负数,返回真,反之为假

static inline int atomic_add_negative(int i, atomic_t *v)

{

    unsigned char c;

 

    asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"

             : "+m" (v->counter), "=qm" (c)

             : "ir" (i) : "memory");

    return c;

}

 

原子地给V1,如果结果等于0,返回真,反之为假

static inline int atomic_dec_and_test(atomic_t *v)

{

    unsigned char c;

 

    asm volatile(LOCK_PREFIX "decl %0; sete %1"

             : "+m" (v->counter), "=qm" (c)

             : : "memory");

    return c != 0;

}

 

原子地给Vi,如果结果等于0,返回真,反之为假

static inline int atomic_inc_and_test(atomic_t *v)

{

    unsigned char c;

 

    asm volatile(LOCK_PREFIX "incl %0; sete %1"

             : "+m" (v->counter), "=qm" (c)

             : : "memory");

    return c != 0;

}

 

自旋锁

数据结构

代码出处: /include/linux/spinlock_types.h

 

typedef struct {

    raw_spinlock_t raw_lock;

#ifdef CONFIG_GENERIC_LOCKBREAK

    unsigned int break_lock;

#endif

#ifdef CONFIG_DEBUG_SPINLOCK

    unsigned int magic, owner_cpu;

    void *owner;

#endif

#ifdef CONFIG_DEBUG_LOCK_ALLOC

    struct lockdep_map dep_map;

#endif

} spinlock_t;

 

 

方法列举

代码出处: /include/linux/spinlock.h /include/linux/spinlock_api_up.h /arch/um/include/asm/system.h

 

spin_lock 获取自旋锁

调用preempt_disable隐式禁止抢占

#define spin_lock(lock) /

  do { preempt_disable(); __acquire(lock); (void)(lock); } while (0)

 

spin_lock_irq 禁止本地中断并获取自旋锁

local_irq_disable禁止本地中断

#define spin_lock_irq(lock) /

  do { local_irq_disable(); __LOCK(lock); } while (0)

 

spin_lock_irqsave 保存本地中断的当前状态,禁止本地中断并获取自旋锁

#define spin_lock_irqsave(lock, flags)          /

    do {                        /

        typecheck(unsigned long, flags);    /

        _spin_lock_irqsave(lock, flags);    /

    } while (0)

 

#define _spin_lock_irqsave(lock, flags) /

  do { local_irq_save(flags); __LOCK(lock); } while (0)

local_save_flags保存当前进程的状态

#define local_irq_save(flags) do { local_save_flags(flags); /

                                   local_irq_disable(); } while(0)

 

spin_unlock 释放自旋锁

# define spin_unlock(lock) /

do {__raw_spin_unlock(&(lock)->raw_lock); __release(lock); } while (0)

 

static inline void __raw_spin_unlock(raw_spinlock_t *lock)

{

    __asm__ volatile ("move.d %1,%0" /

              : "=m" (lock->slock) /

              : "r" (1) /

              : "memory");

}

 

spin_unlock_irq 释放自旋锁,并激活本地中断

local_irq_enable使能本地中断

调用preempt_disable给抢占计数器-1,当其为0时使能抢占

#define spin_unlock_irq(lock) /

  do { local_irq_enable(); __UNLOCK(lock); } while (0)

 

#define __UNLOCK(lock) /

  do { preempt_enable(); __release(lock); (void)(lock); } while (0)

 

spin_unlock_irqrestore 释放自旋锁,并让中断恢复到以前状态

local_irq_restore恢复以前进程的状态

#define spin_unlock_irqrestore(lock, flags)     /

    do {                        /

        typecheck(unsigned long, flags);    /

        _spin_unlock_irqrestore(lock, flags);   /

    } while (0)

 

#define _spin_unlock_irqrestore(lock, flags)    __UNLOCK_IRQRESTORE(lock, flags)

 

#define __UNLOCK_IRQRESTORE(lock, flags) /

  do { local_irq_restore(flags); __UNLOCK(lock); } while (0)

 

#define local_irq_restore(flags) do { typecheck(unsigned long, flags); /

                      set_signals(flags); } while(0)

 

spin_lock_init 初始化自旋锁

# define spin_lock_init(lock)                   /

do {                                /

    static struct lock_class_key __key;         /

                                /

    __spin_lock_init((lock), #lock, &__key);        /

} while (0)

 

void __spin_lock_init(spinlock_t *lock, const char *name,

              struct lock_class_key *key)

{

#ifdef CONFIG_DEBUG_LOCK_ALLOC

    /*

     * Make sure we are not reinitializing a held lock:

     */

    debug_check_no_locks_freed((void *)lock, sizeof(*lock));

    lockdep_init_map(&lock->dep_map, name, key, 0);

#endif

    lock->raw_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;

    lock->magic = SPINLOCK_MAGIC;

    lock->owner = SPINLOCK_OWNER_INIT;

    lock->owner_cpu = -1;

}

spin_trylock试图获取指定的锁,如未获取,返回非0

#define spin_trylock(lock)      __cond_lock(lock, _spin_trylock(lock))

int __lockfunc _spin_trylock(spinlock_t *lock)

{

    preempt_disable();

抱歉!评论已关闭.