第一种:
//这里 val 是安排给旗标的初始值.
void sema_init(struct semaphore *sem, int val);
//结果是一个旗标变量( 称为 name ),
//初始化为 1 ( 使用 DECLARE_MUTEX ) 或者 0 (使用 DECLARE_MUTEX_LOCKED ).
DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name);
// P 函数称为 down — 或者这个名子的某个变体
//这里, “down” 指的是这样的事实, 这个函数递减旗标的值
void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);
//一旦调用down的时候 则不再拥有旗标
void up(struct semaphore *sem);
第二种: 读者 写着旗标
//初始化
void init_rwsem(struct rw_semaphore *sem);
//读者接口
// down_read 的调用提供了对被保护资源的只读存取
//与其他读者可能地并发地存取. 注意 down_read 可能将调用进程置为不可中断的睡眠
// down_read_trylock 如果读存取是不可用时不会等待; 如果被准予存取它返回非零, 否则是 0.
//注意 down_read_trylock 的惯例不同于大部分的内核函数, 返回值 0 指示成功
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);
int down_write_trylock(struct rw_semaphore *sem);
//释放
void up_write(struct rw_semaphore *sem);
//你可以使用 downgrade_write 在一旦你已完成改变后允许其他读者
void downgrade_write(struct rw_semaphore *sem);
第三种:
// completion 是任务使用的一个轻量级机制: 允许一个线程告诉另一个线程工作已经完成.
//初始化
DECLARE_COMPLETION(my_completion);
或者, 如果 completion 必须动态创建和初始化:
struct completion my_completion;
/* … */
init_completion(&my_completion);
//等待 completion 是一个简单事来调用
void wait_for_completion(struct completion *c);
//如果多于一个线程在等待同一个 completion 事件, 这 2 个函数做法不同. complete 只唤醒一个等待的线程,
//而 complete_all 允许它们所有都继续. 在大部分情况下, 只有一个等待者, 这 2 个函数将产生一致的结果
void complete(struct completion *c);
void complete_all(struct completion *c);
//下面列一个example
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 */
}
//清理
void complete_and_exit(struct completion *c, long retval);
第四种: 自旋锁
//初始化spin_lock
spinlock_t my_lock = SPIN_LOCK_UNLOCKED;
//或者在运行时使用:
void spin_lock_init(spinlock_t *lock);
//在进入一个临界区前, 你的代码必须获得需要的 lock
void spin_lock(spinlock_t *lock);
//为释放一个你已获得的锁
void spin_unlock(spinlock_t *lock);
//实际上有 4 个函数可以加锁一个自旋锁:
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)
//也有 4 个方法来释放一个自旋锁
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);
//还有一套非阻塞的自旋锁操作:
//这些函数成功时返回非零( 获得了锁 ), 否则 0. 没有”try”版本来禁止中断.
int spin_trylock(spinlock_t *lock);
int spin_trylock_bh(spinlock_t *lock);