信号量:
Linux 内核的信号量在概念和原理上与用户态的信号量是一样的,
但是它不能在内核之外使用,只能在内核中,它是一种睡眠锁.
如果有一个任务想要获得 已经被占用 的信号量时,信号量会将这个进程放入一个等待队列, 然后让其睡眠,
当持有信号量的进程将信号释放后,处于等待队列中的任务将被唤醒,并让其获得信号量.
1,信号量在创建时需要设置一个初始值,表示允许有几个任务同时访问该信号量保护的资源.
初始值为 1 就变成互斥锁 ( Mutex ) ,即同时只能有一个任务可以访问信号量保护的资源.
2,当任务访问完被信号量保护的共享资源后,必须释放信号量,释放信号量通过把信号量的值加 1 实现.
如果释放后信号量的值为非正数,表明有任务等待当前信号量,因此要唤醒等待该信号量的任务.
定义信号量 struct semaphore:
信号量的实现也是与体系结构相关的,定义在 < asm/semaphore.h > 中,
struct semaphore 类型用来表示信号量.
eg: struct semaphore sem;
初始化信号量 sema_init init_MUTEX init_MUTEX_LOCKED :
void sema_init ( struct semaphore *sem , int val )
该函数用于初始化设置 信号量 的初值,它设置信号量 sem 的值 为 val .
初始化一互斥锁 MUTEX:
void init_MUTEX ( struct semaphore *sem )
该函数用于初始化一个互斥锁,即它把信号量 sem 的值设置为 1.
void init_MUTEX_LOCKED ( struct semaphore *sem)
该函数也用于初始化一个互斥锁,但是它把信号量 sem 的值设置为 0,即一开始就处在已锁状态.
初始化 定义一步完成 DECLARE_MUTEX DECLARE_MUTEX_LOCKED :
定义与初始化的工作可由如下宏一步完成:
DECLARE_MUTEX ( name )
定义一个信号量 name,并初始化她的值为 1 .
DECLARE_MUTEX_LOCKED ( name )
定义一个信号量 name ,但把它的初始化设置为 0 ,即锁在创建时就处在已锁状态.
获取信号量 down down_interruptible down_trylock :
1, void down ( struct semaphore * sem )
获得信号量 sem . 可能会导致进程睡眠,因此不能在中断上下文使用该函数.
该函数将把 sem 的值减 1,如果信号量 sem 的值非负,就直接返回,
否则调用者将被挂起,直到别的任务释放该信号量才能继续使用.
2, int down_interruptible ( struct semaphore * sem )
获取信号量 sem . 如果信号量不可用,进程将被置为 TASK_INTERRUPTIBLE 类型的睡眠状态.
该函数由返回值来区分是正常返回还是被信号中断返回,
如果返回 0 ,表示获得信号量正常返回,
如果被信号打断,返回 ——EINTR .
3, down_trylock ( struct semaphore * sem )
获取信号量 sem . 如果信号量不可获取,down_trylock 会立即返回 一个 非零值. down_trylock 它永远不会休眠
注:
down () 函数现已不建议继续使用,建议使用 down_killable ()或 down_interruptible ()
释放信号量 up :
void up ( struct semaphore *sem )
该函数释放信号量 sem ,即把 sem 的值加 1,如果 sem 的值为非负数,
表明有任务等待该信号量,因此唤醒这些等待者.
实例 --- 按键信号量使用:
1,初始化,定义信号量:
在驱动程序开头初始化,定义信号量:
static DECLARE_MUTEX(button_lock); //定义互斥锁
2,获取信号量:
在 open 函数中获取信号量,获取到就继续执行,否则休眠;
/* 获取信号量 */
down(&button_lock);
3,释放信号量:
程序退出,close 释放信息量:
up(&button_lock); /* 释放信号量 */
return 0;
4,执行测试应用程序:
两个应用程序同时去打开这驱动,两个应用程序都放在后台执行;
首先,第一个的应用程序的 stat 为 S 睡眠状态;
第二个应用程序的 stat 为 D 状态,为僵死,不可中断的睡眠状态;
只有第一个应用程序退出的时候 ( kill 掉 ),
这时第一个应用程序 释放了信号量 up(&button_lock); ,
才会去唤醒第二个应用程序,
第二个应用程序才能继续执行,
第二个应用程序处于正常运行状态.