I / OチャネルはLinuxカーネルにどのように実装されていますか?


8

stdin、stdout、stderrは、プロセスに使用するI / Oチャネルを「認識」しているデータ構造にインデックスを付ける整数です。このデータ構造はすべてのプロセスに固有であることを理解しています。I / Oチャネルは、動的メモリ割り当てを備えたいくつかのデータ配列構造にすぎませんか?


I / Oチャネルとは、ストリームまたはパイプを意味しますか?また、これはおそらくカーネルによって異なります。おそらく特定のカーネルについて尋ねる必要があるでしょう。
Strugee 2013年

1
@strugee私はLinuxカーネルについて話している。I / Oチャネルによるストリームを意味しました。これらのストリームはどのようにLinuxに実装されていますか?配列か何か?
KawaiKx 2013年

回答:


14

Unixライクなオペレーティングシステムでは、標準入力、出力およびエラーストリームは、ファイル記述子によって識別されます012。Linuxでは、これらはのprocファイルシステムの下に表示されます/proc/[pid]/fs/{0,1,2}。これらのファイルは、実際にはディレクトリ下の疑似端末デバイスへのシンボリックリンク/dev/ptsです。

疑似端末(PTY)は、仮想デバイスのペアである疑似端末マスター(PTM)と疑似端末スレーブ(PTS)(まとめて疑似端末ペアと呼ばれます)であり、IPCチャネルを提供します。端末デバイスに接続され、疑似端末を使用して入力を送信したり、前のプログラムから入力を受信したりするドライバプログラム。

重要な点は、疑似端末スレーブが通常の端末と同じように表示されることです。たとえば、非標準モードと標準モード(デフォルト)を切り替えることができます。このモードではSIGINT割り込み文字(通常は生成)時に信号 を生成するなど、特定の入力文字を解釈します。キーボードのCtrl+ Cを押すと)が疑似端末マスターに書き込まれるか、ファイルの終わり文字(通常は+ によって生成されます)が検出されると、nextはマスターread()に戻り0ます。端末がサポートするその他の操作には、エコーのオン/オフの切り替え、フォアグラウンドプロセスグループの設定などがあります。CtrlD

疑似端末にはいくつかの用途があります。

  • それらは、プログラムsshがネットワークを介して接続された別のホストで端末指向プログラムを操作することを可能にします。端末指向プログラムは、対話型端末セッションで通常実行される任意のプログラムです。ソケットは前述の端末関連機能をサポートしていないため、このようなプログラムの標準入力、出力、およびエラーは直接ソケットに接続できません。

  • これらは、プログラムexpectがスクリプトからインタラクティブな端末指向プログラムを駆動することを可能にします。

  • これらは、ターミナルxterm関連の機能を提供するためなど、ターミナルエミュレータによって使用されます。

  • これらはscreen、複数のプロセス間で単一の物理端末を多重化するなどのプログラムで使用されます。

  • これらはscript、シェルセッション中に発生するすべての入力と出力を記録するようなプログラムで使用されます。

Linuxで使用されるUnix98スタイルのPTYは、次のように設定されます。

  • ドライバープログラムは、で疑似端末マスターマルチプレクサーを開き、そこでdev/ptmxPTMのファイル記述子を受信し、PTSデバイスが/dev/ptsディレクトリに作成されます。オープンによって取得される各ファイル記述子/dev/ptmxは、独自のPTSが関連付けられた独立したPTMです。

  • ドライバープログラムはfork()、子プロセスを作成するように呼び出します。子プロセスは、次の手順を実行します。

    • setsid()子供は、子供がセッションリーダーである新しいセッションを開始するように要求します。これにより、子供は制御端末を失います。

    • 子は、ドライバプログラムによって作成されたPTMに対応するPTSデバイスを開きます。子はセッションリーダーですが、制御端末がないため、PTSが子制御端末になります。

    • 子はdup()、スレーブデバイスのファイル記述子を標準入力、出力、およびエラーに複製するために使用します。

    • 最後に、子はexec()、疑似端末デバイスに接続される端末指向プログラムを起動するために呼び出します。

この時点で、ドライバープログラムがPTMに書き込むものはすべて、PTSの端末指向プログラムへの入力として表示されます。逆も同様です。

正規モードで動作している場合、PTSへの入力は行ごとにバッファリングされます。言い換えると、通常の端末と同様に、PTSから読み取るプログラムは、改行文字がPTMに書き込まれた場合にのみ入力行を受け取ります。バッファリングキャパシティが使い果たさwrite()れると、入力の一部が消費されるまで、以降の呼び出しはブロックされます。

Linuxカーネルでは、ファイルに関連するシステムコールはopen()read()write() stat()などのユーザ空間のプログラムのための均一なファイルシステムインタフェースを提供する仮想ファイルシステム(VFS)層に実装されています。VFSを使用すると、カーネル内で異なるファイルシステムの実装を共存させることができます。ユーザースペースプログラムが前述のシステムコールを呼び出すと、VFSはその呼び出しを適切なファイルシステム実装にリダイレクトします。

下のPTSデバイスは、で定義さ/dev/ptsれているdevptsファイルシステムの実装によって管理され/fs/devpts/inode.c、Unix98スタイルのptmxデバイスを提供するTTYドライバは、で定義されてい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以降、TTYフリップバッファはkmalloc()、リングで編成されて割り当てられたオブジェクトに置き換えられました。通常の速度のIRQ駆動シリアルポートの通常の状況では、それらの動作は古いフリップバッファーの場合とほとんど同じです。2つのバッファが割り当てられ、カーネルは以前と同様にそれらの間を循環します。ただし、遅延がある場合や速度が向上する場合、バッファプールが少し大きくなる可能性があるため、新しいバッファの実装のパフォーマンスは向上します。


これと同じくらい知識が豊富な回答は、入手するのが非常に困難です。
エタールコホモロジー

-1

3つのいずれかのmanページから、答えを説明しています。

   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>.

この回答では、の実装についてstdinstdoutおよびstderrCライブラリの観点から説明していますが、問題はカーネルの実装に関するものです。私の回答では、カーネルの視点を説明しようとしました。
Thomas Nyman 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.