簡體   English   中英

內核互斥與wait_event_interruptible_exclusive

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM