Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

リダイレクトでのdup関数の必要 性って?

453 views
Skip to first unread message

matsui888

unread,
Mar 7, 2005, 12:52:12 AM3/7/05
to
matsui888と申します。宜しくお願い致します。
Win2k+cygwinで学習してます。
参考書に

/* test.c */
#include<stdio.h>
int main(void){
printf("HelloWorld");
return 0;
}

$ ./test.exe > file

というリダイレクトについての説明で
標準出力のリダイレクトの振舞いについて、

close(1);
dup(fd); //既生成のディスクリプタを空いている1番に複製?
close(fd); // fdの評価値「3」は「1」になる?
write(1,…);

という処理が行われているとありました(コメント文は私の考え)。
複製の意味がイマイチわかりません。もし、fdディスクリプタの評価値が3の
時には
dup(fd);で
fdの評価値は1に変更されてしまうという事ですか?
でもclose(fd);としたら1番ディスクリプタが開放されてしまい、元に戻って
しまい
ますよね?

上記リストの動作は

close(1);
FILE *fp=fopne("pathname","w"); //1番ディスクリプタが空きなのでカーネ
ルに
よって1番がfp->fileに割当てられる
write(fp->file,…);

する事と同じと解釈していいんですかね(fp->fileはディスクリプタを表す)。
つまり、dup関数はディスクリプタの複製を作るではなく、生成させる関数と
呼ぶべ
きじゃないのかなと思ったのですが、、、

うーん、ディスクリプタのコピーってどういう意味かいまいちピンと来ませ
ん。


この動作を顕著に見て取れるリストをご紹介いただけませんでしょうか?

koun...@mbh.nifty.com

unread,
Mar 7, 2005, 7:44:50 AM3/7/05
to
"matsui888" <mats...@hotmail.com> wrote in message
news:d0gq6p$lf6$1...@caraway.media.kyoto-u.ac.jp...

> うーん、ディスクリプタのコピーってどういう意味かいまいちピンと来ませ
> ん。
>

私も十分には理解してないですが,例えば下の fd が hoge というファイルを
指しているとすると,

newfd = dup(fd)

で newfd も 同じ hoge というファイルを指すという意味だと思いますが。

適切な例かどうかは分かりませんが,

#include <stdio.h>
#include <fcntl.h>

int main (void)
{
int fd, tmp, n;
char * buf = "hello world\n";

for(n = 0; *(buf + n) != 0; n++);

fd = open("temp.txt", O_CREAT | O_WRONLY, S_IWUSR);
if (fd == -1) {
fprintf(stderr,"can't open temp.txt\n");
return -1;
}

close(1);
dup(fd);
//close(fd);

tmp = write(fd, buf, n);
if (tmp < 0)
perror("fd error");
tmp = write(1, buf, n);
if (tmp < 0)
perror("stdout error");
return 0;
}

上の
//close(fd);
部分のコメントをはずした時とはずさない時のtemp.txtを比べれば
てみてはどうでしょうか。

--
******************************
keizi kounoike
******************************

ku...@gssm.otsuka.tsukuba.ac.jp

unread,
Mar 7, 2005, 8:54:01 AM3/7/05
to
久野です。

mats...@hotmail.comさん:
> dup(fd); //既生成のディスクリプタを空いている1番に複製?

dupは「今あいている一番若い番号に複製する」という仕様に
なっています。なので、たとえば

0:X 1:Y 2:Z

という対応づけになっているのを

0:Y 1:Z 2:X

のように「番号を割り当て直したい」としますよね。それには

→ dup(0) → 0:X 1:Y 2:Z 3:X
→ close(0) → 0:- 1:Y 2:Z 3:X
→ dup(1) → 0:Y 1:Y 2:Z 3:X
→ close(1) → 0:Y 1:- 2:Z 3:X
→ dup(2) → 0:Y 1:Z 2:Z 3:X
→ close(2) → 0:Y 1:Z 2:- 3:X
→ dup(3) → 0:Y 1:Z 2:X 3:X
→ close(3) → 0:Y 1:Z 2:X

なんていう風にしてできるわけです。なお、Unixでは0が標準入力、1が
標準出力、2が標準エラー出力なので、何かを特定番号に割り当てたい
というのは結構あるわけです。

うまくできているというか、パズルみたいというか。 久野

ca...@xxx.kgc.co.jp

unread,
Mar 9, 2005, 6:08:13 AM3/9/05
to
"matsui888" <mats...@hotmail.com> writes:

> うーん、ディスクリプタのコピーってどういう意味かいまいちピンと来ませ
> ん。
>
>
> この動作を顕著に見て取れるリストをご紹介いただけませんでしょうか?

「UNIXカーネルの設計」 ISBN: 4320025512
の 5.13 に、これ以上は無いってくらいわかりやすく書いてありますよ。

5565 円か~~。いい本だけど高いなあ。

神田敏広

Masamichi Takatsu

unread,
Mar 7, 2005, 9:15:39 PM3/7/05
to
高津@ドーガです。

記事 <d0hmdp$1...@utogw.gssm.otsuka.tsukuba.ac.jp> で
kunoさんは書きました

> 0:X 1:Y 2:Z
> という対応づけになっているのを
> 0:Y 1:Z 2:X
> のように「番号を割り当て直したい」としますよね。

無駄にファイルディスクリプタを確保しない、という方針としては
パズルも楽しいですけど、

dup2を使って

fd0 = dup(0);
fd1 = dup(1);
fd2 = dup(2); → 0:X 1:Y 2:Z fd0:X fd1:Y fd2:Z
close(0);
close(1);
close(2); → 0:- 1:- 2:- fd0:X fd1:Y fd2:Z
dup2(fd1,0);
dup2(fd2,1);
dup2(fd0,2); → 0:Y 1:Z 2:X fd0:X fd1:Y fd2:Z
close(fd0);
close(fd1);
close(fd2); → 0:Y 1:Z 2:X

