サーバ側ではディスクリプタsocにパケットが届いているかをチェックする為に、
int n;
fd_set mask;
FD_ZERO(&mask);
FD_SET(0,&mask);
FD_SET(soc,&mask);
select(soc+1,&mask,NULL,NULL,NULL);
n=FD_ISSET(soc,&mask);
として返値nを吟味する事でsocにパケットが届いているかを知る事が出来るのですよ
ね。
つまり、
$ ulimit -a | grep max
max user processes (-u) 63
の場合、上記のコードは
mask.fds_bits[1]、mask.fds_bit[0]、の64ビット分を「0」にする。
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000
↓
0番ディスクリプタとsoc番ディスクリプタを「1」にする。
(下記例はsocの評価値が「4」の場合)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001
0001
↓
0番ディスクリプタ~soc番ディスクリプタにパケットが届いているかを調査する。
届いているディスクリプタ(ビット目)だけ「1」にして、届いていないものは全て
「0」に書換える。
(例 4番ディスクリプタのみに届いている場合は
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001
0000
0番ディスクリプタのみに届いている場合は
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0001
3番ディスクリプタのみに届いている場合は
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
1000)
↓
実際に4番ディスクテリプタに届いているかの判定は最後にFD_ISSET関数の返値に
よって知りうる事ができる。
nの値が「1」ならsocディスクリプタにパケットが届いている。「0」なら届いていな
い。
という具合の処理になるのですよね?
(勘違いしてましたら、ご指摘ください)
としますと
FD_ZERO(&mask);
FD_SET(0,&mask);
FD_SET(soc,&mask);
は不要なんじゃないでしょうか?
select(soc+1,&mask,NULL,NULL,NULL);
n=FD_ISSET(soc,&mask);
だけで十分なような気がするのですが、勘違いしてましたら、ご指摘ください。
kaor...@plum.freemail.ne.jpさん:
> select(soc+1,&mask,NULL,NULL,NULL);
> n=FD_ISSET(soc,&mask);
> だけで十分なような気がするのですが、勘違いしてましたら、ご指摘ください。
maskの中でビットが「1」になっているものに対応するチャネルのみ
をselectは監視しますよね。
だから初期化は必要なんじゃないですか? 久野
> maskの中でビットが「1」になっているものに対応するチャネルのみ
> をselectは監視しますよね。
>
> だから初期化は必要なんじゃないですか? 久野
えーと、select関数に関する
『届いているディスクリプタ(ビット目)だけ「1」にして、届いていないものは全て
「0」に書換える。』
という解釈が間違っているんですね。
(一応、アチコチの参考書を調べてはみたのですがよく理解できませんで)
久野さまのお話だと
select(soc+1,&mask,NULL,NULL,NULL);は
0番ディスクリプタ~soc番ディスクリプタ
の内でビットが立っているものに関してだけのバケット到着の有無を調査するんです
かね。
すると、
1番ディスクリプタ~(soc-1)番ディスクリプタ
はFD_ZERO、FD_SET関数でビットは立てられていないのでselect関数では
1番ディスクリプタ~(soc-1)番ディスクリプタ
にパケットが届いていようがいまいが
何にもしないという解釈で宜しいんでしょうか。
としますと、前記事において
『3番ディスクリプタのみに届いている場合は
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
1000)』
は間違いで
『3番ディスクリプタのみに届いている場合は
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000』
という風に3番ディスクリプタにビットは立たないという事になるんですね。
kaor...@plum.freemail.ne.jpさん:
> (一応、アチコチの参考書を調べてはみたのですがよく理解できませ
> んで)
manページを読むべきなんだと思いますが。私もmanページを読んでい
るだけですし。
> の内でビットが立っているものに関してだけのバケット到着の有無を
> 調査するんですかね。
と思いますが。
> はFD_ZERO、FD_SET関数でビットは立てられていないのでselect関数
> では1番ディスクリプタ~(soc-1)番ディスクリプタにパケットが届い
> ていようがいまいが何にもしないという解釈で宜しいんでしょうか。
そうなってないと、調べたくもないディスクリプタまで調べられてし
まって使いにくいじゃないですか。
> 『3番ディスクリプタのみに届いている場合は
> という風に3番ディスクリプタにビットは立たないという事になるんですね。
え、最初に1だったもののうち、実際にデータが到着したものは1のま
ま残り、到着しなかったものは0になるんじゃないの。
だから届いてるなら1は立つと思うけど。 久野
ku...@gssm.otsuka.tsukuba.ac.jp wrote:
> manページを読むべきなんだと思いますが。私もmanページを読んでい
> るだけですし。
ですね。manページが第1に調べるべきものでしょう。
select(2)にかんしては、linux/FreeBSD/NetBSD見比べてみましたが、
特に大きな差異はないようだし(linuxのmanページは時としてBSDより
かなり簡略されてて居ることがあるのですが、selectに関しては
linuxのほうが分かりやすいかもしれません。BSDのほうは「ディスクリプタのア
ドレス」という表現が出てきて分かりにくい)。
ただ、頭から字を追って読んでもわけが分からないかも。
selectは複数のファイルディスクリプタを並行に見張るシステム
コールであるということを頭において読むと、理解できると思います。
P.S.
「WEBにある解説記事よりmanページのほうがコンパクトで正確で
わかりやすい」と思えるようになったら、もう初心者の気持ちが
分からなくなっている証拠だったりして。
--
齊藤明紀 saitoh at kankyo-u ac jp
In article <cp25gl$alc$1...@caraway.media.kyoto-u.ac.jp>
"KMochida" <kaor...@plum.freemail.ne.jp> writes:
> $ ulimit -a | grep max
> max user processes (-u) 63
>
> の場合、上記のコードは
>
> mask.fds_bits[1]、mask.fds_bit[0]、の64ビット分を「0」にする。
fd_set のビット数とmax user processesは関係ないので、ビット数を知りたければ
システムヘッダファイルで、FD_SETSIZE の定義を探すのが良いかと思います。
printf("%d\n",sizeof(fd_set)*8); でもいいですけど。
--
tksotn
> そうなってないと、調べたくもないディスクリプタまで調べられてし
> まって使いにくいじゃないですか。
>> 『3番ディスクリプタのみに届いている場合は
>> という風に3番ディスクリプタにビットは立たないという事になるんですね。
> え、最初に1だったもののうち、実際にデータが到着したものは1のま
> ま残り、到着しなかったものは0になるんじゃないの。
> だから届いてるなら1は立つと思うけど。 久野
分かってきました。
とりあえず、実験的してみました。
各関数処理後のビットがどうなっているか逐一吐かせてみました。
FD_ZERO(&mask);
↓
mask.fds_bits[1]、mask.fds_bit[0]、の64ビット分を「0」にする。
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000
↓
FD_SET(0,&mask);
↓
mask.fds_bits[1]、mask.fds_bit[0]、の0ビット目を「1」にする。
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0001
↓
FD_SET(4,&mask);
↓
mask.fds_bits[1]、mask.fds_bit[0]、の4ビット目を「1」にする。
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001
0001
↓
FD_SET(9,&mask);
(select関数での有効ビット幅外ではどうなるか観察する為に更に9ビット目を立てて
みる)
↓
mask.fds_bits[1]、mask.fds_bit[0]、の9ビット目を「1」にする。
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0001
0001
↓
select(4+1,&mask,NULL,NULL,NULL);
↓
selectの返値は1であった
(0~4番ディスクリプタの内、少なくともひとディスクリプタにバケットが到達した
と分かる)。
↓
mask.fds_bits[1]、mask.fds_bit[0]
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001
0000
となりました
(有効ビット幅外である9番ディスクリプタも「0」にされちゃいました)。
、、、という事は
select(n+1,&mask,NULL,NULL,NULL);は
0番~n番ディスクリプタでパケットが到達しているディスクリプタでしかも、予め
ビットが立っているディスクリプタを「1」にする(勿論、複数のディスクリプタがこ
の用件を満たしてれば複数のディスクリプタが1となる)。
そして、それ以外のディスクリプタ、つまり、
最初から「0」になっているディスクリプタ、パケットが到達していないディスクリ
プタ、有効ビット幅外のディスクリプタは全て「0」にしてしまう
のですね。
> かなり簡略されてて居ることがあるのですが、selectに関しては
> linuxのほうが分かりやすいかもしれません。BSDのほうは「ディスクリプタのア
> ドレス」という表現が出てきて分かりにくい)。
> ただ、頭から字を追って読んでもわけが分からないかも。
> selectは複数のファイルディスクリプタを並行に見張るシステム
> コールであるということを頭において読むと、理解できると思います。
> P.S.
> 「WEBにある解説記事よりmanページのほうがコンパクトで正確で
> わかりやすい」と思えるようになったら、もう初心者の気持ちが
> 分からなくなっている証拠だったりして。
有難うございます。
manの方は読んでて混乱してきて、ついイラストも載っている書籍やWEBの解説を読ん
でしまいます。
manで読めるようになりたいと思います。
> fd_set のビット数とmax user processesは関係ないので、ビット数を知りたけれ
ば
> システムヘッダファイルで、FD_SETSIZE の定義を探すのが良いかと思います。
> printf("%d\n",sizeof(fd_set)*8); でもいいですけど。
cygwinでは
$ ulimit -a | grep max
max user processes (-u) 63
で
printf("%d\n",sizeof(fd_set)*8);
を試すと「64」になりましたのですっかり勘違いしておりました。
因みに、RedHat9上では
$ uname -a
Linux hoge.foo.dydnd.net 2.4.20-8 #1 Thu Mar 13 17:54:28 EST 2003 i686 i686
i386 GNU/Linux
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 7168
virtual memory (kbytes, -v) unlimited
となっていて、
printf("%d\n",sizeof(fd_set)*8);
を試すと「1024」となりました。でもfd_set のビット数はopen files数とも違うん
ですね。
飽くまで、FD_SETSIZEで定義されている値なのですね。