【专业技术】Linux设备驱动第八篇:高级字符驱动操作之设备存取控制

上一篇中介绍了阻塞IO等的一些用法,本来这一篇准备介绍一下poll/select等的一些高级IO操作,后来想想,在实际工作中开发驱动的时候很少会使用到poll/select这些操作,就不再介绍,有兴趣的可以自己查找资料学习一下。这一篇会介绍下相对比较实用的设备文件的存取控制的一些内容。

存取控制主要用于设备的使用控制,只有授权的用户才能访问设备或者同时只有一个进程访问设备。这也是存取控制使用最广的地方。下面分别简单说明。

单open设备

单open设备就是同时只有一个进程允许打开一次所要访问的设备。此种方法是最简单方便的访问控制策略,可以防止多进程的竞争问题,但是这样也造成了其局限性。不能同时被多个进程多个用户访问。下面是一个单open设备的简单实现:

static atomic_t scull_s_available = ATOMIC_INIT(1);
static int scull_s_open(struct inode *inode, struct file *filp)
{

        struct scull_dev *dev = &scull_s_device; /* device information */
        if (! atomic_dec_and_test (&scull_s_available))
        {
                atomic_inc(&scull_s_available);
                return -EBUSY; /* already open */
        }

        /* then, everything else is copied from the bare scull device */
        if ( (filp->f_flags & O_ACCMODE) == O_WRONLY)

                scull_trim(dev);
        filp->private_data = dev;
        return 0; /* success */
}

这段代码维护一个 atiomic_t 变量,称为 scull_s_available;这个变量被初始化为值 1,表示设备确实可用。open 调用递减并测试 scull_s_available 并拒绝存取如果其他人已经使设备打开。

release调用,标识设备不再忙。

static int scull_s_release(struct inode *inode, struct file *filp)
{
        atomic_inc(&scull_s_available); /* release the device */
        return 0;
}

单用户多进程使用设备

这种方式更高级一些,可以允许单个用户的多个进程同时使用设备。这种方式在第一次打开设备是会记住设备拥有着,当下一次同一个用户打开设备时也会得到允许。在上面介绍的open实现中需要加入类似下面的代码:

spin_lock(&scull_u_lock);
if (scull_u_count &&
                (scull_u_owner != current->uid) && /* allow user */
                (scull_u_owner != current->euid) && /* allow whoever did su */
                !capable(CAP_DAC_OVERRIDE))
{ /* still allow root */
        spin_unlock(&scull_u_lock);
        return -EBUSY; /* -EPERM would confuse the user */
}

if (scull_u_count == 0)
        scull_u_owner = current->uid; /* grab it */

scull_u_count++;
spin_unlock(&scull_u_lock);

这里有几个注意点,scull_u_owner 和 scull_u_count来控制对设备的存取,并且可被多个进程并发地存取,为了使这俩个变量安全,使用自旋锁来控制。

返回-EBUSY而不是-EPERM,我们这种情况虽然看着是在检查权限,但如果返回-EPERM,用户一般会去检查设备节点的文件mode已经拥有着,这是一个错误的方向。所以返回设备忙更合理。

相应的release方法如下:

static int scull_u_release(struct inode *inode, struct file *filp)
{
        spin_lock(&scull_u_lock);
        scull_u_count--; /* nothing else */
        spin_unlock(&scull_u_lock);
        return 0;
}

以上就是设备存取控制最常用方法,还有一些不常用的点没有仔细介绍。有兴趣的可以自行了解,也欢迎随时交流。

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-08-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码农之路_构建基础

Linux 内核中 Kconfig 文件的作用和添加 menuconfig 项的方法

嵌入式开发中,需要定制或添加一些内核的功能。这里就需要配置 Kconfig 文件了。本文简单说明一下如何修改。便于需要时查找

1405
来自专栏北京马哥教育

Linux 运维必备的 13 款实用工具,拿好了~

本文介绍几款 Linux 运维比较实用的工具,希望对 Linux 运维人员有所帮助。 1. 查看进程占用带宽情况 - Nethogs Nethogs 是一个...

3208
来自专栏北京马哥教育

Zmap详细用户手册和DDOS的可行性

0x00 背景 Zmap是美国密歇根大学研究者开发出一款工具。在第22届USENIX安全研讨会,以超过nmap 1300倍的扫描速度声名鹊起。相比大名鼎鼎的nm...

31210
来自专栏惨绿少年

nginx服务部署 说明

第1章 常用的软件 1.1 常用来提供静态服务的软件 Apache :这是中小型Web服务的主流,Web服务器中的老大哥, Nginx :大型网站Web服务...

2950
来自专栏流柯技术学院

LR常见问题整理

  当一台主机上安装多个浏览器时,LoadRunner录制脚本经常遇到不能打开浏览器的情况,可以用下面的方法来解决。

994
来自专栏前端架构

细说OSI七层协议模型及OSI参考模型中的数据封装过程?

OSI模型,即开放式通信系统互联参考模型(Open System Interconnection,OSI/RM,Open Systems Interconnec...

892
来自专栏Android开发指南

genymotion常见问题解答

44410
来自专栏北京马哥教育

centos7.0体验与之前版本的不同

今天下午,没事干,在一台机器上装了一个centos7玩一玩,发现与之前版本有很大不同,不知道rhel7是不是也是这样,毕竟现在centos属于redhat了。 ...

2027
来自专栏抠抠空间

Node.js基础

1650
来自专栏lestat's blog

一个投票项目的总结

最近开发了一个只有3个页面的微信投票小项目 基本流程:一个微信号一天只能对一个参与者投一次票且一天总共可以对不同参与者投10次票 首页内容:展示所有投票参与者以...

2805

扫描关注云+社区