【发布时间】:2016-04-05 04:32:25
【问题描述】:
我正在学习 linux 设备驱动程序。我遇到了一个主题“手动睡眠”。所以我写了一个简单的char驱动,如果没有数据写入缓冲区,read方法会休眠
问题是即使数据已经写入,read 方法也会永远休眠
代码中可能出现的错误是什么? 提前感谢您的帮助。
char 驱动程序的代码 sn-ps 是
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;
}
【问题讨论】:
-
“用户空间应用程序的完整代码”甚至无法完全编译。编译时,始终启用所有警告,然后修复这些警告。 (对于 gcc,至少使用:
-Wall -Wextra -pedantic。我通常还会添加:-std-c99 -Wconversion)然后修复生成的警告。首先,在使用操作系统时,main() 函数只有 2 个有效(和一个可选)签名,它们的返回类型均为int -
cont:代码缺少定义
memset()、open()、printf()、scanf()、write()、read()、strlen()所需的#include 语句并且由于调用了open(),因此应该有一个对close()的匹配调用,但缺少代码。 -
在调用
open()函数时,一定要检查返回值,确保操作成功。调用scanf()函数时,始终检查返回值以确保操作成功。调用read()函数时,一定要检查返回值,确保操作成功。 -
这些头文件只是原型所必需的,而原型对于 scanf、printf、memset 和所有这些都是必需的......我可以用警告而不是错误来编译它们......可执行文件总是有效的很好...为什么要包含不必要的头文件来增加程序大小
-
发布的代码包含一些“神奇”数字。 “神奇”数字使代码难以理解、调试和维护。 “神奇”数字包括
100。建议使用#define 为“魔术”数字赋予有意义的名称,然后在整个代码中使用该有意义的名称。
标签: c linux linux-kernel operating-system kernel-module