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

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. 如果我使用猫,我会使用bufcount

  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 syscall以检索剩余数据。 像: ret = read (fd, buffer+ret, sizebuff-ret);

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

  • ret是<0。这是一个错误条件。 用户进程必须检查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)copy_to_user是否返回剩余要读取的字节数或读取的字节数?

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

2)如果我使用猫,是什么使用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/ ),并详细介绍这些主题。