我有一个内核模块,它分配一个大的内存缓冲区,然后将这个缓冲区映射到用户空间。
模块从硬件接收一些数据,然后将新数据放入缓冲区,前面有一个标志。 (内存初始化为零,标志为1)。
用户空间程序在返回指向有效数据的指针
之前读取循环中的标志代码的简化版本:
uint8_t * getData()
{
while(1)
{
if(*((volatile uint32_t*)this->buffer) == 1)
return this->buffer+sizeof(uint32_t);
}
}
内存区域映射为共享,完整缓冲区内存转储确认缓冲区已正确写入。
问题是在经过一定数量的正确读取后,此功能会停止返回 这可能是由于CPU缓存?有没有办法规避这一点,并确保每次都直接从RAM进行读取,而不是从缓存中进行读取?
答案 0 :(得分:0)
是的,这可能是由于读卡器端的cpu缓存造成的。有人可能会认为“volatile”关键字应该可以防止出现这种问题,但这并不完全正确,因为volatile只是指令编译器不注册变量,而不是指导cpu直接从主内存读取每一次。
问题需要在写入方面解决。从您的描述中,它听起来像是在内核模块中发生并从用户端读取。如果这两个操作发生在不同的cpus(不同的缓存域)上,并且没有任何东西可以在读取端触发缓存失效,那么在描述时你将被困在读取端。您需要在存储指令后强制在Linux内核上存储缓冲区刷新。假设它是linux内核,在设置标志后立即插入对smp_mb的调用,并且模块中的值很可能在所有体系结构上做正确的事情。
答案 1 :(得分:0)
提醒用户空间应用程序存在更多数据的更好方法是让它在read()
中阻塞内核模块提供的文件描述符,内核模块在更多数据被唤醒时将其唤醒可用。