struct semaphore { spinlock_t lock; unsigned int count; struct list_head wait_list; };1.1 信号量的初始化
void sema_init(struct semaphore *sem, int val);其中参数val用于初始化信号量结构中的count值,即信号量的初值。
void down(struct semaphore *sem); int down_interruptible(struct semaphore *sem); int down_trylock(struct semaphore *sem);down操作用于对信号量中的count值做减1操作,其中down函数有可能会导致进程睡眠,即对临界资源访问时,首先是判断该临界资源是否能够被访问(判断信号量的count值),如果不能对其进行访问(count值为0),那么将导致进程睡眠。而down_interruptible函数同down函数类似,只是使用down_interruptible函数会将进程设置成TASK_INTERRUPTIBLE状态,意味着该进程可以被其它信号唤醒,如果该进程在睡眠过程中接收到了信号,那么该进程就会被唤醒,而down_interruptible函数返回一个非0值。而down_trylock函数不会引起进程的睡眠,如果临界资源不可被访问,down_trylock函数会立即返回,返回一个非0值,而如果可以被访问,则返回0值。
void up(struct semaphore *sem);down操作是对信号量中的count值做减1操作,那么up操作就是对count值做加1操作,即释放对临界区的控制权,同时唤醒被睡眠的进程,从信号量结构中可以看到有个链表wait_list,那么被睡眠的进程就会被添加到这条链表上,那么在执行up操作时就从这条链表上去获取被睡眠的进程。
/* 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);
struct rw_semaphore { signed long count; spinlock_t wait_lock; struct list_head wait_list; #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; #endif };
void init_rwsem(struct rw_semaphore *sem);当然也可以使用宏DECLARE_RWSEM静态定义一个读写信号量并对其做初始化。
void down_read(struct rw_semaphore *sem); int down_read_trylock(struct rw_semaphore *sem); void up_read(struct rw_semaphore *sem);
void down_write(struct rw_semaphore *sem); down_write_trylock(struct rw_semaphore *sem); void up_write(struct rw_semaphore *sem); void downgrade_write(struct rw_semaphore *sem);
void spin_lock_init(spinlock_t *lock);或者使用宏SPIN_LOCK_UNLOCKED在编译时就进行初始化,例如:
spinlock_t my_lock = SPIN_LOCK_UNLOCKED;或者使用宏DEFINE_SPINLOCK静态定义一个自旋锁并对其做初始化,注意初始化都是将其初始化成解锁状态。
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);自旋锁可以用于中断处理函数中(信号量就不能,因为会导致睡眠),那么在中断处理函数中使用自旋锁时,首先需要禁止本地中断,然后再获取锁,spin_lock_irqsave将这两个步骤合并成一个,而中断状态则包存在flags中。而spin_lock_irq只会禁止本地中断,而不会存储中断状态,所以需要确保在加锁前中断是被激活的。而spin_lock_bh只会禁止软中断,硬中断会继续执行,即至禁止底半部中断。
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);
DEFINE_SPINLOCK(mr_lock); spin_lock(&mr_lock); /* critical region ... */ spin_unlock(&mr_lock);
void rwlock_init(rwlock_t *lock);或者使用宏DEFINE_RWLOCK静态定义和初始化一个读写自旋锁,例如:
DEFINE_RWLOCK(mr_rwlock);
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 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_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);
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);
void init_completion(struct completion *x);或者使用宏DECLARE_COMPLETION静态定义和初始化一个completion,例如:
DECLARE_COMPLETION(mr_comp);
void wait_for_completion(struct completion *); void complete(struct completion *); void complete_all(struct completion *);注意wait_for_completion是一个非中断等待,complete和complete_all两个函数类似,都是用于唤醒线程,只是complete只会唤醒一个线程,而complete_all会唤醒所有的等待线程。
typedef struct {
volatile int counter;
} atomic_t;
可以看到实际上就是int类型,虽然int类型是32位,但是这里只使用了其中的24位。
void atomic_set(atomic_t *v, int i);也可以使用宏ATOMIC_INIT在定义原子变量时就对其做初始化,例如:
atomic_t v = ATOMIC_INIT(0);
int atomic_read(const atomic_t *v);
void atomic_add(int i, atomic_t *v); /* 原子变量加i */ void atomic_sub(int i, atomic_t *v); /* 原子变量减i */
void atomic_inc(atomic_t *v); void atomic_dec(atomic_t *v);
int atomic_sub_and_test(int i, atomic_t *v); int atomic_dec_and_test(atomic_t *v); int atomic_inc_and_test(atomic_t *v);执行操作后并测试原子值,如果其值为0,则返回true,否则返回false。
int atomic_add_negative(int i, atomic_t *v);atomic_add_negative函数在执行add操作后,如果原子值为负是返回true,否则返回false。
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);执行操作后将原子值返回。
void set_bit(unsigned int nr, volatile unsigned long *addr);参数nr即要设置的哪位。
void clear_bit(int nr, volatile unsigned long *addr);
void change_bit(int nr, volatile unsigned long *addr);对指定的位取反。
int test_bit(int nr, const volatile unsigned long *addr);
int test_and_set_bit(int nr, volatile unsigned long *addr); int test_and_clear_bit(int nr, volatile unsigned long *addr); int test_and_change_bit(int nr, volatile unsigned long *addr);