という感じにするのはどうでしょうか?
わかりやすさを優先です。

PROJECT TEAM DoGA 高津正道 ta...@doga.jp
TBD0...@nifty.ne.jp
PROJECT TEAM DoGAのホームページ → http://doga.jp/
3月8日(火) 今日のマーフィーの法則 [マックリスティーのコンピュータの公理]
バックアップファイルが、まともにとれていることはない。

Shinji KONO

unread,
Mar 10, 2005, 11:45:15 PM3/10/05
to
河野真治 @ 琉球大学情報工学です。

In article <0503081115...@XP.doga.jp>, Masamichi Takatsu <ta...@doga.jp> writes
> dup2を使って

システムコールの回数がなぁ。

まぁ、たいしたことないっちゃそうなんだけど。


---
Shinji KONO @ Information Engineering, University of the Ryukyus
河野真治 @ 琉球大学工学部情報工学科

ca...@xxx.kgc.co.jp

unread,
Mar 11, 2005, 3:08:29 AM3/11/05
to
ko...@ie.u-ryukyu.ac.jp (Shinji KONO) writes:

> > dup2を使って
>
> システムコールの回数がなぁ。

dup2 がシステムコールという前提で

dup2 は close もしてくれるから途中の close は不要ですね。
すると 9 回になり、久野版の 8 回に迫る勢いです。

久野版を dup2 で書き直すと

dup2(0, 3)
dup2(1, 0)
dup2(2, 1)
dup2(3, 2)
close(3)

で 5 回で済み、えらい倹約ぶりです。


> まぁ、たいしたことないっちゃそうなんだけど。

ですね

神田敏広

matsui888

unread,
Mar 14, 2005, 2:28:06 AM3/14/05
to
matsui888と申します。
ご回答有難うございます。


適切な例かどうかは分かりませんが,
>
> #include <stdio.h>
> #include <fcntl.h>


> 上の
> //close(fd);
> 部分のコメントをはずした時とはずさない時のtemp.txtを比べれば
> てみてはどうでしょうか。
有難うございます。

$ ./dup.exe
$ chmod 600 ./temp.txt
$ cat ./temp.txt
hello world
hello world

となりました。
close(1);

1番ファイルディスクリプタ⇔モニタ
の経路が断たれ、
dup(fd);

1番ファイルディスクリプタ⇔temp.txt
の経路が生成され、


tmp = write(fd, buf, n);

にて
fdファイルディスクリプタ⇔temp.txt
を利用して文字列"hello world\n"がtemp.txtに書き込まれ、


tmp = write(1, buf, n);

にて
1番ファイルディスクリプタ⇔temp.txt
を利用して文字列"hello world\n"がtemp.txtに書き込まれたのですね。

よく理解できました。コメントを外した場合には

$ rm ./temp.txt

$ ./dup.exe
fd error: Bad file descriptor

$ chmod 600 ./temp.txt

$ cat ./temp.txt
hello world

となりました。
dup(fd);
にて
1番ファイルディスクリプタ⇔temp.txt
の経路が生成され、
close(fd);
にて
fdファイルディスクリプタ⇔temp.txt
の経路が断たれたが
1番ファイルディスクリプタ⇔temp.txt
の経路はそのまま残っている。

で、上記のような出力結果になったのですね。
なるほど。。です。

>> dup(fd); //既生成のディスクリプタを空いている1番に複製?
> dupは「今あいている一番若い番号に複製する」という仕様に
> なっています。なので、たとえば

> 0:X 1:Y 2:Z
> という対応づけになっているのを
> 0:Y 1:Z 2:X

> のように「番号を割り当て直したい」としますよね。それには
> → dup(0) → 0:X 1:Y 2:Z 3:X
0番ファイルディスクリプタの端末ドライババッファ(この例ではX)を
3番ファイルディスクリプタをXにもリンクさせる。
通常はこのXはキーボードの事なので、
dup(0);
read(3,char *const,10);
という風に3番ファイルディスクリプタでも読み込めるようになるのですね。

> → close(0) → 0:- 1:Y 2:Z 3:X
> → dup(1) → 0:Y 1:Y 2:Z 3:X
> → close(1) → 0:Y 1:- 2:Z 3:X

> → dup(2) → 0:Y 1:Z 2:Z 3:X
> → close(2) → 0:Y 1:Z 2:- 3:X
> → dup(3) → 0:Y 1:Z 2:X 3:X
> → close(3) → 0:Y 1:Z 2:X
> なんていう風にしてできるわけです。
成る程。。分かり易いです。

> 「UNIXカーネルの設計」 ISBN: 4320025512
> の 5.13 に、これ以上は無いってくらいわかりやすく書いてありますよ。
> 5565 円か~~。いい本だけど高いなあ。

ご紹介有難うございます。
探してみたいと思います。

> dup2 がシステムコールという前提で
> dup2 は close もしてくれるから途中の close は不要ですね。
> すると 9 回になり、久野版の 8 回に迫る勢いです。

> 久野版を dup2 で書き直すと

> ですね
参考になります。
kounoikeさんのをこれで書き直すと

// close(1);
dup2(fd,1);
//close(fd);

ですね。これで
$ rm ./temp.txt
$ gcc -o dup dup.c
$ ./dup.exe
$ chmod 600 ./temp.txt
$ cat ./temp.txt
hello world
hello world

となり、
close(1);
dup(fd);
//close(fd);

の時と上手くいきました。

皆様、どうも有難うございました。

0 new messages