我正在为数据采集系统开发一个设备驱动程序。有一个pci设备,它同时提供定期的输入和输出数据。然后,linux通过文件操作来管理循环缓冲区中的数据。
系统的数据吞吐量相对较低--每秒接收750,000字节多一点,每秒传输150,000字节。
有一个小的用户空间实用程序,用于为测试目的在循环中写入和读取数据。
下面是驱动程序代码的一部分(为了简单起见,省略了与循环缓冲区相关的所有代码)。PCI设备初始化在其他地方处理,pci_interupt不是中断处理程序的真正入口点)
#include <linux/sched.h>
#include <linux/wait.h>
static DECLARE_WAIT_QUEUE_HEAD(wq_head);
static ssize_t read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
DECLARE_WAITQUEUE(wq, current);
if(count == 0)
return 0;
add_wait_queue(&wq_head, &wq);
do
{
set_current_state(TASK_INTERRUPTIBLE);
if(/*There is any data in the receive buffer*/)
{
/*Copy Data from the receive buffer into user space*/
break;
}
schedule();
} while(1);
set_current_state(TASK_RUNNING);
remove_wait_queue(&wq_head, &wq);
return count;
}
static ssize_t write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
/* Copy data from userspace into the transmit buffer*/
}
/* This procedure get's called in real time roughly once every 5 milliseconds,
It writes 4k to the receiving buffer and reads 1k from the transmit buffer*/
static void pci_interrupt() {
/*Copy data from PCI dma buffer to receiving buffer*/
if(/*There is enough data in the transmit buffer to fill the PCI dma buffer*/) {
/*Copy from the transmit buffer to the PCI device*/
} else {
/*Copy zero's to the PCI device*/
printk(KERN_ALERT DEVICE_NAME ": Data Underflow. Writing 0's'");
}
wake_up_interruptible(&wq_head);
} 以上代码很好地工作了很长一段时间,但每12-18小时,有一个数据下流错误。导致零被写入。
我的第一个想法是,由于用户空间应用程序不是真正实时的,它的读写操作之间的时间延迟有时会太大,导致失败。但是,我尝试更改用户空间中的读和写的大小,并更改用户空间应用程序的良好性,这对错误的频率没有影响。
根据错误的本质,我相信在上述三种方法中都存在某种形式的竞赛条件。我不知道linux内核等待队列是如何工作的。
除了上述阻止读取的方法之外,还有其他合适的替代方法吗?或者是否有其他错误导致此行为的原因。
系统信息:
Linux版本: Ubuntu 16.10
Linux内核:Linux4.8.0-低延迟
芯片组: Intel Celeron N 3150/N 3160四核2.08 GHz SoC
TL;DR:,上面的代码每12-18小时就会碰到下流错误,有一种更好的方法来阻止IO或者代码中的某些竞争条件。
https://stackoverflow.com/questions/47357313
复制相似问题