首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >阻止读取操作直到发生外部事件的正确方法?

阻止读取操作直到发生外部事件的正确方法?
EN

Stack Overflow用户
提问于 2017-11-17 18:45:00
回答 1查看 82关注 0票数 0

我正在为数据采集系统开发一个设备驱动程序。有一个pci设备,它同时提供定期的输入和输出数据。然后,linux通过文件操作来管理循环缓冲区中的数据。

系统的数据吞吐量相对较低--每秒接收750,000字节多一点,每秒传输150,000字节。

有一个小的用户空间实用程序,用于为测试目的在循环中写入和读取数据。

下面是驱动程序代码的一部分(为了简单起见,省略了与循环缓冲区相关的所有代码)。PCI设备初始化在其他地方处理,pci_interupt不是中断处理程序的真正入口点)

代码语言:javascript
复制
#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或者代码中的某些竞争条件。

EN

回答 1

Stack Overflow用户

发布于 2017-12-08 15:51:17

linux中使用的一种标准方法也可以在您的情况下使用。

用户空间测试程序: 1.在阻塞模式下打开文件(在linux中默认,直到指定NONBLOCK标志);2.调用select()来阻塞文件描述符。

内核驱动程序:1.寄存器中断处理程序,只要有数据可用,就会调用它。2.处理程序锁定以保护数据的读写和传输之间的公共缓冲区。请查看这些来自ldd3、book、测试司机源代码的链接。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47357313

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档