dup()
dup()
(duplicate) は、既存のファイル記述子のコピーを作成するために使用される UNIX システム コールです。この新しいファイル記述子は、多くの点で元のファイル記述子と同一です。同じファイル テーブル エントリを共有します。つまり、同じファイル、ソケット、または他の I/O チャネルを指し、同じファイル オフセット、アクセス権を共有します。 、など。
関数プロトタイプ
dup()
関数のプロトタイプは次のとおりです。
#include <unistd.h>
int dup(int oldfd);
ここでoldfd
、 はコピーされる既存のファイル記述子です。
戻り値
成功した場合は新しいファイル記述子が返され、失敗した場合は -1 が返されます。
特定の行動
- Smallest available descriptor :
dup()
新しいファイル記述子として現在利用可能な最小の整数値を返します。 - ファイル ステータス フラグ: 新しいファイル記述子は、独自の独立したファイル ステータス フラグのセット (
FD_CLOEXEC
など) を持ちますが、ファイル オフセットやアクセス モード (読み取り、書き込み、読み取り/書き込み) を含む他のすべてのステータスを共有します。 - 共有ロックとその他の状態: 新旧のファイル記述子は同じファイル テーブル エントリを共有するため、ファイル ロック、動作モード、ファイル オフセットなども共有されます。
例
dup()
標準入力、出力、エラー ストリームをリダイレクトするためによく使用されます。たとえば、プロセス内で、標準出力 (通常はファイル記述子 1) をファイルにリダイレクトしたい場合があります。これは、次の手順に従って行うことができます。
open()
ファイルを開いてそのファイル記述子を取得するために使用します。dup()
このファイル記述子をコピーし、標準出力ファイル記述子を上書きするために使用します。
close()
機能を組み合わせたりdup()
、機能を利用したりする2通りの操作が可能ですdup2()
。
方法 1
I/O リダイレクトを実行するために使用close()
およびdup()
組み合わせることは、より低レベルで直接的な方法です。以下は、標準出力 (ファイル記述子 1) をファイルにリダイレクトする方法を示す簡単な例です。
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
// 打开一个文件
int fd = open("output.txt", O_WRONLY | O_CREAT, 0666);
if (fd < 0) {
perror("open");
return 1;
}
// 关闭标准输出(文件描述符1)
close(1);
// 使用dup复制fd,这将返回最低可用的文件描述符,即刚刚关闭的1
int newfd = dup(fd);
if (newfd < 0) {
perror("dup");
return 1;
}
// 此时,printf的输出将写入到"output.txt"
printf("Hello, world!\n");
// 关闭文件描述符
close(fd);
return 0;
}
ここでの手順は次のとおりです。
open()
ファイルを開いてファイル記述子を取得するために使用しますfd
。- クローズ標準出力 (ファイル記述子 1)を使用します
close(1)
。 dup(fd)
使用可能な最も低いファイル記述子へのコピーを使用しますfd
。これは、標準出力 (ファイル記述子 1) が閉じられたばかりであるため、dup()
新しいファイル記述子として 1 が返されるためです。
ここで、標準出力 (ファイル記述子 1) が にリダイレクトされたためoutput.txt
、標準出力 (たとえば、 経由printf()
) に書き込まれたすべてのデータはそのファイルに書き込まれます。
このアプローチの利点は、単純で明確であることですが、欠点は、を呼び出すdup()
前にターゲット ファイル記述子が適切に閉じられていることを確認する必要があることです。これは通常は問題ありませんが、より複雑なプログラムではエラーや一貫性のない動作が発生する可能性があります。dup2()
したがって、ファイル記述子のコピーと置換のより安全で一貫した方法を提供するため、多くのプログラムでこれが好まれます。
方法 2
dup2()
標準出力をファイルにリダイレクトする方法を示す簡単な例を次に示します。
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
// 打开一个文件
int fd = open("output.txt", O_WRONLY | O_CREAT, 0666);
if (fd < 0) {
perror("open");
return 1;
}
// 将标准输出(文件描述符1)重定向到fd指向的文件
if (dup2(fd, 1) < 0) {
perror("dup2");
return 1;
}
// 此时,printf的输出将写入到"output.txt"
printf("Hello, world!\n");
// 关闭文件描述符
close(fd);
return 0;
}
この例では、dup2(fd, 1)
呼び出しは標準出力を (まだ閉じていない場合) 閉じてコピーしfd
、それを新しい標準出力にします。したがって、標準出力に書き込むその他の関数を呼び出すとprintf()
、出力は「output.txt」ファイルに書き込まれます。
ここで、新しいファイル記述子 (この場合は標準出力、ファイル記述子 1)dup2()
が古いファイル記述子 (この場合は ) とfd
同じファイルまたは他のリソースを指すことが保証されます。したがって、I/O リダイレクトを実装する便利な方法を提供します。