zoukankan      html  css  js  c++  java
  • linux驱动编写之进程独占驱动

    一、描述

          嵌入式开发系统中,有各种硬件资源,而有些硬件资源使用时候是需要进程独占的。也就是说,同一时刻只有一个进程允许使用这个硬件资源,其他的进程只能放弃执行或者挂起等待。在设计其对应驱动的时候,就需要做独占处理。

    example: 

          led灯驱动,4盏LED灯,在open的时候调用驱动,对其引脚进行配置。如果没有进程独占驱动的处理机制,效果如下:

          根据测试结果可以得到结论,调用了4次应用程序led_test,每一次调用open("/dev/leds", 0),都返回了一个/dev/leds的fd,fd是相同的,都是3。应用程序led_test的4次运行,都成功得到了执行,进程pid号分别为680、681、682、683。当调用open("/dev/leds", 0)时候,对应的就会调用驱动的leds_open函数,然后进行4次初始化。

          所以要实现只有一个进程使用该leds驱动,就需要在驱动模块的leds_open函数动手脚,具体实现方法如下。

    二、原子操作

    1、定义一个全局原子变量

    static atomic_t open_ability = ATOMIC_INIT(1);

    2、修改drivers_open函数

    static int drivers_open(struct inode *inode, struct file *file)
    {    
        if (!atomic_dec_and_test(&open_ability))
        {
            atomic_inc(&open_ability);
            return -EBUSY;
        }
            ............
    }

          如果是第一次打开或者处于关闭之后未打开状态,那么可以打开,if判断为false,执行之后的open代码段;如果已经打开了,就不能打开,返回-EBUSY.

    3、修改drivers_close函数

    int drivers_close(struct inode *inode, struct file *file)
    {
        atomic_inc(&open_ability);
            ............      
        return 0;
    }

          打开之后,关闭驱动文件,就需要释放open_ability.

    4、实现思路总结

          通过引入一个变量open_ability,为硬件驱动设计一个锁,只允许一个进程对其独占;当进程使用完驱动之后,就可以释放这个资源,以提供给其他应用程序来使用。

    5、测试效果

          可以看到第一次打开驱动成功,但是第二次打开驱动失败了。而且,这种方法实现的效果是,直接由驱动程序返回打开失败的消息-EBUSY.

     三、信号量--互斥锁

    1、定义一个互斥锁,并将互斥锁初始值设为1

    static DECLARE_MUTEX(leds_lock);  //利用宏来实现定义,并初始化

    2、修改drivers_open函数

    static int drivers_open(struct inode *inode, struct file *file)
    {    
            /* 获取信号量,如果没有获得,那么就进入睡眠状态 */
            down(&leds_lock);
            ............
    }    

    3、修改drivers_close函数

    int drivers_close(struct inode *inode, struct file *file)
    {
        ............
        up(&leds_lock);      
        return 0;
    }

    4、实现思路总结

          利用互斥锁,来实现对硬件驱动的独占,显然是很适合的,因为互斥锁设计的初衷就是来解决这类问题。

    5、测试效果

          可以看到第一次成功打开了驱动,第二次进入了不可中断的休眠状态。也就是说,当pid号645的应用程序led_test调用调用open("/dev/leds", 0)时候,驱动程序中的down(leds_lock)令进程进入了不可中断的休眠状态,直到第一次运行pid号644的应用程序led_test释放互斥锁,才能够重新得到运行。

          备注:STAT一栏中的,S代表“休眠状态”;D代表“不可中断的休眠状态”。

    6、与原子操作实现的区别

          原子操作,当第二次打开驱动文件的时候,直接返回-EBUSY,也就是说是非阻塞的;而互斥锁的这种方法,当第二次打开驱动文件的时候,由驱动程序中的down()函数迫使进程进入不可中断的休眠状态,可以说是阻塞的。

          不过,如果将down()函数换成down_trylock()函数,实现的效果也是非阻塞的。

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

                  linux中原子操作实现方式

  • 相关阅读:
    Elasticsearch重要文章之四:监控每个节点(ThreadPool部分)
    [翻译]Elasticsearch重要文章之四:监控每个节点(jvm部分)
    IDFA
    Python中eval函数的作用
    Android开发重点难点:RelativeLayout(相对布局)详解
    布局相关
    Nginx配置proxy_pass
    Docker部署Elasticsearch集群
    extends Thread 与 implements Runnable 的区别
    玩转 Redis缓存 集群高可用
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/6909025.html
Copyright © 2011-2022 走看看