我正在开发一种采集器件,需要DMA操作才能将大数据帧传输到主存储器。现在我假设目的地是一个连续的内存区域,所以我在启动时分配它(比如1 MB),如ldd2-ch13中的“自己动手分配”部分所述。然后,驱动程序可以通过调用ioremap()来访问该区域。
当前系统的工作原理如下:
内存映射控制寄存器允许用户空间应用程序启动/停止设备
启动后,设备开始以~8MB / s的速度连续(和循环)将获取的数据传输到指定的存储区域。
我开发了一个简单的char驱动程序,它提供了一个阻塞的read()函数,这样每次收到一个中断时,用户空间就可以读取一个新的数据帧。
运行一些测试后,我意识到用户空间应用程序在运行以下代码时错过了一些帧:
for(i=0;i<NUM_FRAMES;i++) {
read(dev_d,buf,FRAME_SIZE);/*Read frame*/
for(j=0;j<FRAME_SIZE;j++) /*File dump*/
fprintf(fp,"%d",buf[j]);
fprintf(fp,"\n");
}
我怀疑应用程序的进程在两次后续读取之间进入休眠状态,允许设备重写应该已经读取的内存位置。
由于我没有内核开发经验,我想知道为这种设备实现驱动程序的正确方法是什么,以确保同步。基本上我正在尝试为实时采集设备实现简单的共享内存通信,我需要保证操作系统能够读取所有采集的数据帧。
答案 0 :(得分:2)
你正在读一本非常古老的书。这里是本书最后一个版本的链接(它很老):Linux Device Driver 3 - Memory Mapping。您还可以从内核文档中阅读DMA-API。
进行一种同步读取Time, Delays and Deferred Work章节。您可以使用a waitqueue 。你可以在read()上等待,并在新帧可用时你* wake_up *。
关于您的代码,仅仅了解您的问题是不够的。但是,如果您认为需要休眠/等待,可以在驱动程序中实现轮询file_operation,并在用户空间中使用select()来询问是否有要阅读的内容。