为什么从 linux 模块读取一个字符一个字符而不是整个字符串

Why reading from a linux module works character by character but not for whole string

我的内核模块的读取函数如下。它只是从内核缓冲区中读取一个字符并将其复制到用户缓冲区中。 一旦到达内核缓冲区的末尾,我 return 0。这非常有效。

static ssize_t debugfs_read(struct file *f, char __user *buf,
    size_t length, loff_t *offset)
{
    ssize_t rc = 0;

    pr_info("%s.\n", "In read");

    rc = copy_to_user(buf, &kbuffer[*offset], 1);



    if (rc < 0)
        return -EFAULT;

    if (kbuffer[*offset] == '[=11=]')
        return 0;

    *offset = *offset + 1;

    return 1;
}

现在如果我尝试将整个内核缓冲区一次性复制到用户缓冲区中, 该模块不打印任何内容。

这是为什么呢?本例代码:

static ssize_t debugfs_read(struct file *f, char __user *buf,
    size_t length, loff_t *offset)
{
    ssize_t rc = 0;

    pr_info("%s.\n", "In read");

    rc = copy_to_user(buf, &kbuffer, BUFF_LEN);


    if (rc != 0)
        return -EFAULT;

    return 0;
}

编辑:

在使用已接受答案的解决方案时,我意识到 read 被内核调用了两次。这里是 strace:

read(3, "s03324135655[=13=]", 65536)        = 13
write(1, "s03324135655[=13=]", 13)          = 13
read(3, "", 65536)                      = 0

这是为什么?是因为我们 必须 return 0 一旦我们从一个模块完成 reading 吗?第二个系统调用有一个空字符串,基本上规定没有任何内容可读,我们应该 return 零。

  1. 如果给定一个带缓冲区的长度,你需要使用它。如果提供的缓冲区小于您的内核缓冲区,您不会想踩踏其他用户-space 内存。
  2. 您需要 return 您复制到缓冲区的字节数。您的逐字符代码 returned 1,但是您复制整个缓冲区的代码在成功的情况下总是 returned 0,这告诉调用者您写了0 字节到缓冲区。
  3. 您还需要考虑偏移参数。

因此,与其自己实现所有这些逻辑,不如使用 simple_read_from_buffer,它会为您完成此操作:

static ssize_t debugfs_read(struct file *f, char __user *buf,
    size_t length, loff_t *offset)
{
    return simple_read_from_buffer(buf, length, offset, &kbuffer, BUFF_LEN);
}