如何在以下简单设备读取程序中使用“cat”

时间:2013-12-26 10:40:17

标签: c linux-device-driver

static ssize_t device_read (struct file* filp, char *bufStoreData, size_t bufCount, loff_t* curOffset)
{
    printk(KERN_INFO"reading from the device");
    ret = copy_to_user(bufStoreData,virtual_device.data,bufCount);
    return ret;
}
  1. copy_to_user是否返回剩余要读取的字节数或读取的字节数?

  2. 如果我使用cat

  3. ,是否使用了bufcount
  4. 如果所有数据都没有在单个调用中读取它如何读取剩余数据?应用程序的责任是再次发出系统调用还是驱动程序自动运行?

  5. 我需要了解这个基本概念。

2 个答案:

答案 0 :(得分:3)

copy_to_user()返回无法复制到用户空间的字节数。如果可以复制完整的缓冲区,则返回0.

通常情况下,如果!= 0,表示存在某种内存问题(写入合法的内存地址),因此应检测这些情况并报告给用户。

static ssize_t device_read (struct file* filp, char *bufStoreData, 
                            size_t bufCount, loff_t* curOffset)
{
  size_t bytes_to_copy;

  printk(KERN_INFO"reading from the device");

  /* do stuff to get device data into virtual_device.data . Also
     update virtual_device.datasize */

  bytes_to_copy = (virtual_device.datasize <= bufCount)? 
                             virtual_device.datasize : bufCount;
  /* note that I'm not using bufCount, but an hypothetical field in 
     virtual_device that gives me how much data the device has ready 
     for the user. I choose the lower of both */
  /* Also recall that if the number of bytes requested by the user is
     less than the number of bytes the device has generated, then the
     next read should return the remainder of the device data, so the
     driver should carry the count of how many bytes have been copied
     to the user and how many are left. This is not covered in this
     example. */

  ret = copy_to_user(bufStoreData,virtual_device.data, bytes_to_copy);
  if (ret != 0)
    return -EPERM; /* if copy was not successful, report it */
  return bytes_to_copy;
}

当用户发出ret = read (fd, buffer, sizebuff);时,它会发现其中一件事并应做出相应的反应:

  • ret等于sizebuff。这意味着read可以返回用户请求的所有数据。这里别无其他。

  • ret为正,但小于sizebuff。这意味着读取给了用户一些数据,但没有他要求的那么多。如果需要,用户进程必须重新发出read系统调用以检索剩余数据。例如:ret = read (fd, buffer+ret, sizebuff-ret);

  • ret为0.这意味着设备没有更多数据要发送。这是EOF条件。用户进程应该关闭设备。

  • ret是&lt;这是一个错误的情况。用户流程必须检查errno并采取适当的措施。

您的设备驱动程序必须根据设备读取时发生的情况在device_read中返回适当的值。

另一方面,像cat这样的进程希望每read次调用读取多达4096个字节。如果设备发送的数量少于该数量,它将打印收到的数据并要求更多。 cat只有在收到信号(例如Ctrl-C)或read调用返回不可恢复的错误(例如ENODEVICE时才会停止,该错误应由你的驱动程序,如果出现这种情况),或者读取0字节(EOF条件)。


一个相当愚蠢的设备,它将"Hello, world"返回给用户进程。它使用一些必须在device_open函数中重置的全局数据。请注意,如果多个进程同时使用您的设备,则必须将这些全局数据转换为实例数据(使用file->private_data)。此device_read示例显示如何处理设备缓冲区和用户缓冲区,以及如何跟踪发送给用户的字节,因此设备永远不会发送比它更多的数据,从不发送比用户请求更多的数据,以及何时设备用完数据后,它会向用户返回0。

int curindx = 0; /* should be reset upon calling device_open */

static ssize_t device_read (struct file* filp, char *bufStoreData, 
                            size_t bufCount, loff_t* curOffset)
{
  size_t bytes_to_copy;
  char device_data[]="Hello, world!\n";
  size_t remaindersize;

  remaindersize = strlen(device_data) - curindx;
  bytes_to_copy = (remaindersize <= bufCount)? 
                             remaindersize : bufCount;
  ret = copy_to_user(bufStoreData,device_data+curindx, bytes_to_copy);
  if (ret != 0)
    return -EPERM; /* if copy was not successful, report it */
  curindx += bytes_to_copy;
  return bytes_to_copy;
}

答案 1 :(得分:0)

  

1)copy_to_user是否返回剩余要读取的字节数或读取的字节数?

copy_to_user返回无法复制的字节数。

  

2)如果我使用cat

,是否使用bufcount

bufCount是用户可以读取的字节数。换句话说,它是用户空间应用程序的缓冲区大小。我猜cat使用多个PAGE_SIZE作为缓冲区大小,实际上你可以通过将printk添加到你的device_read()函数来自己检查:

print(KERN_INFO "bufCount=%ld\n", bufCount);
  

3)如果所有数据都没有在单个调用中读取它如何读取剩余数据?应用程序的责任是再次发出系统调用还是驱动程序自动运行?

用户空间程序使用read()系统调用从文件(包括块和字符设备)读取数据,只有在到达文件末尾时才返回0。这就是他们知道何时停止的方式。所以,是的,用户空间程序负责读取剩余数据(如果需要)。

ssize_t ret;
...
while ((ret = read(fd, buf, bufsize)) > 0) {...};
if (ret < 0)
   error();

另一方面,设备驱动程序的职责是正确维护其内部结构内的偏移并返回有意义的值。

P / S: 我建议你阅读一本书“Linux设备驱动程序”,它可以在互联网上免费获得(http://lwn.net/Kernel/LDD3/),并详细介绍这些主题。