linux等待队列 第四篇
来源:互联网 发布:黑桐谷嫂的淘宝店 编辑:程序博客网 时间:2024/05/17 04:37
Linux内核里的等待队列机制在做驱动开发时用的非常多,多用来实现阻塞式访问,下面简单总结了等待队列的四种用法,希望对读者有所帮助。
1. 睡眠等待某个条件发生(条件为假时睡眠):
睡眠方式:wait_event, wait_event_interruptible
唤醒方式:wake_up (唤醒时要检测条件是否为真,如果还为假则继续睡眠,唤醒前一定要把条件变为真)
2. 手工休眠方式一:
1)建立并初始化一个等待队列项
DEFINE_WAIT(my_wait) <==> wait_queue_t my_wait; init_wait(&my_wait);
2)将等待队列项添加到等待队列头中,并设置进程的状态
prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state)
3)调用schedule(),告诉内核调度别的进程运行
4)schedule返回,完成后续清理工作
finish_wait()
#define __wait_event(wq, condition) \do {\DEFINE_WAIT(__wait);\\for (;;) {\prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);\if (condition)\break;\schedule();\}\finish_wait(&wq, &__wait);\} while (0)voidprepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state){unsigned long flags;wait->flags &= ~WQ_FLAG_EXCLUSIVE;spin_lock_irqsave(&q->lock, flags);if (list_empty(&wait->task_list))__add_wait_queue(q, wait);set_current_state(state);spin_unlock_irqrestore(&q->lock, flags);}实际上,在wait_event宏里已经集成了上述的步骤,不需自己一步步来写,自己只要定义一个等待队列头wait_queue_head_t *head(记住是头头头)就行了,而不需要定义wait_queue_t *wait(它在宏wait_event(wq, condition)-->DEFINE_WAIT(__wait)调用时会定义的,每调用一次就定义一个wait[局部的],然后添加到等待队列头head[全局的])
3. 手工休眠方式二:
1)建立并初始化一个等待队列项:
DEFINE_WAIT(my_wait) <==> wait_queue_t my_wait; init_wait(&my_wait);
2)将等待队列项添加到等待队列头中:
add_wait_queue
3)设置进程状态
__set_current_status(TASK_INTERRUPTIBLE);
4)schedule()
5)将等待队列项从等待队列中移除
remove_wait_queue()
其实,这种休眠方式相当于把手工休眠方式一中的第二步prepare_to_wait拆成两步做了,即prepare_to_wait <====>add_wait_queue + __set_current_status,其他都是一样的。
4. 老版本的睡眠函数sleep_on(wait_queue_head_t *queue):
将当前进程无条件休眠在给定的等待队列上,极不赞成使用这个函数,因为它对竞态没有任何保护机制。
一般情况下等待队列使用是有两个进程工作的,比如A进程待,B进程唤醒。
DECLARE_WAIT_QUEUE_HEAD(buffer);
A:while(1){
sleep_on(&buffer);
}
B:while(1){
schedule_timeout_uninterruptible(100);
wake_up(&buffer);
}
其实在内核中有种比较常用的是等待队列 wait_quit_t。
DECLARE_WAITQUEUE(wait,current);
add_wait_queue(&buffer,&wait);
这几天又看下这篇文章以及百度文档,发现其实上面这位仁兄已经把等待队列的用法说的很清楚了,还有就是百度的这篇文档把其中的原理也讲了。大家可以结合这两个一起看。
上次一使用add_wait_queue(&buffer,&wait)时,死机是因为没有使用schedule()这个函数,所以这个函数一直占用cpu所以就死机了。
http://wenku.baidu.com/view/129cbb235901020207409c64.html百度的这个文档好像不错,
#include<linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/kernel.h>
static DECLARE_WAIT_QUEUE_HEAD(myqueue);
int hello(void)
{
DECLARE_WAITQUEUE(wait,current);
daemonize("hello");
add_wait_queue(&myqueue,&wait);
printk("hello\n");
set_current_state(TASK_INTERRUPTIBLE);
schedule();
remove_wait_queue(&myqueue,&wait);
return 0;
}
int H_init(void)
{
int res = 0;
printk(KERN_ALERT "Hello ...\n");
kernel_thread(hello,NULL,CLONE_FS| CLONE_FILES| CLONE_SIGHAND| SIGCHLD);
return res;
}
void H_exit(void)
{
wake_up(&myqueue);
printk(KERN_ALERT "Bye ...\n");
}
static int __init hdrv_init(void)
{
printk(KERN_ALERT "driver loading ...\n");
return H_init();
}
static void __exit hdrv_exit(void)
{
printk(KERN_ALERT " driver unloaded.\n");
H_exit();
}
MODULE_LICENSE("GPL");
module_init(hdrv_init);
module_exit(hdrv_exit);
/** * __wake_up - wake up threads blocked on a waitqueue. * @q: the waitqueue * @mode: which threads * @nr_exclusive: how many wake-one or wake-many threads to wake up * @key: is directly passed to the wakeup function * * It may be assumed that this function implies a write memory barrier before * changing the task state if and only if any tasks are woken up. */void __wake_up(wait_queue_head_t *q, unsigned int mode,int nr_exclusive, void *key){unsigned long flags;spin_lock_irqsave(&q->lock, flags);__wake_up_common(q, mode, nr_exclusive, 0, key);spin_unlock_irqrestore(&q->lock, flags);}
- linux等待队列 第四篇
- linux 等待队列 第二篇
- linux 等待队列 第三篇
- linux等待队列
- LINUX 等待队列
- LINUX内核-等待队列
- linux等待队列
- linux 内核等待队列
- linux 等待队列
- linux 等待队列
- Linux等待队列简介
- linux 等待队列
- linux 等待队列
- linux 之 等待队列
- linux 等待队列
- linux等待队列
- linux 等待队列
- linux 线程等待队列
- Linux下Android ADB驱动安装详解
- Eclipse console 中文乱码解决
- 面向对象之构造函数和析构函数之五
- IOS开发UI展示之UITableView ──分页加载更多
- jBPM开发入门指南(1)
- linux等待队列 第四篇
- hdu 4003 Find Metal Mineral
- centos下安装libevent
- block的使用
- jBPM开发入门指南(2)
- Js文件在不同浏览器中的加载解析问题
- xcode合并模拟器和真机静态库的编译
- 突破LVS瓶颈,LVS Cluster部署(OSPF + LVS)
- 一位年轻董事长给大学生的三十条忠告【转】