为什么从 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 零。
- 如果给定一个带缓冲区的长度,你需要使用它。如果提供的缓冲区小于您的内核缓冲区,您不会想踩踏其他用户-space 内存。
- 您需要 return 您复制到缓冲区的字节数。您的逐字符代码 returned
1
,但是您复制整个缓冲区的代码在成功的情况下总是 returned 0
,这告诉调用者您写了0
字节到缓冲区。
- 您还需要考虑偏移参数。
因此,与其自己实现所有这些逻辑,不如使用 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);
}
我的内核模块的读取函数如下。它只是从内核缓冲区中读取一个字符并将其复制到用户缓冲区中。 一旦到达内核缓冲区的末尾,我 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 零。
- 如果给定一个带缓冲区的长度,你需要使用它。如果提供的缓冲区小于您的内核缓冲区,您不会想踩踏其他用户-space 内存。
- 您需要 return 您复制到缓冲区的字节数。您的逐字符代码 returned
1
,但是您复制整个缓冲区的代码在成功的情况下总是 returned0
,这告诉调用者您写了0
字节到缓冲区。 - 您还需要考虑偏移参数。
因此,与其自己实现所有这些逻辑,不如使用 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);
}