web-dev-qa-db-ja.com

実際の例ではdupまたはdup2を使用します

dup/dup2 はありますが、いつ使用されるのかわかりません。

実用的な例はありますか?

ありがとう。

62
pierrotlefou

1つの使用例は、I/Oリダイレクトです。このためには、子プロセスをフォークし、stdinまたはstdoutファイル記述子(0および1)を閉じてから、選択した別のファイル記述子でdup()を実行します。ケース0または1。

これを使用すると、アプリケーションを認識していない可能性のある子プロセスを実行でき、子がstdoutに書き込む(または設定したものは何でもstdinから読み取る)たびに、代わりに提供されたfiledescriptorにデータが書き込まれます。

シェルはこれを使用して、パイプなどのコマンドを実装します。 /bin/ls | more 1つのプロセスの標準出力を他のプロセスの標準入力に接続する。

60
Alfonso

Dupとdup2を理解するのに最適なシナリオは、リダイレクトです。
最初に知っておくべきことは、システムには、入力と出力を処理する3つのデフォルトのファイルID(または出力または入力ソースを示す変数)があることです。 stdinstdoutstderrであり、整数では012fprintfcoutなどのほとんどの関数は、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 [〜#〜]

  1. これは直感的な説明を提供するだけで、マンページまたは詳細情報を確認する必要がある場合があります。実際、ここでは「コピー」と言いますが、すべてをコピーしているわけではありません。

  2. ここでのファイルIDは、ファイルのハンドラーを参照しています。上記のファイル記述子は、レコードファイルの情報の構造体です。

22
ZijunLost

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から派生。

9
Tim Post

実用的な例の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()");
}
5
vinit dhatrak

シェルでの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
1
maitreyak