我正在学习linux设备驱动程序。我遇到了一个话题“手动睡眠”。所以我写了一个简单的char驱动程序,如果没有数据写入缓冲区,read方法将会休眠
问题是即使已写入数据,read方法也会永远休眠
代码中可能出现的错误是什么? 提前感谢您的帮助。
来自char驱动程序的代码片段是
wait_queue_head_t q;
wait_queue_t wait;
int major_no, flag=0;
char device_buffer[100];
ssize_t myread(struct file *p, char __user *buf, size_t len, loff_t *s)
{
printk(KERN_ALERT "myread() method\n");
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
if(flag!=1)
{
schedule();
}
copy_to_user(buf, device_buffer, strlen(device_buffer));
flag=0;
return 0;
}
ssize_t mywrite(struct file *p, const char __user *buf, size_t len, loff_t *s)
{
printk(KERN_ALERT "mywrite() method\n");
memset(device_buffer, 0, 100);
copy_from_user(device_buffer, buf, len);
flag=1;
finish_wait(&q, &wait);
printk("%s", device_buffer);
return 0;
}
struct file_operations p={
.open=myopen,
.release=myclose,
.write=mywrite,
.read=myread
};
int start(void)
{
printk(KERN_ALERT "module registered\n");
memset(device_buffer, 0, 100);
major_no=register_chrdev(0, "mydriver", &p);
printk(KERN_ALERT "driver major no : %d\n", major_no);
init_waitqueue_head(&q);
init_wait(&wait);
return 0;
}
用户空间应用的完整代码是
#include<fcntl.h>
main()
{
char option, m[100];
memset(m, 0, 100);
int fd=open("my_dev_file", O_RDWR);
printf("%d\n", fd);
printf("read : r\nwrite : w\n");
scanf("%c", &option);
switch(option)
{
case 'w':
printf("msg : ");
scanf("%s", m);
write(fd, m, strlen(m));
break;
case 'r':
read(fd, m, 100);
printf("msg = %s\n", m);
break;
default:
printf("wrong choice\n");
}
return 0;
}
答案 0 :(得分:1)
函数prepare_to_wait
和finish_wait
是单个等待 的一部分。
他们不是 wait()
和notify()
高级语言的类似物,例如java。
更正确的等待实施可能是:
// Global scope: no need to declare `wait`, it will be locally declared in *myread*
// myread
DEFINE_WAIT(wait); // this is a *declaration*, so it should come before function's call like `printk`.
prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
if(flag!=1)
{
schedule();
}
finish_wait(&q, &wait); // This is *finalization* for waiting
...
// mywrite
flag = 1;
wake_up(&q);
请注意,这是不完全正确的示例:至少应该检查flag
并设置在某个关键部分下,例如用螺旋锁举行。但它只适用于您的简单场景。
或者,您可以使用完成:
// Global scope
#include <linux/completion.h>
DECLARE_COMPLETION(comp);
// myread
wait_for_completion_interruptible(&comp);
// mywrite
complete(&comp);
在这种情况下,完成将在等待后自动重新启动。