K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[318] 端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:chisato
2007/02/20 02:13:25

select関数についての振舞いについて調べています。 (Win2k+Cygwin) #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <sys/types.h> #include <curses.h> #include <signal.h> #include <unistd.h> //=================== void session_loop(){ fd_set mask; FD_ZERO(&mask); FD_SET(0,&mask); fd_set readOK; int width=1; char c; printf("う\n"); while(1){ printf("あ\n"); readOK=mask; printf("こwidth=%d\n",width); select(width,(fd_set *)&readOK,NULL,NULL,NULL); printf("け\n"); if ( FD_ISSET(0, &readOK ) ){ printf("い\n"); c=getchar(); //getcharはバッファリングあり関数 printf("c=%c\n",c); printf("さ\n"); } } } //================= int main(void){ session_loop(); return 0; } というリストで 端末ドライババッファやstdinバッファの振舞いについて学習しています。 端末ドライバにバッファリングされた文字群がgetchar関数のread要求とかでstdinバッファに排出される様子や stdinバッファの文字群がgetchar関数の読込み毎に減っていく様子を垣間見たく思っています。 端末ドライバのバッファやstdinバッファの中身を覗くにはどうすればいいのでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[319] Re:端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:774RR
2007/02/20 02:13:25

http://www3.realint.com/cgi-bin/tarticles.cgi?pointc2+3409 ここの人ですか? せっかく「とても適切でわかりやすい」回答があるのですから、 100回くらい繰り返して読むべきです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[320] Re:端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:(ぱ)
2007/02/20 02:13:25

 掲示板では一般にマルチポストは嫌われます。  ただ、今回の例だと、時期がずれていて、質問内容も違うので、マルチポストに 当たるかどうかはわかりません。が、この手の掲示板を見ている人は、同じような ジャンルの掲示板は見ていることが多い、ということは意識している必要があると 思います。かずまさんも、たまにこの掲示板にも登場されます。 >select関数についての振舞いについて調べています。 端末ドライババッファとstdinバッファの振舞いについて調べるのに、 わざわざselectを使う必要があるのでしょうか。もちろん別にselectでもいいですが、 getchar()とputchar()でもよいような。 ... >端末ドライバのバッファやstdinバッファの中身を覗くにはどうすれば >いいのでしょうか?  端末ドライバのバッファは覗けないと思います(少なくとも標準的な方法では)。  標準入力のバッファは、FILE構造体に紐づいていますから、stdio.hから 調べればよいでしょう。  私の環境(gcc (GCC) 3.4.2 (mingw-special))ではこうなっていました。 typedef struct _iobuf { char* _ptr; int _cnt; char* _base; int _flag; int _file; int _charbuf; int _bufsiz; char* _tmpfname; } FILE;  _baseがバッファの根元を押さえ、_cntが現在格納されているデータのサイズだと 想像し(外しているかも)、こんなプログラムを書いてみました。 #include <stdio.h> void dump_buffer(FILE *fp) { int i; printf("["); for (i = 0; i < fp->_cnt; i++) { putchar(fp->_base[i]); } printf("]\n"); } int main(void) { int c; while ((c = getchar()) != EOF) { dump_buffer(stdin); putchar(c); } } [実行結果] C:\ctest>buffertest aaa [aaa] a[aa] a[a] a[] bbb [bbb] b[bb] b[b] b[]  それっぽく動いているように見えます。  重要なのは、標準入出力ライブラリの関数は、そのバッファリングのメカニズムを 含め、普通にCで、システムコールの上に実装されている、ということです。 実装を想像すると、理解が深まると思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[323] Re:端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:chisato
2007/02/20 02:13:25

ご回答大変有難うございます。 > 掲示板では一般にマルチポストは嫌われます。 マルチだと思われたのならお詫び致します。m(_ _)m >  ただ、今回の例だと、時期がずれていて、質問内容も違うので、マルチポストに > 当たるかどうかはわかりません。 そう思っていただければ大変助かります。m(_ _)m > が、この手の掲示板を見ている人は、同じような > ジャンルの掲示板は見ていることが多い、ということは意識している必要があると > 思います。かずまさんも、たまにこの掲示板にも登場されます。 今後、誤解が生じませぬよう成るべく異なるサンプルリストを提示するよう心がけま す。 >>select関数についての振舞いについて調べています。 > 端末ドライババッファとstdinバッファの振舞いについて調べるのに、 > わざわざselectを使う必要があるのでしょうか。もちろん別にselectでもいいです > が、 > getchar()とputchar()でもよいような。 そうですか。参考にしてみます。ただ、最近、select関数を知ったのでちょっと使っ てみたくなりまして。 >  端末ドライバのバッファは覗けないと思います(少なくとも標準的な方法では)。 >  標準入力のバッファは、FILE構造体に紐づいていますから、stdio.hから > 調べればよいでしょう。 >  私の環境(gcc (GCC) 3.4.2 (mingw-special))ではこうなっていました。 : > > [実行結果] > C:\ctest>buffertest > aaa これはエコーバックですよね。 > [aaa] これはdump_buffer関数でのputchar、printf出力ですね。 > a[aa] aが一回だけ入力されているのにこのようになるのですかね??
[この投稿を含むスレッドを表示] [この投稿を削除]
[324] Re:端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:(ぱ)
2007/02/20 02:13:25

