2

我有一个驱动程序想要向用户发送有关状态更改的通知。在当前实现中,它使用 proc 文件系统来执行此操作。读取过程循环read()到 proc 文件系统。直到内核得到一个导致函数中断的read()块。这是基本代码(删除了所有不需要的混乱):wait_event_interruptible()write_new_data()call wake_up_interruptible()

static int flag=0;
DECLARE_WAIT_QUEUE_HEAD(info_wq);

//user process call read() on /proc/myfile to get to this function
int my_proc_read (struct file *filp, char *buf, size_t count, loff_t *pos)
{
    wait_event_interruptible(info_wq, flag != 0);
    flag = 0;

    //copy buffers to user
    return 0;
}


//when an interrupt comes it schedules this function on the systems' work queue
void write_new_data ()
{
    //fill buffer with data
    flag = 1;
    wake_up_interruptible(&info_wq);
}  

现在考虑以下流程:

  1. 用户进程调用read(),然后等待。
  2. 中断发生 ->write_new_data()被调用。写入数据和调用wake_up_interruptible()
  3. read()被唤醒,读取数据但进程没有重新运行读取(没有计划运行,因为下一次中断而没有到达它......)。
  4. 中断发生 ->write_new_data()再次触发,调用wake_up_interruptible()但没有等待线程正在等待......
  5. 进程调用读取和阻塞。

注意:这一切都发生在单处理器系统上。而且只有一个线程读取和一个线程写入新数据。

如何避免错过第二次中断?(一种解决方案是使用 netlink 套接字,但我想知道是否有办法在 /proc 土地上做到这一点)

4

2 回答 2

4

丹,这是 wait_event_interruptible 的代码:

#define wait_event_interruptible(wq, condition)             \
({                                  \
    int __ret = 0;                          \
    if (!(condition))                       \
        __wait_event_interruptible(wq, condition, __ret);   \
    __ret;                              \
})

如果在 "if (!(condition))" 和 "__wait_event_interruptible" 之间发生中断,则将发生睡眠并且读取过程将被阻塞,直到发生另一个中断。

于 2012-11-26T11:10:59.487 回答
3

由于在调用wait_event_interruptibleand之间可能会发生中断flag = 0,因此它会以不希望的方式影响flag变量。

请注意,即使在 UP 机器上,内核也可能是抢占式的,具体取决于配置,因此代码会受到影响。

另外,我建议不要使用简单的“int”标志。相反,您应该使用atomic_tatomic_dec/inc_*操作。查看内核内部完成的实现,它的作用与您在此处所做的类似。

关于问题本身:

如果您查看代码,wait_event_interruptible您会发现如果条件为真,睡眠不会发生 - 所以您的问题不是问题。

于 2012-06-13T11:04:03.347 回答