【发布时间】:2018-04-30 19:23:18
【问题描述】:
我正在为一些新颖的硬件实现设备驱动程序,并且希望一次只允许一个进程访问该设备。并发读/写操作会使硬件混淆,以至于很可能需要进行硬重置。我还有以下问题:
在示例代码 from Linux Device Drivers 中,
open()调用使用锁,但close()没有。这里是否仍然存在竞争条件,或者scull_s_count的减量保证是原子的?基本上,在这个例子中,我想知道如果一个进程试图打开设备,而另一个进程正在结束并关闭它会发生什么。我假设我不需要在我的
read()和write()调用中检查我的打开标志的状态(我正在做类似于示例的scull_s_count),因为进入这些调用的唯一方法是用户空间应用程序已经通过成功调用open()接收到fd。这个假设正确吗?
感谢 tadman 的 cmets,我对内核的 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 的答案。
示例代码使用自旋锁,但互斥锁是否更合适?这部分代码相对较小,几乎没有争用,因此进入睡眠和唤醒可能比仅仅旋转的性能更低。锁/互斥锁总是从用户上下文访问,所以你应该可以安全地睡觉。
【问题讨论】:
-
如果你有一个原子标志,你就不会有竞争条件。
-
是否有 POSIX 原子标志?我知道 C++11 中的 std::atomic_flag,但这是一个用 C 编写的 Linux 设备驱动程序。
-
即使粗略搜索内核中的原子操作也会得到results like this。
-
谢谢。现在将我的标志转换为 atomic_t。稍后将在此处发布示例代码。
-
@tadman,如果你有时间,看看我更新的问题。感谢您的帮助。
标签: c linux linux-kernel linux-device-driver