まず前回のコードにポカがあったので再掲します。ついでに色々いじりました。 > _baseがバッファの根元を押さえ、_cntが現在格納されているデータのサイズだと >想像し(外しているかも)、こんなプログラムを書いてみました。 baseはおそらくバッファの根元を押さえているのでしょうが、バッファから 1文字消費されるたびに中身を移動させていくとは思えないので、 おそらく環状バッファか何かになっていて、現在バッファリングされている 内容の先頭は_ptrが抑えているのでしょう。 というわけで修正プログラムです。 #include <stdio.h> void dump_buffer(FILE *fp) { int i; printf("["); for (i = 0; i < fp->_cnt; i++) { if (fp->_ptr[i] == '\n') { printf("<\\n>"); } else { putchar(fp->_ptr[i]); } } printf("]\n"); } int main(void) { int c; for (;;) { dump_buffer(stdin); c = getchar(); if (c == EOF) break; putchar(c); } return 0; } うちの環境での実行結果。 C:\ctest>buffer [] abcdefg a[bcdefg<\n>] b[cdefg<\n>] c[defg<\n>] d[efg<\n>] e[fg<\n>] f[g<\n>] g[<\n>] [] さて、 >> C:\ctest>buffertest >> aaa >これはエコーバックですよね。 そうです。 >> [aaa] >これはdump_buffer関数でのputchar、printf出力ですね。 そうです。 >> a[aa] >aが一回だけ入力されているのにこのようになるのですかね?? ここに誤解があります。ここで左端に出ている[]に入らないaは、 エコーバックではなく、main()の中でputchar()されている文字です。 つまり、手で「aaa」と入力すると、バッファから1文字ずつ消費しながら putchar()している、という様子を示しているわけです。 # でも、前回のプログラムに「abc」と入れると、変な出方をするのでした(^^;
[この投稿を含むスレッドを表示] [この投稿を削除]
[325] Re:端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:chikato
2007/02/20 02:13:25

