(Unix)を選択します

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

selectは、開いている入出力チャネルのファイル記述子のステータスを調べるための、 UnixライクPOSIX準拠のオペレーティングシステムのシステムコールおよびアプリケーションプログラミングインターフェイス(API)[1] selectシステムコールは、UNIXSystemV以降のオペレーティングシステムで導入されたポーリング機能 に似てただし、 c10k問題では、selectとpollの両方が、 kqueue epoll / dev / poll I/O完了ポートなどに取って代わられてい[2]

ファイルハンドルで待機するという規定された使用以外のselectの一般的な使用法の1つは、ポータブルな1秒未満のスリープを実装することです。これは、3つのfd_set引数すべてにNULLを渡し、タイムアウト引数として目的のスリープの期間を渡すことで実現できます。

Cプログラミング言語では、selectシステムコールはヘッダーファイルsys / select.hまたはunistd.hで宣言されており、構文は次のとおりです。

int select int nfds fd_set * readfds fd_set * writefds fd_set * errorfds struct timeval * timeout );           
口論 説明
nfds これは、任意のセットの任意のファイル記述子の最大値より1大きい整数です。つまり、各セットにファイル記述子を追加するときに、すべてのセットの最大整数値を計算し、この値を1つインクリメントしてから、これをnfdsとして渡す必要があります。
readfds fd_setタイプは、読み取りの準備ができているかどうかをチェックするファイル記述子を保持し、出力では、どのファイル記述子が読み取りの準備ができているかを示します。NULLにすることができます
writefds fd_setタイプは、書き込みの準備ができているかどうかをチェックするファイル記述子を保持し、出力では、どのファイル記述子が書き込みの準備ができているかを示します。NULLにすることができます
errorfds 保留中のエラー条件をチェックするファイル記述子を保持するfd_setタイプ。出力時に、保留中のエラー条件があるファイル記述子を示します。NULLにすることができます
タイムアウト 選択が完了するのを待つ最大間隔を指定するstructtimeval型の構造体。タイムアウト引数が、メンバーが0であるタイプstruct timevalのオブジェクトを指している場合、select()はブロックしません。タイムアウト引数がNULLの場合、select()は、イベントによってマスクの1つが有効な(ゼロ以外の)値で返されるまでブロックします。Linuxはタイムアウトを更新して、経過した時間を示しますが、この動作は他のほとんどのUnixシステムでは共有されていません。

fd_set type引数は、FD_SET()、FD_CLR()、FD_ZERO()、およびFD_ISSET()の4つのユーティリティマクロで操作できます

Selectは、 readfds、writefds、およびerrorfdsに設定されているビットの総数を返します。タイムアウトが期限切れになった場合はゼロ、エラーの場合は-1を返します。

selectで使用されるファイル記述子のセットは、オペレーティングシステムに応じてサイズが有限です。新しいシステムコールポーリングは、より柔軟なソリューションを提供します。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#include <sys / types.h> 
#include <sys / socket.h> 
#include <netinet / in.h> 
#include <netdb.h> 

#include <sys / select.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <err.h> 
#include <errno.h> 

#define PORT "9421"

/*関数プロトタイプ*/
ボイドダイconst char * ;  

int main int argc char ** argv     
{{
    int sockfd new maxfd on = 1 nready i ;        

    struct  addrinfo * res0 * res ヒント;   

    charバッファ[ BUFSIZ ]; 

    fd_set master readfds ;  

    intエラー; 

    ssize_t nbytes ; 

    void memset hints '\ 0' sizeof struct addrinfo ));   

    ヒントai_family = AF_INET ;  
    ヒントai_socktype = SOCK_STREAM ;  
    ヒントai_protocol = IPPROTO_TCP ;  
    ヒントai_flags = AI_PASSIVE ;  

    if 0 != error = getaddrinfo NULL PORT hints res0 )))        
        errx EXIT_FAILURE "%s" gai_strerror エラー));  

    for res = res0 ; res ; res = res- > ai_next        
    {{
        if -1 == sockfd = socket res- > ai_family res- > ai_socktype res- > ai_protocol )))       
        {{
            perror "socket()" );
            続行;
        }

        if -1 == setsockopt sockfd SOL_SOCKET SO_REUSEADDR char * on sizeof int ))))       
        {{
            perror "setsockopt()" );
            続行;
        }

        if -1 == bind sockfd res- > ai_addr res- > ai_addrlen )))     
        {{
            perror "bind()" );
            続行;
        }

        休憩;

    }

    if -1 == sockfd    
        終了EXIT_FAILURE );

    freeaddrinfo res0 );

    if -1 == listen sockfd 32 )))    
        死ぬ"listen()" );

    if -1 == fcntl sockfd F_SETFD O_NONBLOCK )))     
        死ぬ"fcntl()" );

    FD_ZERO master );
    FD_ZERO readfds );

    FD_SET sockfd master ); 

    maxfd = sockfd ;  

    while 1  
    {{
        memcpy readfds master sizeof master ));  

        void printf "running select()\ n " );

        if -1 == nready = select maxfd + 1 readfds NULL NULL NULL )))         
            死ぬ"select()" );

        void printf "準備完了記述子の数:%d \ n " nready ); 

        for i = 0 ; i <= maxfd && nready > 0 ; i ++      
        {{
            if FD_ISSET i readfds ))  
            {{
                すでに- ;

                if i == sockfd    
                {{
                    void printf "新しい接続を受け入れようとしています(s)\ n " );

                    if -1 == new = accept sockfd NULL NULL )))       
                    {{
                        if EWOULDBLOCK != errno    
                            死ぬ"accept()" );

                        休憩;
                    }

                    そうしないと
                    {{

                        if -1 == fcntl new F_SETFD O_NONBLOCK )))     
                            死ぬ"fcntl()" );

                        FD_SET new master ); 

                        if maxfd < new    
                            maxfd = new ;  
                    }
                }

                そうしないと
                {{
                    void printf "記述子の1つからのrecv()データ\ n " );

                    nbytes = recv i buffer sizeof buffer )、0 );     
                    if nbytes <= 0    
                    {{
                        if EWOULDBLOCK != errno    
                            死ぬ"recv()" );

                        休憩;
                    }

                    バッファ[ nbytes ] = '\0' ;  
                    printf "%s" buffer ); 

                    void printf "%ziバイトを受信しました。\ n " nbytes ); 

                    閉じるi );
                    FD_CLR i master ); 

                }
            }

        }

    }
    0を返す; 
}

void die const char * msg    
{{
    perror msg );
    終了EXIT_FAILURE );
}

も参照してください

参照

  1. ^ コンピュータシステム研究グループ(1994)。「select、pselect —同期I/O多重化」BSD相互参照NetBSD
  2. ^ 「接続処理方法」nginx.org_

外部リンク