• ベストアンサー

構造体をディスクからロードして複数バッファリングさせる

構造体をディスクからロードして複数バッファリングさせておくようなプログラムを組みたいと思い、 C言語で下のようなコードを記述しました。 ※質問にあたり最小限の記述にしています。 #define SIZE (sizeof(struct hoge)) #define NUM 16 char buf[SIZE*NUM]; fd=open(file_name,O_RDONLY); read(fd,buf,SIZE*NUM); 上のような記述(read)をして構造体(hoge)を16個分確保できてしまいました。 ここで疑問に当たりました。 (1) read(fd,buf,SIZE); (2) read(fd,buf,SIZE*NUM); 個人的には(1)と書いても(2)のように書いて、fdが指すポインタから、SIZE分読み込んだ時点で、ファイルの末尾に達するので読み込みが終わると思っていました。 SIZE*NUM分読めたことに納得がいきません。 末尾にきたらファイルの先頭に戻っているのでしょうか? readのmanを読んでも間違いないと思えるのですが。。 お分かりの方いらっしゃいましたらぜひぜひ教えてくださいませ。

質問者が選んだベストアンサー

  • ベストアンサー
  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.8

>今回/var/run/utmpから構造体を読み出したわけですが >(エントリといういのでしょうか?)なぜ複数あるのでしょうか?? man utmp を読む限りでは、ユーザが新たにログインすると utmp ファイルにユーザ情報が追記されていくようですね。 しかし、私の使っているシステムで /var/run/utmp を読むと、最初の 17個分は空になっています。 utmp の追加の仕方までは追っていないのでこれ以上はわかりません。 ちなみにウチは FreeBSD 6.3 で、sizeof(struct utmp) は 44バイトですね。

その他の回答 (7)

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.7

UTMP_FILEの実体は/var/run/utmpですね。 で、そのサイズはこちらの環境だと、51072バイトあります。 以下ソースと実行結果 ------------------------------------------ #include <stdio.h> #include <utmp.h> #include <fcntl.h> #define SIZE (sizeof(struct utmp )) #define NUM 16 char buf[SIZE*NUM]; int main(){ int fd=open(UTMP_FILE,O_RDONLY); printf("UTMP_FILE=<%s> fd=%d\n",UTMP_FILE,fd); int read_size=read(fd,buf,SIZE*NUM); printf("SIZE : %d\n",SIZE); printf("NUM : %d\n",NUM); printf("SIZE*NUM : %d\n",SIZE*NUM); printf("read_size : %d\n",read_size); } ----------------------------------------- UTMP_FILE=</var/run/utmp> fd=3 SIZE : 384 NUM : 16 SIZE*NUM : 6144 read_size : 6144 ll /var/run/utmp -rw-rw-r-- 1 root utmp 51072 8月 6 14:44 /var/run/utmp ---------------------------------------- cent-os 4.4で確認しました。 /var/run/utmpのサイズを確認してみて下さい。

skip_jack
質問者

補足

おっしゃるとおりでした。 /var/run/utmpファイルサイズまでreadしていなかったためでした。 そのファイルを超えた分はreadできませんでした。 ここで新しく疑問が生まれました。 今回/var/run/utmpから構造体を読み出したわけですが(エントリといういのでしょうか?)なぜ複数あるのでしょうか?? 基本的なことかもしれませんが、混乱してきました。。 ファイル(ここでは/var/run/utmp)から構造体を読み込むという動作がイメージつきません自分でやろうとしておいてなんですが)。。 単純に一ファイル一構造体のように思っていたのですが。 もしご解答いただけるようでしたらよろしくお願いいたします。

  • kent85
  • ベストアンサー率52% (38/73)
回答No.6

せっかくlseek()を使ったので、ファイルの末尾までシークさせるか filelength()でファイルサイズはわかると思いますよ。

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.5

>readの戻り値は6144です。 >size×個数分readしているようです?? どう考えても UTMP_FILE が 6144 バイト以上あるとしか思えない。 その実体は /var/run/utmp あたりだと思いますが、サイズはいくつになっていますか? まあ 16個くらいエントリーがあっても何ら不思議ではないと思いますけど。

skip_jack
質問者

補足

おっしゃるとおりでした。 /var/run/utmpファイルサイズまでreadしていなかったためでした。 そのファイルを超えた分はreadできませんでした。 ここで新しく疑問が生まれました。 今回/var/run/utmpから構造体を読み出したわけですが(エントリといういのでしょうか?)なぜ複数あるのでしょうか?? 基本的なことかもしれませんが、混乱してきました。。 ファイル(ここでは/var/run/utmp)から構造体を読み込むという動作がイメージつきません自分でやろうとしておいてなんですが)。。 単純に一ファイル一構造体のように思っていたのですが。 もしご解答いただけるようでしたらよろしくお願いいたします。

  • kent85
  • ベストアンサー率52% (38/73)
回答No.4

> 末尾にきたらファイルの先頭に戻っているのでしょうか? いいえ ディスクファイルならばlseek()を使うと現在の位置が確かめられます。 ※シークが出来ないデバイスもあります。 lseek() printf(現在位置) (1) read(fd,buf,SIZE); lseek() printf(現在位置) /********************/ (2) read(fd,buf,SIZE*NUM); lseek() printf(現在位置) open / read / write は低水準ですので基本的にべたべたとアクセスしますが fopen / fread / fwrite にすると一応はバッファリングはされます。

skip_jack
質問者

補足

lseekしたところ、やはり戻っているなんてことはなかったです。 となると、やはりサイズ分readした時点で終わらないことが腑に落ちないです。。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.3

構造体の確保は宣言時にされている 初期化もグローバル変数だったら宣言時に0で初期化される 任意の値の読み込みならファイルの最後で読み込みは終わるはずです

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.2

No.1氏要求に加えて、read()の戻り値がどうなっているかの提示をお願いします。

skip_jack
質問者

補足

No.1さんの回答に私が実行したコードをそのまま載せています。 readの戻り値は6144です。 size×個数分readしているようです??

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

>上のような記述(read)をして構造体(hoge)を16個分確保できてしまいました。 構造体が「確保できた」とは具体的にはどういう状態なのか ほんとうに fd の指すファイルはピッタリ SIZE バイトであるか を補足にどうぞ。

skip_jack
質問者

補足

#include <stdio.h> #include <utmp.h> #include <fcntl.h> #define SIZE (sizeof(struct utmp )) #define NUM 16 char buf[SIZE*NUM]; int main(){ int fd=open(UTMP_FILE,O_RDONLY); int read_size=read(fd,buf,SIZE*NUM); printf("SIZE : %d\n",SIZE); printf("NUM : %d\n",NUM); printf("SIZE*NUM : %d\n",SIZE*NUM); printf("read_size : %d\n",read_size); } ====結果==== SIZE : 384 NUM : 16 SIZE*NUM : 6144 read_size : 6144