我正在学习“ 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: Read\n");
if(copy_to_user(buf, message, len)) {
return -EFAULT;
}
*off += len;
return len;
}
行为上的一个变化是,连续读取的长度为10的读取量(例如)将从先前read
中断的位置开始读取,例如:
'H'
,'e'
,'l'
,'l'
,'o'
,' '
,'f'
,'r'
,)'o'
'm'
' '
,'t'
,'h'
,'e'
,' '
,'k'
,'e'
,'r'
,)'n'
'e'
'l'
,' '
,'w'
,'o'
,'r'
,'l'
,'d'
,)'!'
'\n'
谢谢您的帮助。但是,当我将返回值更改为0
return 0;
而不是问题return len;
中发布的代码时,它在终端中不显示任何内容。帮助我理解这一点。@Vivek返回值指示已读取多少,因此返回0指示未读取任何内容。它还指示文件结束条件。