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

时间:2022-05-04
本文章向大家介绍【专业技术】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;
}

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