SylixOSにおけるselectの原理と使用分析


1.selectインタフェースの概要
1.1 selectインタフェース使用例
selectはオペレーティングシステムの多重I/O多重化技術を実現する方法の一つである.多重I/O多重化技術は、興味のあるファイル記述子のリストを作成し、多重化されたIOインタフェースを呼び出し、これらの記述子の1つがI/Oを行う準備ができているまでインタフェースをブロックします.selectがアプリケーションで使用する例は、次のセグメントコードに示す.
#include 
int main (int argc, char **argv)
{  
    fd_set       fdset;
    struct timeval  timeout;

    timeout.tv_sec  = 10;
    timeout.tv_usec = 0;

    int fd = open("/dev/htm2", O_RDWR, 0666);

    for (;;) {
        FD_ZERO(&fdset);
        FD_SET(fd, &fdset);
        select(fd + 1, &fdset, &fdset, NULL, &timeout);
        sleep(1);
    }
    return  (0);
}

1.2 select関数プロトタイプ分析
LW_API INT   select(INT                   iWidth, 
                   fd_set               *pfdsetRead,
                   fd_set               *pfdsetWrite,
                   fd_set               *pfdsetExcept,
                   struct timeval        *ptmvalTO);
  • iWidthは設定されたファイルセットで、最大のファイル番号+1です.
  • pfdsetReadは、関心のある読み取り可能なファイルセットである.
  • pfdsetWriteは関心のある書き込み可能なファイルセットである.
  • pfdsetExceptは関心のある異常ファイルセットである.
  • ptmvalTOは待ちタイムアウト時間、LW_NULLは永遠に待つことを表す.
  • 戻り値:通常戻り待ちファイル数、エラー戻りPX_ERROR.

  • 2.駆動中のselect実装
    2.1駆動ioctl実装
    SylixOSのselectインタフェース実装では、fdごとに対応するデバイス駆動のioctlインタフェースが呼び出され、次の表に示す2つのコマンドが呼び出されます.
    コマンド#コマンド#
    説明
    FIOSELECT
    SEL_を追加WAKE_NODEノード
    FIOUNSELECT
    SEL_の削除WAKE_NODEノード
    2.2 SylixOSのselect待機チェーン
    SEL_の追加と削除WAKE_NODEの操作は、実際にはSylixOSのselect待機チェーンを操作し、SEL_WAKE_NODE_ADDとSEL_WAKE_NODE_DELETEのシステムインタフェース.待機チェーンの役割は、起動するスレッドのセットをブロックすることであり、起動が必要な場合にシステムのSEL_を呼び出すことができる.WAKE_UPシリーズ関数はスレッドの起動を実現します.SylixOSが提供する起動コマンドを下表に示します.
    コマンド#コマンド#
    説明
    SEL_WAKE_UP
    待機スレッドを起動
    SEL_WAKE_UP_ALL
    あるタイプの操作を待つすべてのスレッドを起動します.
    SEL_WAKE_UP_TYPE
    取得ノードの待機タイプ
    SEL_WAKE_UP_ERROR
    エラーが発生したため、待機しているスレッドを起動します.
    SEL_WAKE_UP_TERM
    エラーが発生したため、あるタイプの操作を待機しているすべてのスレッドを起動します.
    2.3 SylixOSのselectコンテキスト
    なお、selectブロッキング動作で使用される信号量はselectコンテキストであり、駆動するFIOSELECTでもう1つの信号量を実現する必要はない.selectのコンテキストは次のセグメントに示す.
    typedef struct {
        LW_OBJECT_HANDLE       SELCTX_hSembWakeup;              /*                     */
        BOOL                   SELCTX_bPendedOnSelect;          /*        select()    */
        fd_set                *SELCTX_pfdsetReadFds;            /*                  */
        fd_set                *SELCTX_pfdsetWriteFds;           /*                  */
        fd_set                *SELCTX_pfdsetExceptFds;          /*                 */
        fd_set                 SELCTX_fdsetOrigReadFds;         /*                   */
        fd_set                 SELCTX_fdsetOrigWriteFds;        /*                   */
        fd_set                 SELCTX_fdsetOrigExceptFds;       /*                  */
        INT                    SELCTX_iWidth;                   /*  select()          */
    } LW_SEL_CONTEXT;
    typedef LW_SEL_CONTEXT     *PLW_SEL_CONTEXT;

    3.閉塞と起動の実現
    3.1ブロック操作
    selectのブロック動作は、その内部呼び出しpselect関数においてバイナリ信号量を呼び出すpend動作によって実現される.しかしpendを呼び出す前に、pselectはまずioctlを呼び出し、FIOSELECTパラメータを渡します.このインタフェースでは、selectの起動条件が現在満たされているかどうかを判断し、満たされている場合はpostを呼び出し、その後呼び出されたpendがブロックされないようにします.その流れを下図に示します.
    3.2起動操作
    起動が必要な場所でSEL_を呼び出すWAKE_UPシリーズインタフェース、例えば割り込みが発生した箇所、検出されたスレッド.