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(文件结束)