Linux kernel 如何正确唤醒中断处理程序中的进程

Linux kernel 如何正确唤醒中断处理程序中的进程,linux-kernel,linux-device-driver,atomic,Linux Kernel,Linux Device Driver,Atomic,简单地说,在read方法中,我检查变量是否为0,如果为0,我将当前进程置于休眠状态: static ssize_t soc2e_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) { ... struct soc2e_dev *soc2e = (struct soc2e_dev *)filp->private_data; i

简单地说,在
read
方法中,我检查变量是否为0,如果为0,我将当前进程置于休眠状态:

static ssize_t soc2e_read(struct file *filp, char __user *buf,
                          size_t count, loff_t * ppos)
{
    ...
    struct soc2e_dev *soc2e = (struct soc2e_dev *)filp->private_data;

    if (soc2e->bytes == 0)
    {
        if (wait_event_interruptible(soc2e->wlist, (soc2e->bytes > 0)))
            return -ERESTARTSYS;
    }
    ...
 }
我必须在中断处理程序中唤醒进程:

static irqreturn_t soc2e_irq_handler(int irq, void *dev)
{
   ...
   struct soc2e_dev *soc2e = dev;
   ...
   soc2e->bytes += read_bytes;

   wake_up_interruptible(&soc2e->wlist);
   return IRQ_HANDLED;
}

我认为(也证实)这里可能存在原子性问题。如果中断发生在
read
方法中的
if(soc2e->bytes==0)
和调用
wait\u event\u interruptable
之间,会发生什么。也许在下一次中断之前进程不会被唤醒。解决此问题的最佳方法是什么?

wait\u event\u interruptable
已经非常小心地避免了您描述的竞争。事实上,您不需要对
bytes
成员进行初始检查——您只需使用
read
方法编写:

  if (wait_event_interruptible(soc2e->wlist, soc2e->bytes > 0))
          return -ERESTARTSYS;

因为<代码> WajyEnviaIddiTyBuffle()/Case>如果条件是真的,则不会真正进入睡眠状态(或者当它处于睡眠状态时变为真)。< /P>酷!谢谢罗兰。但是,我应该在该进程唤醒后重新测试该条件吗?如果我有更多的进程,字节可以被其他消费者读取…也许一个信号量就足够了?是的,如果条件可以改变,你需要再次检查它。一般来说,信号量通常不是正确的答案。。。内核习惯用法是使用锁保护条件,并执行类似“lock_state();while(!condition){drop_lock();wait_event…();retake_lock();}”的操作