DUP
Section: Linux Programmer's Manual (2)
Updated: 2020-11-01
Index
JM Home Page
roff page
 
名前
dup, dup2, dup3 - ファイルディスクリプターを複製する
 
書式
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
#define _GNU_SOURCE             /* feature_test_macros(7) 参照 */
#include <fcntl.h>              /* 定数 O_* の定義の取得 */
#include <unistd.h>
int dup3(int oldfd, int newfd, int flags);
 
説明
dup() システムコールは、 ファイルディスクリプター oldfd のコピーを作成し、 最も小さい番号の未使用のファイルディスクリプターを
新しいディスクリプターとして使用する。
成功が返された場合には、 古いファイルディスクリプターと新しいファイルディスクリプターは 互いに可換なものとして使うことができる。
2つのファイルディスクリプターは同じファイル記述 (description)  (open(2)  参照)
を参照しており、したがってファイルオフセットやファイル状態フラグが 共有される。例えば、一方のファイルディスクリプターに対して lseek(2)
を使ってファイルオフセットを変更した場合、もう一方のファイルディスクリプターの オフセットも変化する。
2つのファイルディスクリプターはファイルディスクリプターフラグ (close-on-exec flag)  を共有しない。複製されたディスクリプターの
close-on-exec flag (fcntl(2)  参照) は off となる。
 
dup2()
dup2() システムコールは dup() と同じ処理を実行するが、
番号が最も小さい未使用のファイルディスクリプターを使用する代わりに、
newfd で指定されたファイルディスクリプター番号を使用する。
ファイルディスクリプター newfd が以前にオープンされていた場合には、
黙ってそのファイルディスクリプターをクローズしてから再利用する。
ファイルディスクリプター newfd をクローズして再利用する処理は
アトミック(不可分)に実行される。これは重要な点である。 なぜなら、
等価な機能を close(2) と dup() を使って実装しようとすると、
2 つの処理の間に newfd が再利用されてしまうという、
競合状態にさらされることになるからだ。
このような再利用が起こるのは、
メインプログラムがファイルディスクリプターを割り当てる
シグナルハンドラーにより割り込まれたり、並行動作するスレッドが
ファイルディスクリプターを割り当てたりすることがあるからだ。
以下の点について注意すること:
- *
 - 
oldfd が有効なファイルディスクリプターでない場合、その呼び出しは失敗し、 newfd はクローズされない。
 - *
 - 
oldfd が有効なファイルディスクリプターで、 newfd が oldfd と同じ値の場合、 dup2()  は何もせず、
newfd を返す。
 
 
dup3()
dup3()  は dup2()  と同じだが、以下の点が異なる。
- *
 - 
呼び出し元が、新しいファイルディスクリプターに対して close-on-exec フラグを強制的に設定することができる。 これを行うには、
flags に O_CLOEXEC を指定する。 このフラグが役に立つ理由については、 open(2)  の O_CLOEXEC
フラグの説明を参照のこと。
 - *
 - 
oldfd が newfd と同じ場合、 dup3()  は EINVAL エラーで失敗する。
 
 
返り値
成功すると、これらのシステムコールは新しいファイルディスクリプターを返す。 エラーの場合、-1 を返し、 errno を適切に設定する。
 
エラー
- EBADF
 - 
oldfd がオープンされたファイルディスクリプターではない。
 - EBADF
 - 
newfd がファイルディスクリプターとして許可されている範囲ではない (getrlimit(2) の RLIMIT_NOFILE
の議論を参照)。
 - EBUSY
 - 
(Linux のみ)  open(2)  や dup()  との競合状態の場合に、 dup2()  や dup3()
はこのエラーを返すかもしれない。
 - EINTR
 - 
dup2()  や dup3()  の呼び出しがシグナルにより割り込まれた。 signal(7)  参照。
 - EINVAL
 - 
(dup3())  flags に無効な値が入っている。
 - EINVAL
 - 
(dup3()) oldfd が newfd と同じであった。
 - EMFILE
 - 
The per-process limit on the number of open file descriptors has been
reached (see the discussion of RLIMIT_NOFILE in getrlimit(2)).
 
 
バージョン
dup3()  はバージョン 2.6.27 で Linux に追加された。 glibc によるサポートはバージョン 2.9 以降で利用できる。
 
準拠
dup(), dup2(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
dup3()  は Linux 固有である。
 
注意
newfd が範囲を超えた時に返されるエラーは、 dup2()  と fcntl(..., F_DUPFD, ...)
では異っている。 dup2()  が F_DUPFD と同じように EINVAL を返すシステムもある。
newfd がオープンされていた場合、
close(2) 時に報告されることになるエラーはすべて失われる。
これが心配で、シングルスレッドかつシグナルハンドラーで
ファイルディスクリプターを割り当てるようなプログラムでない場合には、
正しい方法は dup2() を呼び出す前に
newfd をクローズ「しない」ことである。
なぜなら、上で説明した競合状況があるからである。
代わりに、以下のようなコードが使用できることだろう。
/* あとで close() エラーをチェックするのに使用できる
   ように 'newfd' の複製を取得する。 EBADF エラーは
   'newfd' がオープンされていないことを意味する。 */
tmpfd = dup(newfd);
if (tmpfd == -1 && errno != EBADF) {
    /* 予期しない dup() のエラーを処理する */
}
/* アトミックに 'oldfd' を 'newfd' に複製する */
if (dup2(oldfd, newfd) == -1) {
    /* dup2() のエラーを処理する */
}
/* ここでもともと 'newfd' で参照されていたファイルの
   close() エラーをチェックする */
if (tmpfd != -1) {
    if (close(tmpfd) == -1) {
        /* close からのエラーを処理する */
    }
}
 
関連項目
close(2), fcntl(2), open(2), pidfd_getfd(2)
 
この文書について
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は
https://www.kernel.org/doc/man-pages/ に書かれている。
 Index
- 名前
 - 
 - 書式
 - 
 - 説明
 - 
- dup2()
 - 
 - dup3()
 - 
 
 - 返り値
 - 
 - エラー
 - 
 - バージョン
 - 
 - 準拠
 - 
 - 注意
 - 
 - 関連項目
 - 
 - この文書について
 - 
 
This document was created by
man2html,
using the manual pages.
Time: 16:46:41 GMT, November 24, 2023