![](/img/trans.png)
[英]Why is wait_event_interruptible() in Linux kernel never used in a while loop?
[英]kernel mutex vs wait_event_interruptible_exclusive
我想編寫一個簡單的char驅動程序,該驅動程序實現耗時的讀寫操作,它包含一個緩沖區和兩個用於緩沖區的讀寫指針的全局指針。 每個進程都應專門進行讀取或寫入,讀取器也必須等到至少有512個字節才能讀取。 我只是想在練習中使用wait_event_interruptible_exclusive
而不是互斥鎖來完成此wait_event_interruptible_exclusive
。 我的讀寫是:
static ssize_t
my_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos)
{
int nbytes;
wait_event_interruptible_exclusive(wq, atomic_read(&data_sz) >=512 && (atomic_xchg(&data_sz,-1) || 1) );
nbytes = simple_read_from_buffer(buf, lbuf, &read_pos, my_buff, my_buff_size);
*ppos = read_pos;
atomic_set(&data_sz,write_pos-read_pos);
wake_up_interruptible(&wq);
return nbytes;
}
static ssize_t
my_write(struct file *file, const char __user *buf, size_t lbuf,
loff_t *ppos)
{
int nbytes;
wait_event_interruptible_exclusive(wq, atomic_read(&data_sz) != -1 && (atomic_xchg(&data_sz,-1) || 1));
nbytes = simple_write_to_buffer(my_buff, my_buff_size, &write_pos, buf, lbuf);
*ppos = write_pos;
atomic_set(&data_sz,write_pos-read_pos);
wake_up_interruptible(&wq);
return nbytes;
}
可以那樣做嗎? 是否可以用類似的東西替換互斥體的所有用法? 另外,由於緩沖區的偏移量是全局的,因此驅動程序將忽略讀寫的ppos參數,並想知道是否需要行*ppos=read_pos
和*ppos=write_pos
嗎?
盡管從所有進程的角度來看原子操作都是不可分割的 ,但是原子操作的組合 (例如與&&
操作)已不再不可分割 。
在您的代碼中,兩個讀取器可能同時發現atomic_read(&data_sz) >=512
為真,然后執行atomic_xchg(&data_sz,-1)
(第二個讀取器將以data_sz
等於-1
來執行此操作)。
對於條件的不可分割性,您可以使用自旋鎖保護其評估。 在這種情況下,不需要原子變量。 下面的示例使用waitqueue本身提供的自旋鎖:
loff_t read_pos = 0, write_pos = 0;
size_t data_sz = 0;
DECLARE_WAIT_QUEUE_HEAD(wq);
static ssize_t
my_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos)
{
int nbytes;
spin_lock(&wq.lock); // Take the lock before checking condition
// Next call will drop the lock while waiting and reacquire it on wake up.
wait_event_interruptible_exclusive_locked(&wq, data_sz >= 512);
// TODO: Interruptible wait may wakeup premature; check its return value.
data_sz = -1; // Prevent other waiters to enter read/write section
spin_unlock(&wq.lock);
nbytes = simple_read_from_buffer(buf, lbuf, &read_pos, my_buff, my_buff_size);
*ppos = read_pos;
spin_lock(&wq.lock); // Take the lock before updating data_sz
data_sz = write_pos - read_pos;
// There is no 'wake_up_interruptible_locked',
// but "normal" wakeup works with interruptible waits too.
wake_up_locked(&wq);
spin_unlock(&wq.lock);
return nbytes;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.