• linux驱动编写之阻塞与非阻塞


    一、概念

          应用程序使用API接口,如open、read等来最终操作驱动,有两种结果--成功和失败。成功,很好处理,直接返回想要的结果;但是,失败,是继续等待,还是返回失败类型呢?  如果继续等待,将进程休眠,那么这类驱动设计就是阻塞式的;如果不等待,返回失败的类型(原因),那么这类驱动的设计就是非阻塞式的。

          在应用程序打开驱动文件的时候,可以通过参数向驱动传递使用驱动的方式(阻塞或者非阻塞),通过flags这个参数来传递。当flags中包含“O_NONBLOCK”,就是非阻塞,否则就是阻塞式的。

    fd = open("/dev/xxx", O_RDWR | O_NONBLOCK);

    二、具体实现

          以按键驱动为例进行说明,主要是利用互斥锁功能来实现。

    1、实现open函数的阻塞非阻塞功能

    static DECLARE_MUTEX(buttons_lock); 
    
    static int buttons_open(struct inode *inode, struct file *file)
    {    
        if (file->f_flags & O_NONBLOCK)
        {
            if (down_trylock(&buttons_lock))
            return -EBUSY;
        }
        else
        {
            down(&buttons_lock);
        }
        ............
        return 0;
    }            

          open()函数的目的是打开驱动文件/dev/buttons,而通常驱动文件允许打开的进程数量是有限制的,本例中是独占式的,所以需要利用互斥锁。函数down_trylock()和函数down(),分别具有非阻塞和阻塞的特性,所以利用这种特性,很容易实现open()函数的需求。

          注意在buttons_close()函数,不要忘记调用up(&buttons_lock)把互斥锁释放。

    2、实现read函数的阻塞非阻塞功能

    static int buttons_read(struct file *filp, char __user *buff, 
                                             size_t count, loff_t *offp)
    {
        unsigned long err;
        
        if (filp->f_flags & O_NONBLOCK)
        {
            if(0 == ev_press)
            {
                return -EAGAIN;
            }
        }
        else
        {
            /* 如果没有按键动作, 休眠 */
            wait_event_interruptible(button_waitq, ev_press);
        }
    
        /* 执行到这里时,ev_press等于1,将它清0 */
        ev_press = 0;
    
        /* 将按键状态复制给用户,并清0 */
        err = copy_to_user(buff, &keys_val, count);
    
        return err ? -EFAULT : 0;
    }

          read()函数的目的是来读取/dev/buttons文件,所收到的按键键值。当被按下,中断程序令ev_press置1,读取完之后清0。

          显然,如果已经被按下,已经存入了键值,那么read函数很容易成功返回。但是,如果没有按键按下,这个时候阻塞的处理就是继续等待,将进程休眠;而非阻塞则是返回-EAGAIN,重新来读。

    参考资料:韦东山linux教学视频

  • 相关阅读:
    由一个表更新另一个表中field
    DevExpress控件XtraGrid显示问题,分组不好用
    20090522: IBM X22
    DevExpress的GridControl选择一行,不显示单元格焦点的设置
    DataTable添加行的方法
    DevExpress自定义XtraGrid列菜单
    一道面试题
    DevExpress 设置LookUpEdit的值
    解决端口占用问题
    NoSQL
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/6913376.html
Copyright © 2020-2023  润新知