1

我有一个分配大量内存缓冲区的内核模块,然后将该缓冲区映射到用户空间中。
模块从硬件接收一些数据,然后将新数据放入带有标志的缓冲区中。(内存初始化为零,标志为1)。

用户空间程序在返回指向有效数据的指针之前循环读取标志

代码的简化版本:

uint8_t * getData()
{
    while(1)
   {
      if(*((volatile uint32_t*)this->buffer) == 1)
          return this->buffer+sizeof(uint32_t);
   }
}

内存区域被映射为共享,并且完整的缓冲区内存转储确认缓冲区已正确写入。

问题是在一定数量的正确读取后,此函数停止返回。
这可能是由于 CPU 缓存造成的吗?有没有办法避免这种情况并确保每次都直接从 RAM 读取而不是从缓存中读取?

4

2 回答 2

0

是的,这可能是由于读取器端的 cpu 缓存所致。有人可能认为“volatile”关键字应该可以防止此类问题,但这并不完全正确,因为 volatile 只是对编译器的一个指令,不要注册变量,与指示 cpu 直接从主存储器读取并不完全相同每次。

这个问题需要在写端解决。根据您的描述,听起来写入发生在内核模块中并从用户端读取。如果这两个操作发生在不同的 cpus(不同的缓存域)上,并且没有任何东西可以触发读取端的缓存失效,那么正如您所描述的那样,您将卡在读取端。您需要在存储指令之后强制在 linux 内核上刷新存储缓冲区。假设它是 linux 内核,在设置标志后立即插入对 smp_mb 的调用,并且模块中的值很可能在所有体系结构上都做正确的事情。

于 2012-02-08T00:04:36.070 回答
0

提醒用户空间应用程序存在更多数据的更好方法是让它阻塞read()内核模块提供的文件描述符,当更多数据可用时内核模块唤醒它。

于 2012-02-08T00:36:11.087 回答