2012-03-21 27 views
2

簡單地說,在一個read方法我檢查,如果一個變量爲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; 
} 

我認爲(也驗證了)這裏可能是一個原子性問題。如果在if (soc2e->bytes == 0)read方法和wait_event_interruptible的調用之間發生中斷會發生什麼情況。也許這個過程在下一次中斷之前不會被喚醒。解決此問題的最佳方法是什麼?

回答

3

wait_event_interruptible宏已經非常小心避免您描述的種族。其實,你並不需要你bytes成員的初始檢查 - 你可以只寫在你的read方法:

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

因爲wait_event_interruptible()不會真正去睡覺,如果條件爲真(或爲真而它正處於睡眠中)。

+0

酷!感謝羅蘭。但是,在這個過程被喚醒之後,我應該重新測試一下情況嗎?如果我有更多的進程,字節可以被其他消費者讀取...也許信號量可能是足夠的? – MirkoBanchi 2012-03-22 09:03:11

+1

是的,如果情況可能改變,您需要再次檢查。通常,信號量通常不是正確的答案......內核習慣用法是用鎖來保護條件,並執行諸如「lock_state(); while(!condition){drop_lock(); wait_event ...() ; retake_lock();}「 – Roland 2012-03-26 21:41:22