0

我正在编写我的第二个内核模块。作为演示,我正在尝试提供对固件核心的用户空间访问。该演示在 petalinux(专为 Zynq 或 Microblaze 定制的嵌入式操作系统)下进行。我在用户空间和内核模块之间添加了虚拟文件系统挂钩,它似乎在读取和写入时都有效。唯一的问题是,在我的用户应用程序和内核模块之间的某个地方,操作系统将我的请求大小膨胀到 PAGE SIZE (4096)。

一位同事评论说我可能将模块安装为块设备而不是字符设备。这很有意义。我的模块上游的某个人肯定在缓存我的结果(如果我对块驱动程序的理解是准确的,那么这对于硬盘驱动器来说非常有意义),但我们与易失性设备相关联,所以这不是合适的。但是我能找到的所有诊断结果都表明它是作为字符设备安装的......

mknod /dev/myModule **c** (Dynamically specified Major Number) (Zero)
ls -la /dev/myModule
   **c**rw-r--r--     1   root    root 252, -    Jan 1 01:05 myModule

这是我用来注册虚拟文件 IO 挂钩的模块源......

alloc_chrdev_region (&moduleMajorNumber, 0, 1, "moduleLayerCDMA");
register_chrdev_region  (&moduleMajorNumber,    1, "moduleLayerCDMA");    
cdevP = cdev_alloc();
cdevP->ops = &moduleLayerCDMA_fileOperations;
cdevP->owner = THIS_MODULE;
cdev_add(cdevP, moduleMajorNumber, 1);

有什么线索吗?

4

1 回答 1

0

您的问题来自这样一个事实,即标准 C 库缓冲 I/O 例程(fopenfclosefreadfgetch他们的朋友)为每个打开的文件/设备保留一个用户空间缓冲区,并且当您的程序尝试从该文件/设备读取时,库例程尝试进行预读,为以后的读取调用做准备,以提高 I/O 的效率。类似地,写入fwrite通过写入缓冲区进行,并且仅在缓冲区已满或关闭文件/设备或明确执行时通过系统调用刷新到系统fflush

有两种方法可以解决这个问题:

  • 更简单的方法可能是简单地将您的用户空间程序转换为使用非缓冲 I/O(open, close, read, write& 他们的朋友),这些只是在 1:1 的基础上进行相应的系统调用。
  • 或者在您的内核模块中处理问题:忽略 a 中询问的字节数read是否超过您希望在单个系统调用中返回的字节数。您可以将该值视为调用者提供的缓冲区的长度,并且您不必完全填满它。当然,在返回值中,你必须指出实际读取了多少字节。
于 2013-11-05T22:04:41.423 回答