dup2 / dup-ファイル記述子を複製する必要があるのはなぜですか?


85

私はの使用を理解しようとしているdup2dup

マニュアルページから:

なぜそのシステムコールが必要なのですか?ファイル記述子を複製することの使用は何ですか?

ファイル記述子がある場合、なぜそのコピーを作成したいのですか?

dup2/dupが必要な場所について説明し、例を挙げていただければ幸いです。

ありがとう


またはなしでシェルの配管機能をどのように実装しますdupdup2?を呼び出しpipe(2)てから、ファイル記述子の1つdupをたとえばSTDIN_FILENO
Basile Starynkevitch 2012

回答:


48

dupシステム呼び出しは、既存のファイル記述子を複製し、同じ基になるI / Oオブジェクトを参照する新しいファイル記述子を返します。

Dupを使用すると、シェルは次のようなコマンドを実装できます。

2>&1は、記述子1の複製であるファイル記述子2をコマンドに与えるようにシェルに指示します(つまり、stderrとstdoutは同じfdを指します)。
今呼び出すためのエラーメッセージLSを非既存のファイルとの正しい出力LS上の既存のファイルはに表示TMP1のファイル。

次のサンプルコードは、パイプの読み取り端に接続された標準入力を使用してプログラムwcを実行します。

子は読み取り端をファイル記述子0に複製し、pのファイル記述子を閉じ、wcを実行します。wcが標準入力から読み取る場合、パイプから読み取ります。
これは、dupを使用してパイプを実装する方法です。dupを1回使用すると、パイプを使用して他の何かを構築できます。これがシステムコールの美しさです。すでに存在するツールを使用して次々に構築します。これらのツールは、他の何かなど..最後に、システムコールはカーネルで取得する最も基本的なツールです

乾杯:)


1
それでduplsプログラム自体ではなく、発信者にとって役立つのでしょうか?dupすでにファイルにアクセスできる場合、ls自体のようなプログラムで使用したことの利点はありますか?ここでは、たとえば、ハードコードされlsているエラーを書き込む2ので、のコンシューマーとしてオーバーライドする方法がありlsます。それは微妙な点ではないと思いますか?
ニシャント2016年

3
あなたのプログラム例は、と思われるバグを持っています。あなたは電話をかけてdup(p[STDIN])いますが、結果を捨てています。使うつもりでしたdup2(p[STDIN], 0)か?
Quuxplusone 2017

1
@Quuxplusonedupは、「プロセスで現在使用されていない最小番号の記述子」を返します。fd 0が閉じられたばかりなので、dup0を返すdup2必要があります。最低の空きfdを使用するのではなく、どのfdを使用するかを明示しているので、それをお勧めします。
Wodin 2017

@Wodin:ああ、OPが何を考えていたのかはあなたが正しいと思います。ただし、「閉じたばかり」は相対的なものであり、たとえば、ファイルを開いている可能性のある並行スレッドが存在すると、OPのコードが破損する可能性があることも正しいのでしょうか。
Quuxplusone 2017

@Quuxplusoneあなたが正しいと思いますが、はっきりとはわかりません。しかし、その場合、他の問題が発生します。他の場所から読み取りたいためにstdinを閉じてから、別のスレッドがファイルを開くと、fd 0になります。次にdup2を使用すると、他のスレッドが開いたfdが閉じられるため、他のスレッドが閉じます。これで、開いたファイルからの読み取り(および書き込み?)が行われます。とにかく、私が正しく覚えていればexec*、マルチスレッドプロセスから呼び出すべきではありません。しかし、私はスレッドの専門家ではありません:)
Wodin 2017

18

ファイル記述子を複製するもう1つの理由は、それをfdopen。とともに使用することです。fcloseに渡されたファイル記述子を閉じるfdopenため、元のファイル記述子を閉じたくない場合は、dup最初にそれを複製する必要があります。


fdopen()ファイル記述子を複製しないようです。ユーザースペースにバッファを作成するだけです。
user218867 2015

3
あなたは私の答えを読み間違えました。ポイントは、あなたがしたいことがあるdupに渡す前にFDfdopenので、fcloseそれを閉じます。
R .. GitHub STOP HELPING ICE 2015

1
@ theferrit32:FILEstdioインターフェースを介して既存の開いているファイルにアクセスするためのハンドルを割り当てる場合は、fcloseそのFILEハンドルの割り当てを解除するために呼び出す必要があります。基になる開いているファイルを使い続けたい場合、またはファイル記述子の元の「所有者」コードが使用するようなソフトウェアアーキテクチャの場合、渡された基になるファイル記述子も閉じるcloseという事実が問題になります。を使用して、同じ開いているファイルが渡される新しいファイル記述子を作成し、元のファイルを閉じないようにすることで、この問題を回避できます。fclosefdopendupfdopenfclose
R .. GitHub STOP HELPING ICE 2018年

1
重要なのは、fdopen()fdの所有権をコピーするのFILEではなく、に移動することです。これは、ユーザーが知っておくべきことです。オブジェクトfdに加えて使用可能なハンドルを保持する必要があるコンシューマーは、をFILE複製する必要がありfdます。それで全部です。
コンラッドマイヤー

1
@ConradMeyer:はい、それは非常に良い言い方ですFILE。所有権を移動した後、「所有権を移動」する操作はないことに注意してください。
R .. GitHub STOP HELPINGICE20年

4

dupは、プロセスからの出力をリダイレクトできるようにするために使用されます。

たとえば、プロセスからの出力を保存する場合は、出力を複製し(fd = 1)、複製したfdをファイルにリダイレクトしてから、フォークしてプロセスを実行し、プロセスが終了したら、再度リダイレクトします。 fdを出力に保存しました。


4

dup / dup2に関連するいくつかの点に注意してください

dup / dup2-技術的な目的は、1つのプロセス内で1つのファイルテーブルエントリを異なるハンドルで共有することです。(フォークしている場合、記述子は子プロセスでデフォルトで複製され、ファイルテーブルエントリも共有されます)。

つまり、dup / dup2関数を使用して、1つの開いているファイルテーブルエントリに対して異なる属性を持つ可能性のある複数のファイル記述子を持つことができます。

(現在、FD_CLOEXECフラグのみがファイル記述子の唯一の属性であるように見えますが)。

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

違いは(最後に)-2つの関数呼び出しが含まれるため、dup2とfcntl closeの後にfcntlが続くいくつかのerrno値は別として、競合状態を引き起こす可能性があります。

詳細はhttp://pubs.opengroup.org/onlinepubs/009695399/functions/dup.htmlから確認できます。

使用例-

シェルでジョブ制御を実装する際の興味深い例の1つで、dup / dup2の使用を以下のリンクで確認できます。

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.