为什么从一个linux模块读取字符而不是整个字符串
问题描述:
我有我的内核模块的读取功能如下。它只是从内核缓冲区中读取一个字符并将其复制到用户缓冲区中。 一旦我到达内核缓冲区的末尾,我返回0.这完美地工作。为什么从一个linux模块读取字符而不是整个字符串
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] == '\0')
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\0", 65536) = 13
write(1, "s03324135655\0", 13) = 13
read(3, "", 65536) = 0
这是为什么?是否因为我们必须一旦我们完成reading
从模块返回0?第二个系统调用有一个空字符串,基本上规定没有什么可读的,我们应该返回零。
答
- 如果给你一个缓冲区的长度,你需要使用它。如果提供的缓冲区小于内核缓冲区,则不会希望在其他用户空间内存上跺脚。
- 您需要返回复制到缓冲区的字节数。您的逐字符代码返回
1
,但您的复制整个缓冲区的代码在成功情况下总是返回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);
}
就我而言,我得到了长度的随机值,我想这是内核的特权。但我有一个问题。在单字符函数中,完成时返回'0',但这里返回实际长度。我应该*什么*实际*返回?字符复制功能正常工作。 – user1343318
写入到提供的缓冲区的字节数。但是,如果您获得“随机”长度的值,那么您必须在未显示的代码中某处出错。 –
请参阅答案的结尾,了解可能的正确方法:使用内置函数执行您正在尝试执行的操作。 –