2016-04-11 7 views
0

私はSTDINと言うとき、私はストリームを参照していますが= 0stdinはLinuxの文字デバイスとして扱われますか?

fdで、私はブロックと文字のデバイスをカバーしてOSのコースを取っています言及しました。具体的には、キーボードは文字デバイスであると言われています。しかし、readシステムコールが表示されたとき、カーネルはブロックデバイスまたはブロックデバイス上のファイルであれば、カーネルはそれが何を読み込んでいるか気にしませんでした。私の質問がある

#include <stdlib.h> 
#include <unistd.h> 

const int BUFFSIZE = 5; 

int main() { 
    int fd, n; 
    char buffer[BUFFSIZE]; 

    int stdin = 0; 
    int stdout = 1; 
    int stderr = 2; 

    do { 
    n = read (0, buffer, BUFFSIZE); 
    if (n < 0) { 
     write (stderr, "Error occurred\n", 10); 
    } else { 
     write (stdout, "Entered if\n", 20); 
     write (stdout, buffer, n); 
    } 
    } while (n > 0); 
    return 0; 
} 

:どのようにLinuxは、標準入力(FD = 0)の治療ん

これは、我々が与えられたコードのですか?キャラクターデバイスとして扱われているのか、カーネルは何らかのバッファリングをしています(これはコードを実行したときの結果で判断すると思われます)。

さらに、私が使用できるかどうかを知ることは有用でしょう文字デバイスから一般に読み込むためのシステムコールです。もしそうなら、入力はバッファされていますか?

+6

'stdin'は*デバイス*ではなく*ストリーム*です。 –

+1

_ "カーネルは、ブロックデバイスまたはブロックデバイス上のファイルであれば、何を読み込んでいるか気にしません。" _これは正しくはありません。ファイルシステムのどこにでも関連するファイルを持たないファイルディスクリプタ(ソケット、名前のないパイプ、 'signalfd's、' eventfd's、 'epoll'ディスクリプタなど)がいくつかあります。重要なことは、ファイル記述子を持っていて、読み込みをサポートしていることです。 –

+0

@PaulRありがとう!コメントを編集しました:) –

答えて

4

カーネルは、通常、文字デバイス上でほとんどバッファリングを行いません。

カーネルは、ファイルシステムのファイルから読み込むときに一定量のバッファリングを行います。

デバイス標準入力の種類は、プロセスによって異なりますので、どのような種類のものであるかは言えません。デフォルトでは、通常fd 0は文字デバイスであるユーザーのキーボードです。しかし、私が言うならば、

program < file 

fd 0は普通のファイルです。私が言うなら、

program < /dev/hda0 

fd0はブロックデバイスです。そして私がそれに取り組んだ場合、おそらくfd 0をネットワークソケットに接続することができます。

Linuxでは、/proc/pid/fd/0もありますが、これはデバイスでもありません。それは/devの実際のデバイスへのシンボリックリンクのように見えます。


補遺:特定のデバイスがバッファリングされているかどうかは、実際にそのデバイス用のドライバが書かれているかに依存するかどうか。任意のドライバは、ある形式のバッファリングを実装しても実装しなくてもよい。さらに、バッファリングが実際にであるかどうかは、他の要因によってはが使用される可能性があります。(例えば、Unixターミナルドライバはすべてデフォルトでラインバッファされていますが、ドライバを "cbreak"または "raw"モードにすると、バッファリングはオフになります)。私はキャラクターやブロックのデバイスがバッファリングされている、またはバッファされていないという一般的な記述はできないと思います。


補足2:レイヤーの剥離を開始するとかなり複雑になります。 Unixはdo-what-I-meanとkeep-it-simple、stupidとの間の適切なバランスを取るのに、強く(そして一般的にはとても良い仕事をしています)努力しています。たとえば、の端末がのラインバッファではなく、10文字を要求していますが、3つしか利用できない場合、read()は3を返します。これは正しいことですが、それでもまだどこかでバッファリングします。そこでは、入力された時刻から読み込んだ時刻までの3つの文字が蓄積されています。さらに、3つしか要求しなかったが、利用可能なものが10つある場合、状況によっては、もう1つがあなたのために節約されると思います。これはかなりの量のカーネルレベルのバッファリングを示唆しています。

しかし、ローモードでは、十分に速く読み込めないと文字を失う可能性があります。私は、端末ドライバからネットワークソケットに注目して、特定の状況でUDPモードのソケットでread()を実行し、実際のUDPパケットが読み取り要求よりも大きければ、残りのパケットを失う可能性があると私は考えていましたそこにも。 [コメント者が私が間違っている可能性があると示唆していますが(TCPモードソケットは明らかにかなりバッファリングされています)

したがって、最終行はルールが複雑になる可能性があります。特定のデバイスドライバのみが使用されていますが、潜在的に無数の他の詳細もあります。

+0

ありがとうございました! 私はまだ私が特に明確ではない何かを持っています。ユーザーのキーボードのようなキャラクターデバイスから1文字以上のものを読み取ったとすると、 "ABC"と言う。 次に、文字列 "ABC"を含むバッファをすべて取得し、すべてを一度に返します。これは、カーネルが結果を格納するためにバッファを使用することを意味しているわけではないので、 '\ 0'や '\ n'のような特殊文字が入力されると、システムコールから戻ってくるだけです。提供された制限に達していますか? –

+0

あなたがそのコメントを投稿したのと同じように私は自分の答えを更新していました。はい、ジョナサン・レフラー(Jonathan Leffler)が "tty"(テレタイプ、すなわちキーボード)デバイスの場合、カーネルは一般的にラインバッファを保持しているので、キャラクタデバイスの入力をバッファできることを覚えています。 –

+0

'read()'で3文字を要求すると、その動作はまだデバイスによって異なります。例えば、端末やパイプでは、入力に 'X'と改行がある場合、その2文字が返されます(ヌルターミネータなどはありません)。入力に何もない場合、データが表示されるのを待ちます。入力に20文字がある場合は、3が読み込まれ、後の呼び出しのために残りの17が残ります。ファイル記述子0で直接の 'read()'呼び出しとファイルストリーム入出力(例えば 'getchar()')を混ぜると、大きな混乱が生じます。 –

1

Unixには実際の標準はありません。 Cランタイムライブラリは、プロセスの最初の(0番目の)ファイル記述子に関連付けられたシンボルstdinを定義します。

通常、Unixシェルはプロセスを作成するときに3つのファイルを設定します。また、慣例により、これらはstdin、stdout、およびstderrと呼ばれます。

UNIXプロセスにこれらの3つのファイルがあるという要件はありません。独自のシェルを作成して、0,1、または2のファイルを開かずにプロセスを作成することは、まったく可能です。

stdinの動作は、関連付けられている "ファイル"(データストリーム)の種類によって異なります。 Stdinはキーボードにマッピングすることも、ファイルにマップすることもできます。どちらの場合でも、データを読み取ることができます。後者でのみ、fseekを行うことができます。

+1

伝統的に、 'stdin'はコンパイル時マクロです。 '__iob [0]'(1つか2つのアンダースコア - 私は忘れてしまった)に展開され、ライブラリにシンボル 'stdin'というものはありませんでした。 GNU Cが10年以上前にルールを変更したのはかなり衝撃的でした。どちらのシステムも標準に準拠していました。標準では実装に多くの自由度が許されています。 –

関連する問題