加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Linux使用wait_event_interruptible()睡眠进程

(2013-02-18 21:29:40)
标签:

linux

嵌入式

it

wait_event_interruptible(wq, condition),该函数修改task的状态为TASK_INTERRUPTIBLE,意味着该进程将不会继续运行直到被唤醒,然后被添加到等待队列wq中。

在wait_event_interruptible()中首先判断condition是不是已经满足,如果条件满足则直接返回0,否则调用__wait_event_interruptible(),并用__ret来存放返回值
#define wait_event_interruptible(wq, condition)          \
({                                                       \
    int __ret = 0;                                       \
    if (!(condition))                                    \
        __wait_event_interruptible(wq, condition, __ret);\
    __ret;                                               \
})

在无限循环中,__wait_event_interruptible()将本进程置为可中断的挂起状态,反复检查condition是否成立,如果成立则退出,如果不成立则继续休眠;条件满足后,即把本进程运行状态置为运行态

,并将__wait从等待队列中清除掉,从而进程能够调度运行。如果进程当前有异步信号(POSIX的),则返回-ERESTARTSYS。
#define __wait_event_interruptible(wq, condition, ret)      \
do {                                                        \
    DEFINE_WAIT(__wait);                                    \
    for (;;) {                                              \
        prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);  \
        if (condition)                                      \
            break;                                          \
        if (!signal_pending(current)) {                     \
            schedule();                                     \
            continue;                                       \
                                                         \
        ret = -ERESTARTSYS;                                 \
        break;                                              \
                                                         \
    finish_wait(&wq, &__wait);                              \
} while (0)

 

以下是在linux下OV7725驱动(s3c2440camif.c)中的一个例子

定义等待队列
wait_queue_head_t cmdqueue;(s3c2440camif.h中定义的)
初始化等待队列
static int __init camif_probe(struct platform_device *dev)
{
 ......
 pdev->cmdcode = CAMIF_CMD_NONE;
 init_waitqueue_head(&pdev->cmdqueue);
 ......
}
调用等待队列
static int start_capture(struct s3c2440camif_dev * pdev, int stream)
{
 ......
 if (stream == 0)
 {
  pdev->cmdcode = CAMIF_CMD_STOP;
  ret = wait_event_interruptible(pdev->cmdqueue, pdev->cmdcode == CAMIF_CMD_NONE);
 }
 return ret;
 ......
}
在中断处理函数中唤醒等待队列
static irqreturn_t on_camif_irq_c(int irq, void * dev)
{
 ......
 pdev->cmdcode = CAMIF_CMD_NONE;
 wake_up(&pdev->cmdqueue);
 ......
}
static irqreturn_t on_camif_irq_p(int irq, void * dev)
{
 ......
 pdev->cmdcode = CAMIF_CMD_NONE;
 wake_up(&pdev->cmdqueue);
 ......
}
在下面函数中调用start_capture()
static ssize_t camif_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
{
 ......
 if(start_capture(pdev, 0) != 0)
 {
  return -ERESTARTSYS;
 }
 ......
}

 

wait_event_interruptible和wake_up_interruptible小例子:

#include
#include
#include
#include
#include
#include

unsigned int globalvar = 0;
wait_queue_head_t myqueue;
unsigned int flag = 0;

int myread(struct file *fl, char *buf, size_t size,loff_t *loff)
{
    wait_event_interruptible(myqueue, flag != 0);
    if(copy_to_user(buf,&globalvar,sizeof(int)))
    {
    printk("copy to user failed/n");
    return -EFAULT;
    }
    flag = 0;
    return sizeof(int);
}

int mywrite(struct file *fl, char *buf, size_t size, loff_t *loff)
{
    if(copy_from_user(&globalvar, buf,sizeof(int)))
    {
    printk("copy from user failed/n");
    return -EFAULT;
    }
    wake_up_interruptible(&myqueue);
    flag = 1;
    return sizeof(int);
}

static const struct file_operations fops = {
    .read  = myread,
    .write = mywrite
};

static int mod_init()
{
    int ret;
    ret = register_chrdev(133, "mychar", &fops);
    if(ret < 0)
        printk("<0>""register char dev failed/n");
    init_waitqueue_head(&myqueue);
    return 0;
}

static void mod_exit()
{
    unregister_chrdev(133,"mychar");
}

module_init(mod_init);
module_exit(mod_exit);

 

这个东西作用就是一边没wake_up_interruptible和改变flag标志时, 那么另一边就等在wait_event_interruptible。和completion的区别不知道,因为就是这里边也有调度schedule,可以让出处理器,completion里也有调度。

 

http://blog.163.com/allegro_tyc/blog/static/33743768201172102952575/

http://blog.csdn.net/unbutun/article/details/4972656

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有