関数仕様
書式
|
1 2 3 4 5 |
#include <unistd.h> int dup(int oldfd); int dup2(int oldfd, int newfd); |
引数
| oldfd | 複製元のファイル記述子 |
| newfd | 複製によって新たに作るファイル記述子 |
戻り値
| 0以上の値 | 複製されたファイル記述子(複製に成功) |
| -1 | エラーが発生、errno に適切に要因を設定(複製に失敗) |
参考
代表的なエラー要因は EINVAL で、oldfd と newfd が同じ値であることを意味します。
機能
- dup() は、ファイル記述子 oldfd の複製を作成し、最も小さい未使用のファイル記述子を返す
- dup2() は、基本は dup() と同じですが、newfd で指定した番号のファイル記述子を返す
既に open しているファイル記述子を指定した場合は、元の記述子は自動的に close される。
どのような時に使うのか?
プロセス間通信を行いたい時によく使用します。
例えば、ファイル記述子は 0=標準入力、1=標準出力、2=標準エラー出力 となっていることが一般的です。
そこに 3=プロセス間通信 というルールを設定し、以下のように子プロセスを立ち上げると、
簡単にプロセス間通信を行うことができるようになります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
int fds[2]; if (pipe(fds) < 0) return -1 pid = fork(); if (pid > 0) { /* 親プロセス */ /* fds[0] を使って子プロセスと通信する */ } else if (pid == 0) { /* 子プロセス */ dup2(fds[1], 3); close(fds[1]); /* exec 後、fd=3 を使って親プロセスと通信する */ /* exec 等 */ } |
関連
子プロセスを生成する fork() については、「fork関数の使い方」にまとめています。
注意すること
注意ポイント
dup2() の引数 newfd が指定できる範囲を超えていた場合の errno は、システムによって異なる
newfd の値が値域を超えていた場合は、EBADF を返すシステムと EINVAL を返すシステムがある。
エラー処理を行う場合は、注意が必要です。
サンプルプログラム
echo を実行し、出力内容をリダイレクトして test.txt に書き込むサンプルです。
動作イメージ
$ echo "Hello World!" > test.txt
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main(void) { int fd; char *argv[3]; extern char **environ; /* リダイレクト先のファイルを用意 */ if ((fd = open("test.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) { perror("open"); return -1; } /* 1=標準出力 に割り当てる */ if (dup2(fd, 1) < 0) { perror("dup2"); close(fd); return -1; } close(fd); /* echo を実行する */ argv[0] = "echo"; argv[1] = "Hello World!"; argv[2] = NULL; execve("/bin/echo", argv, environ); perror("execve"); return -1; } |
実行結果確認
$ cat test.txt
Hello World!