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中原子操作实现方式

  • 相关阅读:
    CodeForces 156B Suspects(枚举)
    CodeForces 156A Message(暴力)
    CodeForces 157B Trace
    CodeForces 157A Game Outcome
    HDU 3578 Greedy Tino(双塔DP)
    POJ 2609 Ferry Loading(双塔DP)
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛十六进制转换成十进制
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/6909025.html
Copyright © 2011-2022 走看看