copy_to_user() 无限打印消息
copy_to_user() keeps printing message infinitely
我正在学习"Linux device drivers"。我创建了一个名为 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;
}
用于读取设备的用户space命令:
cat /dev/char_device
驱动程序不断打印“来自内核世界的你好!”消息到终端。
cat
等程序将读取当前输入文件,直到遇到文件结束条件或读取错误。按照惯例,当请求非零数据量时,read()
return 值为 0 表示文件结束条件。 -1
的 return 值表示读取错误,错误编号在 errno
变量中。
在内核级别,read
文件操作处理程序应该 return 0 以指示文件结束条件(但也可以在请求的数量为 0 时这样做),并且应该 return 取反 errno
值以指示读取错误。
OP 的当前 read
文件操作处理程序,my_read
,将字符串文字的内容,"Hello from the kernel world!\n"
,复制到用户内存缓冲区,限制为请求的读取数量或字符串的长度,以最小者为准。它永远不会 returns 文件结束条件。唯一一次 returns 0 是当请求的数量为 0 时,但这不是有效的文件结束条件。
my_read
可以做的一件事是使用传入的文件位置信息来确定从哪里开始读取,并限制要复制的数量。它应该相应地更新位置。然后它可以 return 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
停止的地方开始,例如:
- 读取 10,return10(
'H'
,'e'
,'l'
,'l'
,'o'
,' '
, 'f'
, 'r'
, 'o'
, 'm'
)
- 阅读 10,return10(
' '
,'t'
,'h'
,'e'
,' '
,'k'
, 'e'
, 'r'
. 'n'
, 'e'
)
- 阅读 10,return9(
'l'
,' '
,'w'
,'o'
,'r'
,'l'
, 'd'
, '!'
, '\n'
)
- 读取 10,return0(文件结束)
我正在学习"Linux device drivers"。我创建了一个名为 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;
}
用于读取设备的用户space命令:
cat /dev/char_device
驱动程序不断打印“来自内核世界的你好!”消息到终端。
cat
等程序将读取当前输入文件,直到遇到文件结束条件或读取错误。按照惯例,当请求非零数据量时,read()
return 值为 0 表示文件结束条件。 -1
的 return 值表示读取错误,错误编号在 errno
变量中。
在内核级别,read
文件操作处理程序应该 return 0 以指示文件结束条件(但也可以在请求的数量为 0 时这样做),并且应该 return 取反 errno
值以指示读取错误。
OP 的当前 read
文件操作处理程序,my_read
,将字符串文字的内容,"Hello from the kernel world!\n"
,复制到用户内存缓冲区,限制为请求的读取数量或字符串的长度,以最小者为准。它永远不会 returns 文件结束条件。唯一一次 returns 0 是当请求的数量为 0 时,但这不是有效的文件结束条件。
my_read
可以做的一件事是使用传入的文件位置信息来确定从哪里开始读取,并限制要复制的数量。它应该相应地更新位置。然后它可以 return 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
停止的地方开始,例如:
- 读取 10,return10(
'H'
,'e'
,'l'
,'l'
,'o'
,' '
,'f'
,'r'
,'o'
,'m'
) - 阅读 10,return10(
' '
,'t'
,'h'
,'e'
,' '
,'k'
,'e'
,'r'
.'n'
,'e'
) - 阅读 10,return9(
'l'
,' '
,'w'
,'o'
,'r'
,'l'
,'d'
,'!'
,'\n'
) - 读取 10,return0(文件结束)