copy_to_user()不断地打印消息
我正在学习“Linux 设备驱动程序”。我创建了一个名为char_device. 当我从设备读取数据时,它不断将消息打印到终端,使机器无限崩溃。
驱动中读操作的源码:
static ssize_t my_read(struct file *my_file, char __user *buf, size_t len, loff_t *off) {
uint8_t *message = "Hello from the kernel world!n";
size_t datalen = strlen(message);
if(len > datalen) {
len = datalen;
}
printk(KERN_INFO "Char driver: Read");
if(copy_to_user(buf, message, len)) {
return -EFAULT;
}
return len;
}
用于读取设备的用户空间命令:
cat /dev/char_device
驱动程序不断打印“来自内核世界的你好!” 到终端的消息。
回答
诸如此类的程序cat将读取当前输入文件,直到遇到文件结束条件或读取错误。按照惯例,read()当请求非零数据量时,返回值 0 表示文件结束条件。返回值-1表示读取错误,错误编号在errno变量中。
在内核级别,read文件操作处理程序应返回 0 以指示文件结束条件(但也可能在请求的数量为 0 时这样做),并应返回否定errno值以指示读取错误。
OP 的当前read文件操作处理程序my_read将字符串文字 的内容复制"Hello from the kernel world!n"到用户内存缓冲区,限制为请求的读取量或字符串的长度,以最小者为准。它从不返回文件结束条件。它返回 0 的唯一时间是请求的数量为 0 时,但这不是有效的文件结束条件。
my_read可以做的一件事是使用传入的文件位置信息来确定从哪里开始读取,并限制要复制的数量。它应该相应地更新位置。然后当没有更多数据要复制时,它可以返回 0 以指示文件结束。这是一个可能的实现:
static ssize_t my_read(struct file *my_file, char __user *buf, size_t len, loff_t *off) {
char *message = "Hello from the kernel world!n";
size_t datalen = strlen(message);
if (*off >= datalen) {
return 0; /* end of file */
}
if(len > datalen - *off) {
len = datalen - *off;
}
printk(KERN_INFO "Char driver: Readn");
if(copy_to_user(buf, message, len)) {
return -EFAULT;
}
*off += len;
return len;
}
行为的一个变化是长度为 10(例如)的连续读取量将从前一个read停止的位置开始,例如:
- 读取 10,返回 10 (
'H','e','l','l','o',' ','f','r','o','m') - 读取 10,返回 10 (
' ','t','h','e',' ','k','e','r'.'n','e') - 读取 10,返回 9 (
'l',' ','w','o','r','l','d','!','n') - 读取 10,返回 0(文件结束)