假设我有一个外部设备不断地将数据推送到我的驱动程序中的一个小缓冲区。我正在使用等待队列,其中中断处理程序唤醒等待的用户进程(类似于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/