mmap共享缓冲区读取问题
我有一个分配大量内存缓冲区的内核模块,然后将该缓冲区映射到用户空间。
模块从硬件接收一些数据,然后将新数据放入缓冲区,缓冲区前面有一个标志。 (内存初始化为零,标志为1)。
指针之前循环读取该标志
用户空间程序在返回指向有效数据简化版本代码的
uint8_t * getData()
{
while(1)
{
if(*((volatile uint32_t*)this->buffer) == 1)
return this->buffer+sizeof(uint32_t);
}
}
:内存区域被映射为共享区域,并且完整的缓冲区内存转储确认缓冲区已正确写入。
问题是,在正确读取一定次数后,该函数将停止返回。
这可能是由于 CPU 缓存造成的吗?有没有办法避免这种情况,并确保每次直接从 RAM 读取而不是从缓存读取?
I have a kernel module that allocates a large buffer of memory, this buffer is then mmap-ed into userspace.
The module recieves some data from hardware, and then puts the new data into the buffer with a flag in front of it. (memory is initialized to zero, flag is 1).
The userspace program reads the flag in a loop before returning a pointer to valid data
simplified version of the code:
uint8_t * getData()
{
while(1)
{
if(*((volatile uint32_t*)this->buffer) == 1)
return this->buffer+sizeof(uint32_t);
}
}
the memory region is mapped as shared and a full buffer memory dump confirms that the buffer is written to correctly.
The problem is that after a certain number of correct reads, this function stops returning.
Could this be due to CPU caching? Is there a way to circumvent that and make sure that the read is made directly from RAM each time and not from cache?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,这可能是由于读取器端的 cpu 缓存造成的。人们可能认为“易失性”关键字应该可以防止此类问题,但这并不完全正确,因为易失性只是指示编译器不要注册变量的指令,与指示 cpu 直接从主内存读取数据并不完全相同。每次。
这个问题需要在写入端解决。从您的描述来看,听起来像是写入发生在内核模块中并从用户端读取。如果这两个操作发生在不同的 cpu(不同的缓存域)上,并且没有任何内容可以在读取端触发缓存失效,那么您将如所描述的那样卡在读取端。在存储指令之后,您需要在 Linux 内核上强制刷新存储缓冲区。假设它是 Linux 内核,在设置标志和模块中的值后立即插入对 smp_mb 的调用很可能会在所有体系结构上执行正确的操作。
Yes it's likely due to the cpu cache on the reader side. One might think the "volatile" keyword should protect against this sort of problem but that's not quite right since volatile is simply a directive to the compiler not to registerize the variable, not quite the same thing as directing the cpu to read directly from main memory every time.
The problem needs to be solved on the write side. From your description, it sounds like the write is happening in the kernel module and read from the user side. If these two operations are happening on different cpus (different caching domains), and there's nothing to trigger a cache invalidation on the read side, you'll get stuck on the read side as you are describing. You need to force a store buffer flush on the linux kernel after your store instruction. Assuming it's the linux kernel, inserting a call to smp_mb right after you've set the flag and the value from the module will most likely do the right thing on all architectures.
警告用户空间应用程序存在更多数据的更好方法是让它在内核模块提供的文件描述符上的 read() 中阻塞,当更多数据出现时,内核模块将其唤醒。数据可用。
A better way to alert the userspace application to the presence of more data would be to have it block in
read()
on a file descriptor provided by the kernel module, with the kernel module waking it up when more data is available.