我正在开发基于字符设备驱动程序的示例Linux模块(使用misc驱动程序以方便使用),我发现了一些不寻常的行为。
我有文件操作的打开,读取,写入和释放功能,我的misc设备名为test_device
我的设备有一个环形缓冲区,可以存储来自写入系统调用的数据,而读取系统调用可以读取数据。如果缓冲区已满,则调用write系统调用的进程将休眠,如果缓冲区为空,则调用read系统调用的进程将休眠。
有一个信号量(计数1,如互斥量),以避免多次读取,从而避免竞争条件。这对单个读取和单个写入过程没有任何问题,效果很好
现在我使用命令
打开设备作为2个读取实例cat /dev/test_device
正如预期的那样,第二个猫进程会睡觉。我有一个编写过程
ls > /dev/test_device
ls命令甚至不会调用open系统调用。任何人都可以向我解释开放系统调用失败的原因。
代码列在下面
static int hr_open(struct inode *inode, struct file *file)
{
pr_info("process %i (%s) enters open\n", current->pid, current->comm);
if (file->f_mode & FMODE_READ) down_interruptible(&rd_sem);
pr_info("process %i (%s) leaves open\n", current->pid, current->comm);
return 0;
}
static int hr_release(struct inode *inode, struct file *file)
{
pr_info("process %i (%s) enters release\n", current->pid, current->comm);
if (file->f_mode & FMODE_READ) up(&rd_sem);
pr_info("process %i (%s) leaves release\n", current->pid, current->comm);
return 0;
}
static ssize_t hr_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
pr_info("process %i (%s) enters read\n", current->pid, current->comm);
if (wait_event_interruptible(wq_rd, head != tail))
return -ERESTARTSYS;
if (put_user(buff[head], buffer))
return -EFAULT;
head = (head + 1) % BUFF_SIZE;
wake_up_interruptible(&wq_wr);
pr_info("process %i (%s) leaves read\n", current->pid, current->comm);
return 1;
}
static ssize_t hr_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
pr_info("process %i (%s) enters write\n", current->pid, current->comm);
if (wait_event_interruptible(wq_wr, tail != ((head + 1) % BUFF_SIZE)))
return -ERESTARTSYS;
if (get_user(buff[tail], buffer))
return -EFAULT;
tail = (tail + 1) % BUFF_SIZE;
wake_up_interruptible(&wq_rd);
pr_info("process %i (%s) leaves write\n", current->pid, current->comm);
return 1;
}
答案 0 :(得分:0)
我在你的代码中注意到你将信号量锁打开并在发布功能中释放它。我通常不建议在一个函数中持一个锁并释放另一个函数,因为它可能导致锁定问题或死锁。
static int hr_open(struct inode *inode, struct file *file)
{
...
if (file->f_mode & FMODE_READ) down_interruptible(&rd_sem);
...
}
static int hr_release(struct inode *inode, struct file *file)
{
...
if (file->f_mode & FMODE_READ) up(&rd_sem);
...
}
我的建议是在读写功能中移动信号量锁(向下和向上)。