Linuxブロッキングおよび非ブロッキングリード端末


ブロックと非ブロック
  • 通常のファイルを読むとブロックされません.何バイト読んでも、readは限られた時間で返されます.端末装置やネットワークから読むと必ずしもそうではなく、端末から入力されたデータに改行がなければ、readを呼び出して端末装置を読むとブロックされ、ネットワーク上でパケットを受信していなければ、readを呼び出してネットワークから読むとブロックされ、どのくらいブロックされるかは不明であり、データが到着しなければそこにブロックされている.同様に、通常のファイルを書くとブロックされず、端末装置やネットワークに書くとは限らない.
  • ブロック(Block)という概念を明確にします.プロセスがブロックされたシステム関数を呼び出すと、プロセスはスリープ(Sleep)状態に置かれ、カーネルは、ネットワーク上でパケットを受信したり、sleepで指定されたスリープ時間を呼び出したりするなど、プロセスが待つイベントが発生するまで、他のプロセスが実行されるようにスケジューリングされます.スリープ状態とは対照的にRunning状態であり,Linuxカーネルでは実行状態にあるプロセスは,実行がスケジューリングされている場合の2つに分けられる.CPUはこのプロセスのコンテキスト環境にあり,プログラムカウンタ(eip)にはそのプロセスの命令アドレスが保存され,汎用レジスタにはそのプロセス演算プロセスの中間結果が保存され,そのプロセスの命令が実行され,そのプロセスのアドレス空間が読み書きされている.
  • 準備状態.このプロセスは、イベントの発生を待つ必要はなく、いつでも実行できますが、CPUは一時的に別のプロセスを実行しているので、カーネルスケジューリングされるのを1つの準備キューで待つことになります.システムに複数の準備完了プロセスが同時に存在する可能性がありますが、スケジューリングは誰が実行しますか?カーネルのスケジューリングアルゴリズムは、優先度とタイムスライスに基づいており、各プロセスの実行状況に応じて優先度とタイムスライスを動的に調整し、各プロセスが比較的公平に実行できるようにするとともに、ユーザー体験を両立させ、ユーザーと対話するプロセスの応答を遅くすることはできません.

  • ブロッキングリードターミナル
    #include 
    #include 
    #include 
    #include 
    
    int main(void)
    {
            char buf[10] = {0};
            int n = 0;
            n = read(STDIN_FILENO, buf, 10);
            if (n < 0)
            {
                    perror("read STDIN_FILENO");
            }
            write(STDOUT_FILENO, buf, n);
            printf("
    "
    ); return 0; }

    ノンブロッキングリードターミナル
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MSG_AGN "try again
    "
    int main(void) { char buf[10] = {0}; int n = 0; int fd = 0; fd = open("/dev/tty", O_RDONLY | O_NONBLOCK); if (fd < 0) { perror("open /dev/tty"); exit(1); } tryagain: n = read(fd, buf, 10); if (n < 0) { if (errno == EAGAIN) { sleep(5); write(STDOUT_FILENO, MSG_AGN, strlen(MSG_AGN)); goto tryagain; } perror("read /dev/tty"); exit(1); } write(STDOUT_FILENO, buf, n); printf("
    "
    ); close(fd); return 0; }

    非ブロックリード端末とタイムアウト待ち
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MSG_AGN "try again
    "
    #define MSG_TIMEOUT "time out
    "
    int main(void) { char buf[10] = {0}; int n = 0,fd = 0; int i = 0; fd = open("/dev/tty", O_RDONLY | O_NONBLOCK); if (fd < 0) { perror("open /dev/tty"); exit(1); } for (i = 0; i<5; i++) { n = read(fd, buf, 10); if (n >= 0) { break; } if (errno != EAGAIN) { perror("read /dev/tty"); exit(1); } sleep(1); write(STDOUT_FILENO, MSG_AGN, strlen(MSG_AGN)); } if (i == 5) write(STDOUT_FILENO, MSG_TIMEOUT, strlen(MSG_TIMEOUT)); else write(STDOUT_FILENO, buf, n); printf("
    "
    ); close(fd); return 0; }