69

dup/dup2が何をするかは知っていますが、いつ使用されるかわかりません。

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

ありがとう。

4

5 に答える 5

70

使用例の 1 つは、I/O リダイレクションです。このために、子プロセスをフォークし、stdin または stdout ファイル記述子 (0 および 1) を閉じてから、選択した別のファイル記述子で dup() を実行します。このファイル記述子は、利用可能な最も低いファイル記述子にマップされます。ケース 0 または 1。

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

/bin/ls | moreシェルはこれを使用して、たとえば、あるプロセスの stdout を他のプロセスの stdin に接続することにより、パイプを使用してコマンドを実装します。

于 2009-11-12T07:44:30.950 に答える
10

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、範囲外であるかどうかです。つまり、呼び出しfildes2時に開いているファイルを参照するかどうかは問題ではありません。dup2()

今後の方向性

なし。

こちらもご覧ください

close(), fcntl(), open(), IEEE Std 1003.1-2001 の Base Definitions ボリューム、<unistd.h>

変更履歴

第 1 号で最初にリリースされました。SVID の第 1 号から派生しました。

于 2009-11-12T07:44:50.187 に答える
5

実用的な例の 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()");
}
于 2009-11-12T08:24:51.323 に答える
3

シェルでの I/O リダイレクションは、dup2/fcnlt システム コールを使用して実装される可能性が最も高いでしょう。

$program 2>&1 > logfile.logdup2 関数を使用して、リダイレクトのタイプを簡単にエミュレートできます。

以下のプログラムは、stdout と stderr の両方をリダイレクト$program 2>&1 > outputします。つまり、dup2 を使用する動作をエミュレートします。

#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
于 2018-06-20T22:45:54.287 に答える