By: 潘云登
Date: 2009-6-1
Email: intrepyd@gmail.com
Homepage: http://blog.csdn.net/intrepyd
Copyright: 该文章版权由潘云登所有。可在非商业目的下任意传播和复制。
对于商业目的下对本文的任何行为需经作者同意。
写在前面
1. 本文内容对应《linux设备驱动程序》第五章。
2. 参考《linux内核设计与实现》。
3. 希望本文对您有所帮助,也欢迎您给我提意见和建议。
同步机制快速参考
同步机制 | 信号量 |
头文件 | <asm/semaphore.h> |
类型 | struct semaphore; |
静态声明 | DECLARE_SEMAPHORE_GENERIC(name, count); DECLARE_MUTEX(name); DECLARE_MUTEX_LOCKED(name); |
动态初始化 | void sema_init(struct semaphore *sem, int val); void init_MUTEX(struct semaphore *sem); void init_MUTEX_LOCKED(struct semaphore *sem); |
请求 | void down(struct semaphore *sem); int down_interruptible(struct semaphore *sem); int down_trylock(struct semaphore *sem); |
释放 | void up(struct semaphore *sem); |
示例 | /* define and declare a semaphore, named mr_sem, with a count of one */ static DECLARE_MUTEX(mr_sem);
/* attempt to acquire the semaphore ... */ if (down_interruptible(&mr_sem)) { /* signal received, semaphore not acquired ... */ }
/* critical region ... */
/* release the given semaphore */ up(&mr_sem); |
同步机制 | 读写信号量 |
头文件 | <linux/rwsem.h> |
类型 | struct rw_semaphore; |
静态声明 | DECLARE_RWSEM(name); |
动态初始化 | void init_rwsem(struct rw_semaphore *sem); |
请求 | void down_read(struct rw_semaphore *sem); int down_read_trylock(struct rw_semaphore *sem); void down_write(struct rw_semaphore *sem); int down_write_trylock(struct rw_semaphore *sem); |
释放 | void up_read(struct rw_semaphore *sem); void up_write(struct rw_semaphore *sem); void downgrade_write(struct rw_semaphore *sem); |
示例 | static DECLARE_RWSEM(mr_rwsem);
/* attempt to acquire the semaphore for reading ... */ down_read(&mr_rwsem);
/* critical region (read only) ... */
/* release the semaphore */ up_read(&mr_rwsem);
/* ... */
/* attempt to acquire the semaphore for writing ... */ down_write(&mr_rwsem);
/* critical region (read and write) ... */
/* release the semaphore */ up_write(&mr_sem); |
同步机制 | completion |
头文件 | <linux/completion.h> |
类型 | struct completion; |
静态声明 | DECLARE_COMPLETION(my_completion); |
动态初始化 | init_completion(&my_completion); |
请求 | void wait_for_completion(struct completion *c); |
释放 | void complete(struct completion *c); void complete_all(struct completion *c); |
示例 | DECLARE_COMPLETION(comp);
ssize_t complete_read (struct file *filp, char _ _user *buf, size_t count, loff_t *pos) { printk(KERN_DEBUG "process %i (%s) going to sleep/n", current->pid, current->comm); wait_for_completion(&comp); printk(KERN_DEBUG "awoken %i (%s)/n", current->pid, current->comm); return 0; /* EOF */ }
ssize_t complete_write (struct file *filp, const char _ _user *buf, size_t count, loff_t *pos) { printk(KERN_DEBUG "process %i (%s) awakening the readers.../n", current->pid, current->comm); complete(&comp); return count; /* succeed, to avoid retrial */ } |
同步机制 | 自旋锁 |
头文件 | <linux/spinlock.h> |
类型 | spinlock_t; |
静态声明 | spinlock_t my_lock = SPIN_LOCK_UNLOCKED; |
动态初始化 | void spin_lock_init(spinlock_t *lock); |
请求 | void spin_lock(spinlock_t *lock); void spin_lock_irqsave(spinlock_t *lock, unsigned long flags); void spin_lock_irq(spinlock_t *lock); void spin_lock_bh(spinlock_t *lock); int spin_trylock(spinlock_t *lock); int spin_trylock_bh(spinlock_t *lock); |
释放 | void spin_unlock(spinlock_t *lock); void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); void spin_unlock_irq(spinlock_t *lock); void spin_unlock_bh(spinlock_t *lock); |
示例 | spinlock_t mr_lock = SPIN_LOCK_UNLOCKED; spin_lock(&mr_lock); /* critical region */ spin_unlock(&mr_lock);
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED; spin_lock_irq(&mr_lock); /* critical section ... */ spin_unlock_irq(&mr_lock);
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED; unsigned long flags; spin_lock_irqsave(&mr_lock, flags); /* critical region ... */ spin_unlock_irqrestore(&mr_lock, flags); |
同步机制 | 读写自旋锁 |
头文件 | <linux/spinlock.h> |
类型 | rwlock_t |
静态声明 | rwlock_t my_rwlock = RW_LOCK_UNLOCKED; |
动态初始化 | void rwlock_init(rwlock_t *lock); |
请求 | void read_lock(rwlock_t *lock); void read_lock_irqsave(rwlock_t *lock, unsigned long flags); void read_lock_irq(rwlock_t *lock); void read_lock_bh(rwlock_t *lock); void write_lock(rwlock_t *lock); void write_lock_irqsave(rwlock_t *lock, unsigned long flags); void write_lock_irq(rwlock_t *lock); void write_lock_bh(rwlock_t *lock); int write_trylock(rwlock_t *lock); |
释放 | void read_unlock(rwlock_t *lock); void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags); void read_unlock_irq(rwlock_t *lock); void read_unlock_bh(rwlock_t *lock); void write_unlock(rwlock_t *lock); void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags); void write_unlock_irq(rwlock_t *lock); void write_unlock_bh(rwlock_t *lock); |
示例 | rwlock_t mr_rwlock = RW_LOCK_UNLOCKED;
read_lock(&mr_rwlock); /* critical section (read only) ... */ read_unlock(&mr_rwlock);
write_lock(&mr_rwlock); /* critical section (read and write) ... */ write_unlock(&mr_lock); |
同步机制 | 原子变量 |
头文件 | <asm/atomic.h> |
类型 | atomic_t; |
相关操作 | void atomic_set(atomic_t *v, int i); atomic_t v = ATOMIC_INIT(0); int atomic_read(atomic_t *v); void atomic_add(int i, atomic_t *v); void atomic_sub(int i, atomic_t *v); void atomic_inc(atomic_t *v) void atomic_dec(atomic_t *v); int atomic_inc_and_test(atomic_t *v); int atomic_dec_and_test(atomic_t *v); int atomic_sub_and_test(int i, atomic_t *v); int atomic_add_negative(int i, atomic_t *v); int atomic_add_return(int i, atomic_t *v); int atomic_sub_return(int i, atomic_t *v); int atomic_inc_return(atomic_t *v); int atomic_dec_return(atomic_t *v); |
示例 | atomic_t v; /* define v */ atomic_t u = ATOMIC_INIT(0); /* define u and initialize it to zero */
atomic_set(&v, 4); /* v = 4 (atomically) */ atomic_add(2, &v); /* v = v + 2 = 6 (atomically) */ atomic_inc(&v); /* v = v + 1 = 7 (atomically) */
printk("%d/n", atomic_read(&v)); /* will print "7" */ |
同步机制 | 原子位操作 |
头文件 | <asm/bitops.h> |
相关操作 | void set_bit(nr, void *addr); void clear_bit(nr, void *addr); void change_bit(nr, void *addr); test_bit(nr, void *addr); int test_and_set_bit(nr, void *addr); int test_and_clear_bit(nr, void *addr); int test_and_change_bit(nr, void *addr); |
示例 | /* try to set lock */ while (test_and_set_bit(nr, addr) != 0) wait_for_a_while( );
/* do your work */
/* release lock, and check... */ if (test_and_clear_bit(nr, addr) = = 0) something_went_wrong( ); /* already released: error */
unsigned long word = 0;
set_bit(0, &word); /* bit zero is now set (atomically) */ set_bit(1, &word); /* bit one is now set (atomically) */ printk("%ul/n", word); /* will print "3" */ clear_bit(1, &word); /* bit one is now unset (atomically) */ change_bit(0, &word); /* bit zero is flipped; now it is unset (atomically) */
/* atomically sets bit zero and returns the previous value (zero) */ if (test_and_set_bit(0, &word)) { /* never true */ }
/* the following is legal; you can mix atomic bit instructions with normal C */ word = 7; |