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

为什么从一个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. 如果给你一个缓冲区的长度,你需要使用它。如果提供的缓冲区小于内核缓冲区,则不会希望在其他用户空间内存上跺脚。
  2. 您需要返回复制到缓冲区的字节数。您的逐字符代码返回1,但您的复制整个缓冲区的代码在成功情况下总是返回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); 
} 
+0

就我而言,我得到了长度的随机值,我想这是内核的特权。但我有一个问题。在单字符函数中,完成时返回'0',但这里返回实际长度。我应该*什么*实际*返回?字符复制功能正常工作。 – user1343318

+1

写入到提供的缓冲区的字节数。但是,如果您获得“随机”长度的值,那么您必须在未显示的代码中某处出错。 –

+0

请参阅答案的结尾,了解可能的正确方法:使用内置函数执行您正在尝试执行的操作。 –