【专业技术】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 条评论
登录 后参与评论

相关文章

来自专栏Java架构师历程

3、进程间通信

本书主要介绍如何使用微服务架构构建应用程序,这是本书的第三章。第一章介绍了微服务架构模式,将其与单体架构模式进行对比,并讨论了使用微服务的优点与缺点。第二章描述...

1192
来自专栏我叫刘半仙

SpringBoot+JWT+Shiro+MybatisPlus实现Restful快速开发后端脚手架

前后端分离已经成为互联网项目开发标准,它会为以后的大型分布式架构打下基础。SpringBoot使编码配置部署都变得简单,越来越多的互联网公司已经选择Spring...

1.3K13
来自专栏Zephery

谈谈个人网站的建立(六)—— 数据库同步

先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地: ? 由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spri...

4795
来自专栏24k

SpringBoot项目使用JRebel热部署

2444
来自专栏FreeBuf

有趣的安全实验:利用多线程资源竞争技术上传shell

通过多线程资源竞争的手段同时上传两个头像,就可以在Apache+Rails环境下实现远程代码执行。这并不是天方夜谭,同时我相信许多文件上传系统都会有这个漏洞……...

2595
来自专栏我叫刘半仙

SpringBoot+JWT+Shiro+MybatisPlus实现Restful快速开发后端脚手架

1K3
来自专栏蜉蝣禅修之道

oracle用户类型区别

1973
来自专栏JAVA高级架构

程序猿的日常——SpringMVC系统架构与流程回顾

web开发经历了很漫长的时间,在国内也快有十几年的时间了。从最开始的进程级到现在的MVC经历了很多的改进和优化,本篇就主要复习了解下Spring MVC相关的知...

3575
来自专栏架构技术

【转】如何将MySQL数据目录更改为CentOS 7上的新位置

数据库随着时间的推移而增长,有时超过了文件系统的空间。当它们与操作系统的其他部分位于同一分区上时,也可能遇到I / O争用。RAID,网络块存储和其他设备可以提...

1073
来自专栏Web 开发

Ubuntu12.04快速部署 Nginx + MySQL + PHP + Memcached + XCache + phpMyAdmin

#装好后,配置文件都在/etc/nginx/目录下面,网站目录在/usr/share/nginx/www/下面

1210

扫码关注云+社区

领取腾讯云代金券