我正在研究运行 Yocto 的嵌入式处理器。我有一个修改过的 uio_pdrv_genirq.c UIO 驱动程序。
我正在编写一个库来控制 DMA。有一个函数写入设备文件并启动 DMA。第二个函数旨在通过调用 select() 等待 DMA 完成。当 DMA 正在进行时,设备文件 block 。完成后,DMA Controller 发出一个中断,释放设备文件上的 block 。
我使用 read() 让系统按预期工作,但我想切换到 select() 以便我可以包括超时。然而,当我使用 select() 时,它似乎没有识别 block 并且总是立即返回(在 DMA 完成之前)。我包含了一个简单版本的代码:
int gannet_dma_interrupt_wait(dma_device_t *dma_device,
dma_direction dma_transfer_direction) {
fd_set rfds;
struct timeval timeout;
int select_res;
/* Initialize the file descriptor set and add the device file */
FD_ZERO(&rfds);
FD_SET(dma_device->fd, &rfds);
/* Set the timeout period. */
timeout.tv_sec = 5;
timeout.tv_usec = 0;
/* The device file will block until the DMA transfer has completed. */
select_res = select(FD_SETSIZE, &rfds, NULL, NULL, &timeout);
/* Reset the channel */
gannet_dma_reset(dma_device, dma_transfer_direction);
if (select_res == -1) {
/* Select has encountered an error */
perror("ERROR <Interrupt Select Failed>\n");
exit(0);
}
else if (select_res == 1) {
/* The device file descriptor block released */
return 0;
}
else {
/* The device file descriptor block exceeded timeout */
return EINTR;
}
}
我的代码有什么明显的错误吗?或者有人可以建议选择的替代方案吗?
最佳答案
事实证明,UIO 驱动程序包含两个计数器。一个记录
事件数(event_count
),另外记录了多少个事件
调用函数知道 (listener->event_count
)。
当您在 UIO 驱动程序上执行 read()
时,它会返回事件数和
使 listener->event_count
等于 event_count
。 IE。听众是
现在更新所有已发生的事件。
当您在 UIO 驱动程序上使用 poll()
或 select()
时,它会检查这两个
数字不同并返回(如果它们相同)
等到它们不同然后返回)。它不更新
listener->event_count
.
显然,如果您在调用 select()
之间不执行 read()
,那么
listener->event_count
将与 event_count
和第二个不匹配
select()
将立即返回。 因此有必要调用
read()
在调用 select()
之间。
事后看来,select()
应该以这种方式工作似乎很清楚,但当时对我来说并不明显。
关于c - 使用 select() 检测 UIO 设备文件上的 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38304715/