私はウェブ検索を試しましたが、Linuxリダイレクト出力をその場で検索しても答えが見つかりませんでした。私が理解している限り、stdoutと言う出力はファイル記述子1を使用して機能します。
$ ls -l /proc/pid/fd/1
lrwx------ 1 user1 user1 64 Sep 27 13:37 1 -> /dev/pts/1
proc
ファイルシステムで機能するUnixコマンドがあります。 ls
ここでは、tee
はファイルに書き込み、cat
は読み取りが可能です。なぜ例えばLinuxでは、ユーザーがbash
のln -s
を介してこれらのリンクを手動で変更できるように実装されていませんでしたか? (私がしようとしたときにエラー"No such file or directory"
が発生しました)。実装するのは難しいですか?どのユーティリティがproc
で動作するかをどのように決定しましたか-そのユーティリティのプログラマーによって?
どのユーティリティがprocで動作するかをどのように決定しましたか-そのユーティリティのプログラマーによって?
いいえ、procfs
の開発者は、カーネル情報をファイルシステムの形式でエクスポートする仮想ファイルシステムであり、通常のPOSIXシステムコールで操作できます。
ls
とln
は、常に同じシステムコールを実行するだけです。nixすべてがファイルです。それがポイントであり、lsof
やps
などの特別なツールを必要とせずに_ls -l
_で_/proc/PID
_を使用できる理由です。
_/proc/PID/fd/*
_ファイルで必要なものを実行できます。プログラムがその構成ファイルを開いている場合、less
でそのファイルを読み取り、emacs
またはvim
で編集するか、_gzip < /proc/.../3 > foo.gz
_
これはシンボリックリンクをたどるだけで機能すると思います。しかし、実際にはそうではありません。そのファイルのlstat
はそれをシンボリックリンクとして報告し、readlinkはリンクターゲットを示します。ただし、そのリンクターゲットは、カーネルによって作成された単なるテキストです。リンクが解除された後もファイル上でまだ開いているFDの場合、/foo/bar (deleted)
のようになります。ただし、その_/proc
_パスでopen()
を使用しても、実際のファイルは開きます。 (ほとんどのシステムコールと同様に、open
は内部的にシンボリックリンクに従います。通常のファイルシステム上の通常のシンボリックリンクの場合、リンクターゲットは通常のパス名のように扱われます。)
そのiノードをファイルシステムにリンクする方法はありません(主にセキュリティ上の理由から、_O_TMPFILE
_で開かれたFDでlinkat(2)
を使用することは可能ですが、決してhadそもそもパス名 https://stackoverflow.com/questions/4171713/relinking-an-anonymous-unlinked-but-open-file )
あなたの場合、正しい質問は「どのシステムコールが/ proc/PIDの下にあるものに対して何を行うべきかがどのように決定されたか」です。
AFAIK、_/proc
_ファイルのシステムコールはプロセス環境を変更できません。つまりカーネル情報は読み取り専用でエクスポートされます。
プロセスのコンテキスト内で_dup2
_のようなシステムコールを行うには、コメントで説明されているような他のハックを使用する必要があります。例えばptrace
APIを使用します。例えばptrace
を使用してターゲットプロセス内で処理を行うGDBまたは他のデバッガーを使用する。
なぜ例えばLinuxユーザーがbashでln -sを使用してこれらのリンクを手動で変更できるように実装されていませんか?
proc
ファイルシステムは内部のカーネル状態を表示するだけだからです。特定のファイルにデータを書き込むことで実際にカーネルの状態に影響を与えることができる場合もありますが、物事を移動できる単一の例は思いつきません。
実装するのは難しいですか?
カーネルはオープンソースであり、一見して自分で決めてください(「難しい」はプログラミングの経験に関連します)。
また、変更しているプロセスがstdoutに何かを書き込んでいる場合にどうなるかを考えます。また、セキュリティへの影響も考慮してください。
ただし、上流カーネルにこのような変更を加える可能性は、おそらく私の見積もりではかなり低いでしょう。
どのユーティリティがprocで動作するかを決定したのですか-そのユーティリティのプログラマーによって?
/proc
は仮想ファイルシステムであり、仮想ファイルシステムに必要なカーネル機能を実装しています。さまざまなカーネルプログラマが/proc
、彼らは通常、プログラミングするのが最も簡単な方法でそれをしようとします。
Linuxでは、標準の入出力ファイル記述子は、/proc
ファイルシステムではなく、カーネルシステムコールを介して作成されます。
/proc
に表示されるシンボリックリンクは、データをパイプするために使用される実際の手段ではなく、プロセスがデータにアクセスできるようにするためにカーネルが実行していることのreflectionです。そのため、ln -s
を使用してそれらを変更することはできません。
その場で出力をリダイレクトすることについてのあなたの質問のために、私はそれを行うコマンドを知りません。しかし、それは確かに可能です。このようなプログラムを開発する方法の例を次に示します。
cat
の機能を実装することから始めます。したがって、標準入力を取り、それを標準出力にダンプします。これは非インタラクティブアプリケーションです。上記は言うよりも確かに簡単です。たくさんの重要な詳細に目を通しましたが、その場で出力をリダイレクトすることが少なくとも実行可能であることを示すには十分だと思います。
Stdinなどが指す場所を変更する代わりに、 pseudo-terminal(PTY) を作成し、それを介して入力と出力をリダイレクトすることで、プログラムが何かが変更されたことを認識する必要がなくなります。実際、それだけを行うプログラムがいくつかあります(しばしば ターミナルマルチプレクサ と呼ばれます)。
ご存知のように、tmux
のようなマルチプレクサを使用して、1つの端末のセッションから切断して別の場所に再接続できますが、いつでも標準入力または出力のいずれかをパイプすることもできます。たとえば、tmux
ペイン内でシェルを実行していて、コマンドpipe-pane 'cat >>~/test.txt'
( man page から取得)をtmux
に送信した場合、標準セッションペイン内で何も変更せずに、出力が~/test.txt
に追加されるようになりました。
ここでの誤解の核心は、シンボリックリンクが記述されている間に変更すると、予期したとおりに変更されることです。
そうではありません。実際のファイル(またはデバイスやパイプ)が開かれると、すべてのアクティビティは開いているファイルに関係し、それを指しているシンボリックリンクなどに発生したことはすべて無視されます。実際、これはシンボリックリンクに限定されませんが、実際にはファイルに名前を付ける「ハード」リンクに等しく関係します。unixoidシステムでは、ファイルを実際に移動または削除(!)することもできます(注:上書きしてください! )一部のプロセスが開いており、プロセスはファイルを閉じるまで何も変更されていません。
シンボリックリンクは、実際のファイルを見つけるためのヘルパーにすぎません。実際のファイルは、実際のiノードを見つけるためのヘルパーです。その後、何を開くかは、iノード自体によって決まります。の場合 /dev/pts/1
実際に開いているのは、メジャーデバイス番号が136でマイナー1のキャラクターデバイスです。
ファイル名のその時点から、ファイルまたはシンボリックリンクの存在は重要ではありません。削除する前に開いていた場合に限り、削除したファイルにアクセスできます。