1つの使用例は、I/Oリダイレクトです。このためには、子プロセスをフォークし、stdinまたはstdoutファイル記述子(0および1)を閉じてから、選択した別のファイル記述子でdup()を実行します。ケース0または1。
これを使用すると、アプリケーションを認識していない可能性のある子プロセスを実行でき、子がstdoutに書き込む(または設定したものは何でもstdinから読み取る)たびに、代わりに提供されたfiledescriptorにデータが書き込まれます。
シェルはこれを使用して、パイプなどのコマンドを実装します。 /bin/ls | more
1つのプロセスの標準出力を他のプロセスの標準入力に接続する。
Dupとdup2を理解するのに最適なシナリオは、リダイレクトです。
最初に知っておくべきことは、システムには、入力と出力を処理する3つのデフォルトのファイルID(または出力または入力ソースを示す変数)があることです。 stdin
、stdout
、stderr
であり、整数では0
、1
、2
。 fprintf
やcout
などのほとんどの関数は、stdout
に直接出力されます。
出力をリダイレクトする場合、1つの方法は、たとえば、fprintf
およびin
を示す引数をout
functionに与えることです。
ただし、よりエレガントな方法があります。デフォルトのファイルIDを上書きして、出力を受け取りたいファイルを指すようにすることができます。 dup
およびdup2
は、まさにこの状況で機能します。
1つの簡単な例から始めましょう。fprintf
の出力を "chinaisbetter.txt"という名前のtxtファイルにリダイレクトしたいとします。まず、このファイルを開く必要があります
int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);
次に、dup関数を使用して、stdout
が "chinaisbetter.txt"を指すようにします。
dup2(fw,1);
現在、stdout(1)は、まだ1ですが「chinaisbetter.txt」の記述子を指しますが、出力はリダイレクトされます。
その後、通常どおりprintf
を使用できますが、結果は画面に直接表示するのではなく、txtファイルに表示されます。
printf("Are you kidding me? \n");
[〜#〜] ps [〜#〜]:
これは直感的な説明を提供するだけで、マンページまたは詳細情報を確認する必要がある場合があります。実際、ここでは「コピー」と言いますが、すべてをコピーしているわけではありません。
ここでのファイルIDは、ファイルのハンドラーを参照しています。上記のファイル記述子は、レコードファイルの情報の構造体です。
POSIX関数、特に自分自身を複製しているように見える関数に興味がある場合は、一般的に 標準自体を確認する をお勧めします。下部には、通常、例と、両方の実装(および存在)の背後にある理由が表示されます。
この場合:
次のセクションは参考情報です。
標準出力をファイルにリダイレクトする
次の例では、現在のプロセスの標準出力を閉じ、標準出力を再割り当てしてpfd
で参照されるファイルに移動し、元のファイル記述子を閉じてクリーンアップします。
_#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...
_
次の例では、メッセージをstderr
からstdout
にリダイレクトします。
_#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...
_
なし。
dup()
およびdup2()
関数は冗長です。それらのサービスは、fcntl()
関数によっても提供されます。 IEEE Std 1003.1-2001のこのボリュームには、多くの既存のアプリケーションで使用されているため、主に歴史的な理由で含まれています。
表示されている短いコードセグメントの動作はdup2()
と非常に似ていますが、IEEE Std 1003.1-2001のこのボリュームで定義されている他の関数に基づく適合実装は、はるかに複雑です。少なくとも明らかなことは、ステップ間で呼び出され、ファイル記述子の割り当てまたは割り当て解除を行うことができるシグナルキャッチ関数の考えられる効果です。これは、信号をブロックすることで回避できます。
dup2()
関数は、fcntl()
によってタイプセーフでないバージョンで提供される機能のタイプセーフバージョンを提供するため、陳腐化とマークされていません。 POSIX Adaバインディングで使用されます。
dup2()
関数は、重要な領域で同期メカニズムとして使用するためのものではありません。
[EBADF]の説明では、fildesが範囲外の場合は、fildesが無効である場合に該当します。 fildes
と_fildes2
_の説明は異なります。なぜなら、_fildes2
_に関連する唯一の無効性は、範囲外であるかどうかだからです。つまり、dup2()
呼び出しが行われたときに_fildes2
_が開いているファイルを参照しているかどうかは関係ありません。
なし。
close()
、fcntl()
、open()
、IEEE Std 1003.1-2001のベース定義ボリューム、_<unistd.h>
_
問題1で最初にリリースされました。SVIDの問題1から派生。
実用的な例の1つは、出力メッセージをログファイルなどの他のストリームにリダイレクトすることです。 I/Oリダイレクトのサンプルコードを次に示します。
元の投稿を参照してください こちら
#include <stdio.h>
main()
{
int fd;
fpos_t pos;
printf("stdout, ");
fflush(stdout);
fgetpos(stdout, &pos);
fd = dup(fileno(stdout));
freopen("stdout.out", "w", stdout);
f();
fflush(stdout);
dup2(fd, fileno(stdout));
close(fd);
clearerr(stdout);
fsetpos(stdout, &pos); /* for C9X */
printf("stdout again\n");
}
f()
{
printf("stdout in f()");
}
シェルでのI/Oリダイレクトは、dup2/fcnltシステムコールを使用して実装される可能性が高いでしょう。
Dup2関数を使用して、$program 2>&1 > logfile.log
タイプのリダイレクトを簡単にエミュレートできます。
以下のプログラムは、stdoutとstderrの両方をリダイレクトします。つまり、dup2を使用して$program 2>&1 > output
の動作をエミュレートします。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int
main(void){
int close_this_fd;
dup2(close_this_fd = open("output", O_WRONLY), 1);
dup2(1,2);
close(close_this_fd);
fprintf(stdout, "standard output\n");
fprintf(stderr, "standard error\n");
fflush(stdout);
sleep(100); //sleep to examine the filedes in /proc/pid/fd level.
return;
}
vagrant@precise64:/vagrant/advC$ ./a.out
^Z
[2]+ Stopped ./a.out
vagrant@precise64:/vagrant/advC$ cat output
standard error
standard output
vagrant@precise64:/vagrant/advC$ ll /proc/2761/fd
total 0
dr-x------ 2 vagrant vagrant 0 Jun 20 22:07 ./
dr-xr-xr-x 8 vagrant vagrant 0 Jun 20 22:07 ../
lrwx------ 1 vagrant vagrant 64 Jun 20 22:07 0 -> /dev/pts/0
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 1 -> /vagrant/advC/output
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 2 -> /vagrant/advC/output