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();
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 ;
}
打开之后,关闭驱动文件,就需要释放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 ;
}
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驱动编写之进程独占驱动的更多相关文章
- Linux驱动编写(块设备驱动代码)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 按照ldd的说法,linux的设备驱动包括了char,block,net三种设备.char设备 ...
- linux驱动编写(电源管理驱动)
对于嵌入式设备来说,合适的电源管理,不仅可以延长电池的寿命,而且可以省电,延长设备运行时间,在提高用户体验方面有很大的好处.所以,各个soc厂家在这方面花了很多的功夫.下面,我们可以看看linux是如 ...
- v4l2驱动编写篇【转】
转自:http://blog.csdn.net/michaelcao1980/article/details/53008418 大部分所需的信息都在这里.作为一个驱动作者,当挖掘头文件的时候,你可能也 ...
- Linux驱动之按键驱动编写(中断方式)
在Linux驱动之按键驱动编写(查询方式)已经写了一个查询方式的按键驱动,但是查询方式太占用CPU,接下来利用中断方式编写一个驱动程序,使得CPU占有率降低,在按键空闲时调用read系统调用的进程可以 ...
- linux驱动学习笔记---实现中断下半部以及驱动编写规范(七)【转】
转自:https://blog.csdn.net/weixin_42471952/article/details/81609141 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协 ...
- Linux I2C设备驱动编写(一)
在Linux驱动中I2C系统中主要包含以下几个成员: I2C adapter 即I2C适配器 I2C driver 某个I2C设备的设备驱动,可以以driver理解. I2C client 某个I2C ...
- 【转】Linux I2C设备驱动编写(一)
原文网址:http://www.cnblogs.com/biglucky/p/4059576.html 在Linux驱动中I2C系统中主要包含以下几个成员: I2C adapter 即I2C适配器 I ...
- Linux驱动之按键驱动编写(查询方式)
在Linux驱动之LED驱动编写已经详细介绍了一个驱动的编写过程,接着来写一个按键驱动程序,主要是在file_operations结构中添加了一个read函数.还是分以下几步说明 1.查看原理图,确定 ...
- Linux驱动之LED驱动编写
从上到下,一个软件系统可以分为:应用程序.操作系统(内核).驱动程序.结构图如下:我们需要做的就是写出open.read.write等驱动层的函数.一个LED驱动的步骤如下: 1.查看原理图,确定需要 ...
随机推荐
- 【读书笔记】iOS-多点触摸事件与界面几何
边缘与中心检测: CGRectGetMinX 返回矩形左边缘的坐标. CGRectGetMinY 返回矩形底部边缘的坐标. CGRectGetMidX 返回矩形中心的x坐标. CGRectGetMid ...
- 转: Laravel 自定义公共函数的引入
来源:Laravel 自定义公共函数的引入 背景习惯了 使用 ThinkPHP 框架,有一个公共方法类在代码编写上会快捷很多,所以有必要在此进行配置一番.测试框架:Laravel 5.5步骤指导1. ...
- 超级干货 :一文读懂数据可视化 ZT
前言 数据可视化,是指将相对晦涩的的数据通过可视的.交互的方式进行展示,从而形象.直观地表达数据蕴含的信息和规律. 早期的数据可视化作为咨询机构.金融企业的专业工具,其应用领域较为单一,应用形态较为保 ...
- 安卓开发_浅谈主配置文件(AndroidManifest.xml)
AndroidManifest.xml本质:是整个应用的主配置清单文件包含:该应用的包名,版本号,组件,权限等信息作用:记录该应用的相关的配置信息 一.常用标签(1).全局篇(包名,版本信息)(2). ...
- MQTT详解以及在IoT中的应用
MQTT定义: MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协议支持所有平台, ...
- (网页)Angular.js 中 copy 赋值与 = 赋值 区别
转自st.gg Angular.js 中 copy 赋值与 = 赋值 区别 为什么用 $scope.user = $scope.master; $scope.master 会跟着 $scope.use ...
- Maven 安装 on centos7
本文演示如何在CentOS7上安装maven. 1 准备工作 1.1 进入官网下载栏目 http://maven.apache.org/download.cgi 找到下载列表中 Binary tar. ...
- linux设置自动更换壁纸
#!/bin/bash let n=0 files=($HOME/wallpapers/*.jpg) count=${#files[@]} while [ 1 ] do let "n=n%$ ...
- Sql Server 增加字段、修改字段、修改类型、修改默认值
1.修改字段名: alter table 表名 rename column A to B 2.修改字段类型: alter table 表名 alter column 字段名 type not null ...
- DMZ 区域
下面对DMZ区域进行简要介绍:DMZ是网络的一个区域,介于外网与内网之间的一个特殊区域,也称隔离区.它不同于传统的防火墙设置,DMZ防火墙方案为要保护的内部网络增加了一道安全防线,通常认为是非常安全的 ...