2016-07-11 7 views
3

私はYoctoを実行する組み込みプロセッサで作業しています。私は変更されたuio_pdrv_genirq.c UIOドライバを持っています。select()を使用してUIOデバイスファイルのブロックを検出する

私はDMAを制御するライブラリを作成しています。デバイスファイルに書き込み、DMAを開始する関数が1つあります。第2の機能は、()を呼び出すことによってDMAが完了するのを待つことを意図しています。 DMAが進行中はデバイスファイルがブロックされます。完了すると、DMAコントローラは、デバイスファイル上のブロックを解放する割り込みを発行する。

私は時間を含めることができるように、私は読み取りを使用して期待通りに働いシステム()を持っていますが、私は(選択に切り替えたい)。しかし、select()を使用すると、ブロックを認識していないように見え、常に(DMAが完了する前に)すぐに戻ります。コードの簡単なバージョンを含めました:

int gannet_dma_interrupt_wait(dma_device_t *dma_device, 
     dma_direction dma_transfer_direction) { 

    fd_set rfds; 
    struct timeval timeout; 
    int select_res; 

    /* Initialize the file descriptor set and add the device file */ 
    FD_ZERO(&rfds); 
    FD_SET(dma_device->fd, &rfds); 

    /* Set the timeout period. */ 
    timeout.tv_sec = 5; 
    timeout.tv_usec = 0; 

    /* The device file will block until the DMA transfer has completed. */ 
    select_res = select(FD_SETSIZE, &rfds, NULL, NULL, &timeout); 

    /* Reset the channel */ 
    gannet_dma_reset(dma_device, dma_transfer_direction); 

    if (select_res == -1) { 
     /* Select has encountered an error */ 
     perror("ERROR <Interrupt Select Failed>\n"); 
     exit(0); 
    } 
    else if (select_res == 1) { 
     /* The device file descriptor block released */ 
     return 0; 
    } 
    else { 
     /* The device file descriptor block exceeded timeout */ 
     return EINTR; 
    } 
} 

明らかに私のコードに間違いはありますか?または、誰かが選択肢を提案することができますか?

+0

さらに調査した結果、 'read()'を後で組み込むと 'select()'が期待通りに機能することが分かりました。この場合、両方の関数のタイミングを合わせてブロックしているのが 'select()'呼び出しであることを確認しました。 'select()'だけを呼び出すと、実際に 'read()'を実行して 'select()'を最適化することはできません。 –

答えて

0

UIOドライバには2つのカウンタが含まれています。 1つは 件のイベント(event_count)を記録し、もう1つは 呼び出し機能が認識するイベントの数(listener->event_count)を記録します。

UIOドライバでread()を実行すると、イベント数が返され、 はlistener->event_countとなり、event_countとなります。すなわち、リスナーは今発生したすべてのイベントで最新の です。

もしUIOドライバにpoll()又はselect()を使用する場合、彼らは(彼らは異なり、その後戻るまで、彼らは同じこと 待機している場合)であればこれら二つ 番号が異なるとリターンする場合、それはチェック。 listener->event_countは更新されません。

あなたはselect()への呼び出しの間read()をしない場合listener->event_countが一致しません 明らかに、その後event_countと第二 select()はすぐに戻ります。したがって、select()の呼び出しの間に read()を呼び出す必要があります。

このように、select()が動作するはずですが、当時私には分かりませんでした。

0

この回答は、指定されたデバイスファイルに対してselect()を使用することが可能であることを前提としています(ソケットディスクリプタにのみselect()を使用します)。 select()の代替機能として、poll()ファミリーの関数をチェックアウトすることができます。以下は、select()を呼び出すことで問題を解決するために何ができるかについてのヒントを少なくとも提供します。

select()関数の最初のパラメータは、最大デプスクリプタ番号+ 1でなければなりません。記述子が1つしかないので、最初のパラメータとしてselect()に直接渡して1を加えます。 dma_deviceのファイル記述子が無効になる可能性があります。タイムアウト時にEINTRを返すことは、あなたがやろうとするものかもしれませんが、そうでない場合や、無効な記述子をテストする必要がある場合は、別のバージョンを検討してください。 select()呼び出しはシグナルによって中断されます。その場合、戻り値は-1でerrnoはEINTRに設定されます。これは、あなたの関数で内部的に以下のように扱うことができます:

FD_ZERO(&rfds); 
FD_SET(dma_device->fd, &rfds); 

timeout.tv_sec = 5; 
timeout.tv_usec = 0; 

// restart select() if it's interrupted by a signal; 

do { 

    select_res = select(dma_device->fd + 1, &rfds, NULL, NULL, &timeout); 

} 
while(select_res < 0 && errno == EINTR); 


if (select_res > 0) { 

    // a file descriptor is legible 

} 
else { 

    if (select_res == 0) { 

    // select() timed-out 
    } 
    else { 

    // an error other than a signal occurred 

    if (errno == EBADF) { 

     // your file descriptor is invalid 

    } 
    } 
} 
関連する問題