web-dev-qa-db-ja.com

stdinからのread()

次のコード行を検討してください。

_while((n = read(STDIN_FILENO, buff, BUFSIZ)) > 0)
_

私の理解によれば、_read/write_関数は非バッファI/Oの一部です。それでは、read()関数はstdioからの呼び出しごとに1文字しか読み取らないという意味ですか?または言い換えれば、nの値は

_    -1  in case of error
n =  0  in case of EOF
     1  otherwise
_

そうでない場合、上記のread()関数はいつ戻り、なぜですか?

注:read()がstdinからBUFSIZ文字数を正常に読み取るまで待機することも考えていました。しかし、読み取ることができる文字数がBUFSIZ未満の場合はどうなりますか?読み取りは永遠に待つか、EOF=(UNIXでは_Ctrl + D_またはWindowsでは_Ctrl + Z_)が到着するまで)待ちますか?

また、_BUFSIZ = 100_と_stdin = ACtrl+D_(つまり、単一の文字の直後のEOF)と言います)では、_while loop_は何回繰り返されますか?

17
Ravi Gupta

Read()の動作は、読み取られる内容によって異なります。通常のファイルの場合、N文字を要求すると、使用可能な場合はN文字が取得され、ファイルの終わりが介在する場合はN文字より少なくなります。

Read()が標準/クックドモードの端末から読み取っている場合、ttyドライバーは一度に1行にデータを提供します。したがって、read()に3文字または300を取得するように指示すると、ttyドライバーが改行または端末の定義されたEOFキーを認識するまで、readがハングし、read()は次のいずれかで戻ります。行の文字数または要求した文字数のどちらか小さい方。

Read()が非標準/ rawモードの端末から読み取りを行っている場合、readはすぐにキー入力にアクセスできます。 read()に3文字を取得するように要求すると、入力タイミングと端末の構成方法に応じて、0〜3文字で返される場合があります。

read()はシグナルに対して異なる動作をし、要求された文字数より少ない値で戻るか、シグナルが到着する前にシグナルが読み取りを中断した場合はerrnoをEINTRに設定して-1を返します。

記述子が非ブロッキングI/O用に構成されている場合、read()の動作は異なります。 read()は、入力がすぐに利用可能でない場合、errnoをEAGAINまたはEWOULDBLOCKに設定して-1を返します。これはソケットに適用されます。

ご覧のとおり、read()を呼び出すと、驚きの準備ができているはずです。要求した文字数が常に得られるとは限らず、EINTRなどの致命的でないエラーが発生する可能性があります。つまり、read()を再試行する必要があります。

21
Kyle Jones

あなたのコードは:

_while((n = read(0, buff, BUFSIZ) != 0))
_

これには欠陥があります-括弧はそれが次のように解釈されることを意味します:

_while ((n = (read(0, buff, BUFSIZ) != 0)) != 0)
_

ブール条件は代入の前に評価されるため、nは値0(条件が真ではない)と1(条件が真)のみを取得します。

あなたは書くべきです:

_while ((n = read(0, buff, BUFSIZ)) > 0)
_

これはEOFまたは読み取りエラーで停止し、nは発生した状態を通知します。


どうやら、上のコードは問題のタイプミスでした。

バッファリングされていないI/Oは、読み取った文字数まで(ただしそれ以上)読み取りません。 EOFまたはエラーにより、読み取りが少なくなる可能性があります。また、呼び出し時に使用可能な容量が少ないため、読み取りも少なくなる可能性があります。端末について考えてください。通常は、それ以上利用できないため、行末です。パイプを検討してください。フィードプロセスで128の未読バイトが生成された場合、BUFSIZが4096であれば、読み取りから128バイトしか取得できません。非ブロッキングファイル何も利用できないため記述子が返される場合があります。まだ利用可能な情報がないため、ソケットが返すバイト数が少ない場合があります。ディスクの読み取りが返すバイト数が少ないのは、読み取りが実行されたときにファイルに残っているバイト数が要求された数より少ないためです。 。

ただし、一般に、多くのバイトを要求した場合、read()は1バイトだけを返しません。

4

read()マンページには、次のように記載されています。

戻り値

成功すると、読み取られたバイト数が返され(ゼロはファイルの終わりを示します)、ファイル位置はこの数だけ進められます。この数が要求されたバイト数より小さい場合はエラーではありません。これは、たとえば、現在実際に使用可能なバイト数が少ないため(おそらく、ファイルの終わりに近いか、パイプまたは端末から読み込んでいるため)、またはread()が信号。エラーの場合は-1が返され、errnoが適切に設定されます。この場合、ファイルの位置(ある場合)が変更されるかどうかは指定されません。

したがって、各read()は、指定されたバイト数までを読み取ります。しかしそれはより少なく読むかもしれません。 「非バッファリング」とは、read(fd, bar, 1)を指定した場合、読み取りは1バイトのみを読み取ることを意味します。バッファリングされたIOは、1文字だけが必要な場合でも、BUFSIZの量を読み取ろうとします。これは無駄に聞こえるかもしれませんが、システムコールを作成するオーバーヘッドを回避します。速い。

2
Dave
  1. 読み取りは、要求されたすべての文字を取得しようとします。
  2. EOFが要求されたすべての文字が返される前に発生した場合、次の読み取りが-1を返した後に取得したものを返し、ファイルの終わりを知らせます。

それが読み込もうとしたときに何が起こるかはありません。 openを呼び出して、ファイルのブロックまたは非ブロックを読み取ることができます。 「ブロッキング」とは、返すものが存在するまで待機することを意味します。

これは、入力を待機しているシェルで表示されるものです。そこに座っています。リターンを押すまで。

ノンブロッキングとは、データのバイトがない場合、データのバイトが返されないことを意味します。完全な正しい答えが使用できなくなる他の多くの要因に応じて、readはerrnoをEWOULDBLOCKのようなものに設定します。これにより、読み取りがゼロバイトを返した理由がわかります。これは必ずしも致命的なエラーではありません。

あなたのコードはマイナスをテストしてEOFまたはエラーを見つけることができます

0
jim mcnamara

readがバッファリングされていないとは、潜在的に共有されているリソースである、基になるオープンファイルの記述からデータがプルされた後、プロセスのレベルでバッファリングが行われないことを意味します。 stdinがターミナルの場合、少なくとも2つの追加のバッファーが動作している可能性があります。

  1. ターミナルバッファ。これは、回線から1〜4kのデータを保持できる可能性があります。
  2. 端末での行入力/編集用のカーネルのクックド/カノニカルモードバッファー。ユーザーは、Enterキーを押すことにより、行が(上記のバッファーに)送信されるまで行のプリミティブ編集(バックスペース、バックワード、行の消去など)を実行できます。 。

readは、すでに送信されたものを、渡された最大読み取り長までプルしますが、行編集バッファーから何もプルできません。この追加のバッファリング層を無効にする場合は、tcsetattrなどを使用して、ターミナルのクックド/カノニカルモードを無効にする方法を検索する必要があります。