遅くなりまして申し訳有りません。 > というわけで修正プログラムです。 : > return 0; > } 大変有難うございます。 でもコンパイルすると $ gcc -o test5 test5.c test5.c: In function `dump_buffer': test5.c:7: error: structure has no member named `_cnt' test5.c:8: error: structure has no member named `_ptr' test5.c:11: error: structure has no member named `_ptr' となってしまい、プログラム実行できずじまいです。 cygwinのを(\cygwin\usr\include\mingw\stdio.h)調べてみましたら #ifndef _FILE_DEFINED #define _FILE_DEFINED typedef struct _iobuf { char* _ptr; int _cnt; char* _base; int _flag; int _file; int _charbuf; int _bufsiz; char* _tmpfname; } FILE; となってました。 うーん、どうしてコンパイルエラーになってしまうんでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[326] Re:端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:774RR
2007/02/20 02:13:25

その mingw\stdio.h は使われていないからです。 cygwin の gcc のデフォルトは -mcygwin であり mingw ではありません。 とりあえず gcc -mno-cygwin test5.c とすればコンパイル通るような気もします。 ちょっと調べれば判る程度の問題だと思うのですが、聞く前に調べましたか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[327] Re:端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:(ぱ)
2007/02/20 02:13:25

時間がないのでちょっとだけ。 >ちょっと調べれば判る程度の問題だと思うのですが、聞く前に調べましたか? MinGWとcygwinの関係とかに関する知識がないと、そっち方向を調べることを 思いつかなくても不思議はないかもしれません。 ただ、\cygwin\usr\include\mingw\stdio.hを見つけることができたなら、 \cygwin\usr\include\stdio.hを先に見つけてそうですし、ふたつあるなら どっちか片方が使われているはずで、デフォルトで使われるのは、 パスの短い方(\cygwin\usr\include\stdio.h)と推論するのが普通じゃないかなあ、 とは思います。 \cygwin\usr\include\stdio.hそのものにFILEの定義はないかもしれないですが、 そこから#includeしているファイルの中にあるはずです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[328] Re:端末ドライバのバッファやstdinバッファの中身を覗くには?
投稿者:chikato
2007/02/20 02:13:25

ご回答有難うございます。 遅くなりまして申し訳有りません。 > その mingw\stdio.h は使われていないからです。 > cygwin の gcc のデフォルトは -mcygwin であり mingw ではありません。 > とりあえず gcc -mno-cygwin test5.c とすればコンパイル通るような気もします。 これで出来ました。 実行結果も同じになりました。 「-mno-cygwin」オプションはMinGWランタイムライブラリを使用せよリンクの為のオプションなのですね。 ランタイム…関連するヘッダファイルと対応するライブラリの総称 > ちょっと調べれば判る程度の問題だと思うのですが、聞く前に調べましたか? 文法エラーとばかり思い込んでいました。 > ただ、\cygwin\usr\include\mingw\stdio.hを見つけることができたなら、 > \cygwin\usr\include\stdio.hを先に見つけてそうですし、ふたつあるなら > どっちか片方が使われているはずで、デフォルトで使われるのは、 > パスの短い方(\cygwin\usr\include\stdio.h)と推論するのが普通じゃないかなあ、 > とは思います。 そういわれてみればそうですよね。 スイマセン。二つあるのもそんなものなのかなと思って疑問視してませんでした。 > \cygwin\usr\include\stdio.hそのものにFILEの定義はないかもしれないですが、 > そこから#includeしているファイルの中にあるはずです。 \cygwin\usr\include\stdio.h内に typedef __FILE FILE; を見つけ ↓ \cygwin\usr\include\sys\reent.h内に typedef struct __sFILE __FILE; を見つけ ↓ \cygwin\usr\include\sys\reent.h内に struct __sFILE { unsigned char *_p; /* current position in (some) buffer */ int _r; /* read space left for getc() */ int _w; /* write space left for putc() */ short _flags; /* flags, below; this FILE is free if 0 */ short _file; /* fileno, if Unix descriptor, else -1 */ struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ int _lbfsize; /* 0 or -_bf._size, for inline putc */ #ifdef _REENT_SMALL struct _reent *_data; #endif /* operations */ _PTR _cookie; /* cookie passed to io functions */ _READ_WRITE_RETURN_TYPE _EXFUN((*_read),(_PTR _cookie, char *_buf, int _n)); _READ_WRITE_RETURN_TYPE _EXFUN((*_write),(_PTR _cookie, const char *_buf, int _n)); _fpos_t _EXFUN((*_seek),(_PTR _cookie, _fpos_t _offset, int _whence)); int _EXFUN((*_close),(_PTR _cookie)); /* separate buffer for long sequences of ungetc() */ struct __sbuf _ub; /* ungetc buffer */ unsigned char *_up; /* saved _p when _p is doing ungetc data */ int _ur; /* saved _r when _r is counting ungetc data */ /* tricks to meet minimum requirements even when malloc() fails */ unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ unsigned char _nbuf[1]; /* guarantee a getc() buffer */ /* separate buffer for fgetline() when line crosses buffer boundary */ struct __sbuf _lb; /* buffer for fgetline() */ /* Unix stdio files get aligned to block boundaries on fseek() */ int _blksize; /* stat.st_blksize (may be != _bf._size) */ int _offset; /* current lseek offset */ #ifndef _REENT_SMALL struct _reent *_data; /* Here for binary compatibility? Remove? */ #endif #ifndef __SINGLE_THREAD__ _flock_t _lock; /* for thread-safety locking */ #endif }; を見つけました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[960] 管理者により削除されました
2007/03/10 22:19:56

投稿者の記載も新しい追記もなく、単に古い投稿に返信しただけの記事だったので削除しました。 テスト投稿はテスト用掲示板 http://kmaebashi.com/bbs/list.php?boardid=testbbs にお願いします。
[この投稿を含むスレッドを表示]
[996] 管理者により削除されました
2007/07/14 07:55:43

広告なので削除しました
[この投稿を含むスレッドを表示]
[1014] 管理者により削除されました
2007/08/11 13:56:30

広告なので削除しました。
[この投稿を含むスレッドを表示]