c - Linux设备驱动缓冲策略

标签 c linux linux-kernel linux-device-driver

假设我有一个外部设备不断地将数据推送到我的驱动程序中的一个小缓冲区。我正在使用等待队列,其中中断处理程序唤醒等待的用户进程(类似于LDD(第 3 版)- 实现处理程序)。

irq_handler_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{

 flag = 1;
 wake_up_interruptible(&wq);

return  IRQ_HANDLED;
}

ssize_t my_read(struct file *dev, char __user *buf, size_t count, loff_t *f_pos)

{

        wait_event_interruptible(wq, flag != 0);
        flag = 0;
        copy_to_user(usr_buf, drv_buf, count);

}


/***********************User program***********************/

while(1)
{    
    read(fid, buffer, size);

    //do stuff with data

}

用户程序调用read,等待中断从外部设备获取新数据。由于外部设备推送数据的速度可能比这段代码的执行速度快,我可以使用什么机制来确保数据在用户程序复制之前不会被覆盖?像结构这样的环形缓冲区在这里工作吗?目前尚不清楚如何实现。

谢谢

最佳答案

是的,环形缓冲区可以工作。

您只需从中断处理程序中填充缓冲区,然后您将从 my_read 回调中读取它。

一个非常幼稚且非常低效的实现可能是(未经测试):

static irqreturn_t irq_handler(int irq, void *dev_id)
{
        struct my_dev *dev = dev_id;

        buf[buf_wr] = read_device(dev);
        buf_wr++;

        if (buf_wr >= BUFSIZE)
                buf_wr = 0;

        wake_up(&wq);
        return IRQ_HANDLED;
}

static ssize_t my_read(struct file *file, char __user *ubuf,
                             size_t sz, loff_t *ppos)
{
        int n, ret;

        ret = wait_event_interruptible(wq,
                                buf_wr != buf_rd);
        if (ret)
                return ret;

        n = buf_wr - buf_rd;
        if (n < 0)
               n += BUFSIZE;

        n = min(count, n);
        ret = copy_to_user(ubuf, buf, n);
        buf_rd += n;

        if (buf_rd >= BUFSIZE)
                buf_rd -= BUFSIZE;

        if (ret)
                return ret;

        *ppos += n;
        return 1;
}

您可能还想使用 DMA 或 mmap 或两者都使用以获得更高效的东西。

关于c - Linux设备驱动缓冲策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41916628/

相关文章:

c++ - 结构的区别?

linux - 无法使用 input.h Linux 生成写入设备内核的击键

linux - 如何按第三列中的数字对数据进行排序?

c++ - 可以查询 OpenAL 设备它喜欢的频率和格式吗?

C Regex - 获取匹配的字符串

c - 尝试执行 "strrev",来自整数的指针而不进行强制转换

linux - "threads"如何获取CPU和时间片?

c - 在C中实现由上/下箭头键触发的命令历史记录

c - Linux 套接字上的 SO_SNDBUF 和 SO_RCVBUF

c++ - 在没有 Inotify 的情况下从 Linux 内核读取文件系统事件