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

摘要:
如果您继续等待并休眠进程,则驱动程序设计将被阻塞;如果在没有等待的情况下返回失败类型(原因),则这种类型的驱动程序的设计是非阻塞的。当应用程序打开驱动程序文件时,您可以使用驱动程序的方式将参数传递给驱动程序,并传递参数标志。当标志包含“O_NONBLOCK”时,它是非阻塞的,否则它是阻塞的。函数down _ Trylock()和函数down()分别具有非阻塞和阻塞的特性,因此利用这个特性很容易实现open()函数的要求。

一、概念

      应用程序使用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教学视频

免责声明:文章转载自《linux驱动编写之阻塞与非阻塞》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇layui中,同一个页面动态加载table数据表格Delphi程序的自我修改下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

linux proc文件系统学习 (转)

目录: /proc --- 一个虚拟文件系统 加载 proc 文件系统 察看 /proc 的文件 得到有用的系统/内核信息 有关运行中的进程的信息 通过 /proc 与内核交互 结论 参考文献 摘要: Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。尽管在各种硬件平台上的 Linux 系...

Linux学习3-yum安装java和Tomcat环境

前言 linux上安装软件,可以用yum非常方便,不需要下载解压,一个指令就能用yum安装java和tomcat环境。 前面一篇已经实现在阿里云服务器上搭建一个禅道系统的网站,算是小有成就,但并不是每个网站搭建都是这么简单的。 一般开发包是一个.war的文件,这就需要用到一个中间键,比如tomcat了,tomcat又是依赖于java环境的,所以先安装jav...

parallel desktop ubuntu从18.04更新到20.04(包括安装Parallels Tools)

ubuntu是怎么更新到20.04的 只说正确的步骤(实际上不是这个顺序) 我之前用了清华镜像源, 修改了/etc/apt/sources.list, 需要把它改回原样, 这个链接就是原样. 做这一步的原因是(报错是), while scanning your repository information no entry about bionic co...

V3s录音 交叉编译alsa linux

1.下载alsa-lib和alsa-utils  www.alsa-project.org/main/index.php/Download 2.编译alsa-lib tar xvf alsa-lib-1.1.5.tar.bz2 #解压 sync cd alsa-lib-1.1.5/ MyDIR="/usr/local/alsa" ./configure...

Linux下查看硬盘UUID和修改硬盘UUID(转)

查看硬盘UUID: 1、 ls -l /dev/disk/by-uuid 2、 blkid /dev/sda5 修改硬盘UUID: 1、新建和改变分区的UUID sudo uuidgen | xargs tune2fs /dev/sda5 -U 2、将原有UUID写会到分区 tune2fs -U c1b9d5a2-f162-11cf-9ece-0020af...

ubuntu linux环境下安装配置jdk和tomcat

关于linux搭建服务器,ubuntu中jdk和tomcat的安装和配置 一.jdk的安装配置 1:去官网下载好自己需要的版本,注意,linux压缩文件通常以tar.gz结尾,别下载错了。本次我下载安装的版本为jdk7u25.             2:复制jdk到ubuntu下,我本次复制路径为/home/Documents/jdk-7u25-linu...