一个旗标是一个单个整型值,结合有一对函数,典型地称为P,V。
内核代码中包含<asm/semaphore.h>,相关的类型是struct semaphore。旗标可以有几种方法来声明和初始化
一种是直接创建一个旗标,接着使用sema_init来设定它:
void sema_init(struct semaphore *sem, int val);
这里的val是安排给旗标的初始值。
通常旗标以互斥锁的模式使用。为使它的使用更容易,内核提供了一套帮助函数和宏定义。另一种声明和初始化方法如下:
DECLARE_MUTEX(name); 该方式将旗标变量(name)初始化为1
DECLARE_MUTEX_LOCKED(name);将其初始化为0,使互斥锁一开始就处于上锁状态;在允许任何线程存取之前将不得不显式解锁它。
若互斥锁必须在运行时间初始化(比如动态分配它时),使用如下中的一个:
void init_MUTEX(struct semaphore *sem);
void init_MUTEX_LOCKED(struct semaphore *sem);
在linux中,P函数称为down,它递减旗标的值,有3个版本的down:
void down(struct semaphore *sem); 递减旗标值并且需要等待多长时间就等待多长。
int down_interruptible(struct semaphore *sem); 其操作时可中断的,它允许一个在等待一个旗标的用户空间进程被用户中断。运用这 个需要额外关注的是,如果这个操作被中断了,那么函数将会返回一个非0值,调用 者也不会再拥有该旗标了。正确使用该函数需要不断的检查它的返回值,并且做出相 应的回应
int down_trylock(struct semaphore *sem); 它从不睡眠,如果旗标在调用时不可用,则它会立刻返回一个非0值。
当一个线程成功调用down各个版本中的一个时,表示它持有该旗标,就有权利访问其保护的临界区。当所需要的互斥操作完成后 ,旗标必须被返回,V操作对应着up:
void up(struct semaphore *sem);
一旦up被调用,调用者就不再拥有旗标。
如果在持有旗标是遇到了一个错误,旗标必须在返回错误状态给调用者前,必须释放旗标。
为什么设备驱动书里面翻译成旗标而不是信号灯呢。。。。