stdin、stdout、stderrは、プロセスが使用するI / Oチャネルを「知っている」データ構造にインデックス付けされる整数です。私はこのデータ構造がプロセスごとに一意であることを知っています。 I / Oチャネルは、動的メモリ割り当てを含むいくつかのデータ配列構造ですか?
答え1
Unixファミリーオペレーティングシステムでは、標準の入力、出力、およびエラーストリームはファイルディスクリプタとして0
識別1
されます2
。 Linuxでは、これらのファイルproc
があります/proc/[pid]/fs/{0,1,2}
。このファイルは実際には以下を指します。擬似端末ディレクトリ内のデバイス/dev/pts
。
PTY(Pseudo Terminal)は一対の仮想デバイスです。擬似端末ホスト(PTM)と擬似端子スレーブ(PTS)(総称してASAと呼ばれる)偽の端末ペア) は、プログラムに接続するプログラム間の双方向パイプに似た IPC チャネルを提供します。端末機器、擬似端末を使用して以前のプログラムと入力を送受信するドライバです。
重要なのは、疑似ターミナルスレーブが通常のターミナルのように見えることです。非標準および標準パターン(既定値)、SIGINT
次のような特定の入力文字を解釈します。邪魔する文字(通常+を押してCtrl生成C)は疑似ターミナルホストに書き込まれるか、またはファイルの終わりの文字(通常+で生成)が見つかると次の戻りを生成しますread()
。端末でサポートされているその他のタスクには、エコーのオン/オフ、フォアグラウンドプロセスグループの設定などがあります。0
CtrlD
擬似端末は様々な用途に使用されます。
これにより、プログラムは、
ssh
ネットワークを介して接続された他のホスト上でターミナル指向プログラムを実行することができます。ターミナル指向プログラムは、一般に、対話型ターミナルセッションで実行される任意のプログラムであり得る。これらのプログラムの標準入力、出力、およびエラーは、ソケットが上記の端末関連機能をサポートしていないため、ソケットに直接接続することはできません。これにより、プログラムは
expect
スクリプト内の対話型端末指向プログラムを駆動できます。xterm
たとえば、端末関連機能を提供するために端末エミュレータで使用されます。screen
たとえば、複数のプロセス間で単一の物理端末を再利用するためにプログラムで使用されます。これは、
script
シェルセッション中に発生したすべての入出力を記録するなどのプログラムで使用されます。
Unix98スタイルPTY、Linuxで使用される場合、設定は次のようになります。
ドライバはマスターマルチプレクサで擬似端末を開き、
dev/ptmx
PTM のファイル記述子を受け取り、/dev/pts
ディレクトリに PTS デバイスを作成します。開いた各ファイル記述子は、/dev/ptmx
独自の関連PTSを持つ独立したPTMです。ドライバ呼び出しは、
fork()
次の手順を順番に実行する子プロセスを生成します。新しいセッションを開始するために子供が呼び出す
setsid()
子供はセッションリーダーです。これにより子供も負けた。制御端子。子プロセスは、ドライバによって生成されたPTMに対応するPTSデバイスを開きます。子プロセスはセッションリーダーですが、制御端末がないため、PTSは子プロセスの制御端末になります。
子は、
dup()
標準入力、出力、およびエラーのスレーブデバイスのファイル記述子をコピーするために使用されます。最後に、子プロセス呼び出しは、擬似
exec()
端末装置に接続するために端末指向プログラムを開始する。
この時点で、ドライバがPTMに書き込むすべての内容は、PTSのターミナル指向プログラムへの入力として表示され、その逆も同様です。
正式モードで実行すると、PTSへの入力は1行ずつバッファされます。つまり、通常の端末と同様に、PTSから読み取られるプログラムは、改行文字がPTMに書き込まれたときにのみ入力行を受け取ります。バッファ容量がなくなると、write()
入力の一部が消費されるまで追加のブロック呼び出しが実行されます。
Linuxカーネルでは、ファイル関連のシステムコールは、ユーザー空間プログラム用の統合ファイルシステムインターフェースを提供する仮想ファイルシステム(VFS)層で実装されていますopen()
。 VFSを使用すると、さまざまなファイルシステム実装がカーネルに共存できます。ユーザー空間プログラムが上記のシステムコールを呼び出すと、VFS はその呼び出しを適切なファイルシステム実装にリダイレクトします。read()
write()
stat()
次のPTSデバイスは、/dev/pts
で定義されているファイルシステムの実装によって管理され、Unix98スタイルのデバイスを提供するTTYドライバはで定義されています。devpts
/fs/devpts/inode.c
ptmx
drivers/tty/pty.c
TTYデバイスとTTY間のバッファリング産業規律擬似端末などは、次に定義される各 tty デバイスに対して維持されるバッファ構造を提供します。include/linux/tty.h
カーネルバージョン3.7以前では、バッファフリップバッファ:
#define TTY_FLIPBUF_SIZE 512
struct tty_flip_buffer {
struct tq_struct tqueue;
struct semaphore pty_sem;
char *char_buf_ptr;
unsigned char *flag_buf_ptr;
int count;
int buf_num;
unsigned char char_buf[2*TTY_FLIPBUF_SIZE];
char flag_buf[2*TTY_FLIPBUF_SIZE];
unsigned char slop[4];
};
構造には、2つの同じサイズのバッファーに分割されたストレージスペースが含まれています。バッファには番号が付けられています0
(前半char_buf/flag_buf
)と1
(後半)。ドライバは、によって識別されるバッファにデータを格納しますbuf_num
。別のバッファをラインフィールドにフラッシュすることができます。
buf_num
0
との間を切り替えてバッファを「反転」します1
。変更後はbuf_num
、 と識別されるバッファの先頭に設定され、 に設定さchar_buf_ptr
れます。flag_buf_ptr
buf_num
count
0
カーネルバージョン3.7から開始kmalloc()
TTYロールオーバーバッファーは、リング構成によって割り当てられたオブジェクトに置き換えられました。。通常の状況では、IRQベースのシリアルポートは通常の速度で前のフリップバッファとほぼ同じように動作します。両方のバッファは最終的に割り当てられ、カーネルは以前と同様に循環します。ただし、レイテンシが発生したり速度が増加したりすると、バッファプールがわずかに大きくなる可能性があるため、新しいバッファ実装はより良いパフォーマンスを発揮します。
答え2
これら3つのうちの1つのマニュアルページで答えを説明します。
Under normal circumstances every UNIX program has three streams opened
for it when it starts up, one for input, one for output, and one for
printing diagnostic or error messages. These are typically attached to
the user's terminal but might instead refer to files or
other devices, depending on what the parent process chose to set up.
The input stream is referred to as "standard input"; the output stream
is referred to as "standard output"; and the error stream is referred
to as "standard error". These terms are abbreviated to form the sym-
bols used to refer to these files, namely stdin, stdout, and stderr.
Each of these symbols is a stdio(3) macro of type pointer to FILE, and
can be used with functions like fprintf(3) or fread(3).
Since FILEs are a buffering wrapper around UNIX file descriptors, the
same underlying files may also be accessed using the raw UNIX file
interface, that is, the functions like read(2) and lseek(2).
On program startup, the integer file descriptors associated with the
streams stdin, stdout, and stderr are 0, 1, and 2, respectively. The
preprocessor symbols STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO are
defined with these values in <unistd.h>.