Linux设备驱动程序访问控制
我正在为一些新颖的硬件实现设备驱动程序,并希望一次只允许一个进程访问该设备.并发读/写操作会使硬件混淆到可能需要发生硬复位的程度.我还有以下问题:
>在示例代码from Linux Device Drivers中,open()调用使用锁,但close()不使用.这里是不是还有竞争条件,还是scull_s_count的减少保证是原子的?基本上,在这个例子中,我想知道如果一个进程试图在另一个进程正在收尾并关闭它时正确地打开设备会发生什么. 感谢tadman的评论,我对内核的atomic_t机制进行了粗略的搜索.这是我现在拥有的一些伪代码: int open(struct inode *inode,struct file *filp) { spin_lock(&lock); if (atomic_read(&open_flag)) { spin_unlock(&lock); return -EBUSY; } atomic_set(&open_flag,1); /* do other open() related stuff */ spin_unlock(&lock); return 0; } int close(struct inode *inode,struct file *filp) { int rc; /* do close() stuff */ atomic_set(&open_flag,0); return rc; } open_flag是一个atomic_t,它是使用kzalloc()分配的更大结构的一部分.结果,它被初始化为零. 因此,此处的代码显示锁的目的是防止多个进程/线程同时打开设备,而open_flag是atomic_t这一事实可以防止我在上面的问题1中关注的竞争条件.这种实现是否足够?此外,我仍在寻找问题2的答案. 示例代码使用自旋锁,但互斥锁会更合适吗?代码部分相对较小,几乎没有争用,所以进入睡眠和唤醒可能比仅仅旋转更少的性能.始终从用户上下文访问锁定/互斥锁,因此您应该安全地睡觉. 解决方法
你指出的例子确实存在缺陷.减量绝对不能保证是原子的,几乎肯定不会.
但实际上,我认为编译器/ CPU组合不会产生可能失败的代码.可能发生的最坏情况是一个CPU核心可以完成关闭,然后另一个核心可以调用open并恢复忙,因为它有一个陈旧的缓存值. Linux为此提供了atomic_ *函数以及* _bit原子位标志操作.请参阅内核文档中的core_api / atomic_ops.rst. 一个正确而简单的模式的例子就像是: unsigned long mydriver_flags; #define IN_USE_BIT 0 static int mydriver_open(struct inode *inode,struct file *filp) { if (test_and_set_bit(IN_USE_BIT,&mydriver_flags)) return -EBUSY; /* continue with open */ return 0; } static int mydriver_close(struct inode *inode,struct file *filp) { /* do close stuff first */ smp_mb__before_atomic(); clear_bit(IN_USE_BIT,&mydriver_flags); return 0; } 真正的驱动程序应该为每个设备配备一个设备状态结构,其中包含mydriver_flags.而不是像示例中所示的整个驱动程序使用单个全局. 那就是说,你想要做的可能不是一个好主意.即使一次只有一个进程可以打开设备,进程的打开文件描述符也会在进程中的所有线程之间共享.多个线程可以同时对同一个文件描述符进行read()和write()调用. 如果进程打开文件描述符并调用fork(),则该描述符将继承到新进程中.这是多个进程可以让设备一次打开的方式,尽管有上述“单一开放”限制. 因此,您仍然必须在驱动程序的文件操作中保持线程安全,因为用户仍然可以让多个线程/进程同时打开设备并进行同时调用.如果你已经安全,为什么要阻止用户这样做呢?也许他们知道他们正在做什么,并确保他们的多个开启者将“轮流”并且不会拨打电话冲突? 还要考虑在open调用中使用O_EXCL标志来使单个打开可选的可能性. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |