Linux kernel 字符设备中的中断处理
我试图在内核中为用户界面正确注册中断 令人惊讶的是,我并没有在内核中找到很多这样的例子 irq处理器 } 等待中断的ioctlLinux kernel 字符设备中的中断处理,linux-kernel,interrupt-handling,ioctl,Linux Kernel,Interrupt Handling,Ioctl,我试图在内核中为用户界面正确注册中断 令人惊讶的是,我并没有在内核中找到很多这样的例子 irq处理器 } 等待中断的ioctl static long el_device_ioctl(结构文件*filp, 未签名的int ioctl_num, 无符号长ioctl_参数) { 结构el_irq_dev*el_irq=&el_irq_devices[0]; 开关(ioctl_num){ 案例IOCTL_WAIT_IRQ:buf_路); 旋转锁定(&el\u irq->my\u lock); 如果(e
static long el_device_ioctl(结构文件*filp,
未签名的int ioctl_num,
无符号长ioctl_参数)
{
结构el_irq_dev*el_irq=&el_irq_devices[0];
开关(ioctl_num){
案例IOCTL_WAIT_IRQ:buf_路);
旋转锁定(&el\u irq->my\u lock);
如果(el_irq->buf_wr!=&el_irq->buf_rd)
{
我的价值=一些缓冲区[el_irq->buf_rd];
el_irq->buf_rd++;
如果(el_irq->buf_rd>=16)
el_irq->buf_rd=0;
}
旋转解锁(&el\u irq->my\u lock);
将_复制到_用户(ioctl_参数和my_值,sizeof(my_值));
违约:
打破
}
返回0;
}
我的问题是:
[1] 为什么您首先需要所有这些?我们有fpga内存空间,而是在用户空间中执行大多数驱动程序,只是从内核向用户空间发送中断信号什么类型的内存?一般用途?为什么不在内核驱动程序中使用DMA呢?谢谢你的详细回答。假设永远不会错过中断是合理的吗?i、 e.ioctl不应看到超过1个等待中断?如果是-也许我不需要中断处理程序和IOCTL之间的缓冲机制,但我不太清楚这里“错过的中断”是什么意思。最简单的方法是在上次clear_interrupts()之后至少有一个中断时,让IOCtl处理程序(不用担心大写字母,有几个变体)返回。但是用户空间处理程序应该假设,自从上次IOCtl返回以来,可能已经发生了多个中断,并且应该有一种方法让用户空间处理程序了解这些中断报告的所有工作。因此,我假设我在本例中使用的缓冲机制(一些缓冲区),如果这是为所有作品提供用户空间的唯一方式,那么是的。在代码中,您将“ch”指定给当前缓冲区插槽,但我看不出“ch”是从何处获得的,也看不出它到底是什么(我猜您只是在草图代码中遗漏了它)。很多硬件都会在内部实现一个缓冲区,就像某个_缓冲区一样,最终的处理程序(在本例中是用户空间处理程序)可以直接读取。在这种情况下,不需要一些缓冲区。如果这个硬件不能做到这一点,那么您应该确保尽可能快地清除中断,以避免丢失工作。那有帮助吗?是的,帮助很大!我还将此标记为解决方案。我现在也开始认为我真的不需要这个缓冲区,因为HW很关心这个。只要我不清除fpga中的中断,我希望fpga缓冲区不会比预期的要满。因此,如果用户空间处理程序(在ioctl上等待)足够快,可以复制缓冲区并清除中断,那么应该不会有任何真正的问题,对吗?
static irqreturn_t irq_handler(int irq, void *dev_id)
{
struct el_irq_dev *el_irq = &el_irq_devices[0];
printk("irq in\n");
spin_lock(&el->my_lock,flags);
clear_interrupt()
some_buffer[buf_wr] = ch;
el_irq->buf_wr++;
if (el_irqbuf_wr >= 16)
el_irqbuf_wr = 0;
spin_unlock(&el->my_lock,flags);
wake_up_interruptible(&el->pollw);
return IRQ_HANDLED;
static long el_device_ioctl( struct file *filp,
unsigned int ioctl_num,
unsigned long ioctl_param)
{
struct el_irq_dev *el_irq = &el_irq_devices[0];
switch (ioctl_num) {
case IOCTL_WAIT_IRQ: <<<---- using ioctl (no poll) to wait on interrupt
wait_event_interruptible(el_irq->pollw, &el_irq->buf_wr != &el_irq->buf_rd) ;
spin_lock(&el_irq->my_lock);
if (el_irq->buf_wr != &el_irq->buf_rd)
{
my_value=some_buffer[el_irq->buf_rd];
el_irq->buf_rd++;
if (el_irq->buf_rd >= 16)
el_irq->buf_rd = 0;
}
spin_unlock(&el_irq->my_lock);
copy_to_user(ioctl_param,&my_value,sizeof(my_value));
default:
break;
}
return 0;
}