2017-01-29 9 views
5

私は、常にドライバの小さなバッファにデータをプッシュしている外部デバイスがあるとします。私は、割り込みハンドラが待っているユーザプロセスを起動させる待機キューを使用しています(LDD(第3版) - ハンドラの実装に似ています)。Linuxデバイスドライバのバッファリング方法

irq_handler_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) 
{ 

flag = 1; 
wake_up_interruptible(&wq); 

return IRQ_HANDLED; 
} 

ssize_t my_read(struct file *dev, char __user *buf, size_t count, loff_t *f_pos) 

{ 

     wait_event_interruptible(wq, flag != 0); 
     flag = 0; 
     copy_to_user(usr_buf, drv_buf, count); 

} 


/***********************User program***********************/ 

while(1) 
{  
    read(fid, buffer, size); 

    //do stuff with data 

} 

ユーザプログラムはreadを呼び出し、割り込みが外部デバイスから新しいデータを取得するまで待機します。外部デバイスはこのコードが実行できるよりも速くデータをプッシュする可能性があるため、ユーザプログラムがデータをコピーする前にデータを上書きしないようにするためにどのようなメカニズムを使用できますか?構造のようなリングバッファはここで動作しますか?その実装方法は不明です。

ありがとうございました

+0

drv_bufはどのようにデータを取得しますか? copy_to_user(usr_buf、drv_buf、count)は、copy_to_user(buf、drv_buf、count)である必要があります。 –

+0

* "ユーザープログラムがコピーする前にデータを上書きしないようにするために、どのようなメカニズムを使用できますか?" - 基本的に、ドライバはバッファオーバーランが発生するまで、できるだけ多くのバッファを格納できます。答えに提案されているように(静的に割り当てられた)リングバッファは、(リング)バッファがアンダーサイズである場合にのみオーバーランを延期することができます。よく書かれたドライバーは、そのような状態を検出し報告することができます。動的に割り当てられたバッファでさえ、「遅い」読者に対処するには不十分かもしれません。 IOWでは、ユーザー空間が少なくとも平均レートの到着データに追いつくことができるようにする必要があります。 – sawdust

答えて

2

はい、リングバッファが機能します。

バッファを割り込みハンドラから入力するだけで、my_readコールバックから読み込むだけです。

A本当にナイーブと本当に非効率的な実装が(未テスト)のようになります。

static irqreturn_t irq_handler(int irq, void *dev_id) 
{ 
     struct my_dev *dev = dev_id; 

     buf[buf_wr] = read_device(dev); 
     buf_wr++; 

     if (buf_wr >= BUFSIZE) 
       buf_wr = 0; 

     wake_up(&wq); 
     return IRQ_HANDLED; 
} 

static ssize_t my_read(struct file *file, char __user *ubuf, 
          size_t sz, loff_t *ppos) 
{ 
     int n, ret; 

     ret = wait_event_interruptible(wq, 
           buf_wr != buf_rd); 
     if (ret) 
       return ret; 

     n = buf_wr - buf_rd; 
     if (n < 0) 
       n += BUFSIZE; 

     n = min(count, n); 
     ret = copy_to_user(ubuf, buf, n); 
     buf_rd += n; 

     if (buf_rd >= BUFSIZE) 
       buf_rd -= BUFSIZE; 

     if (ret) 
       return ret; 

     *ppos += n; 
     return 1; 
} 

あなたはまた、より効率的な何かを得るためにDMAまたはMMAPまたはその両方を使用することをお勧めします。

+0

2人以上のユーザがリングバッファにアクセスできる場合、いくつかの同期プリミティブによって保護する必要があります。つまり、割り込みハンドラの手段 - irq_handlerがスリープ状態になることがありますか? –

+0

ユーザスペース信号は、Linuxカーネルの割り込みと同等です はい、リングバッファ機構を使用できます。しかし、データを保護するためにカーネルの同期方法を使用する必要があります。 –

+0

はい、確実に適切なロックを使用する必要があります(ここでは、mutexで十分です)。言ったように、これは本当に簡単な実装です。 –

関連する問題