2013年1月22日火曜日

lseek()と32ビットOS

64ビットOSも十分に普及したような気がする今日この頃ですが、
32ビットだってまだまだ現役です。
というかARMはまだ32ビットしかないので
組み込み系に関しては32ビットが主流どころか他に選択肢がありません。

さて、32ビットというと符号なし整数では0から4294967295まで扱えます。
日常では約43億、コンピュータの世界では4Gということになります。
この数字では日本の国家予算には桁が足りませんし、
最近のPCに積んである大容量メモリへのアクセスにも不自由することになります。
HDDは4Gセクタまでアクセスできることになりますが、
一般的な1セクタが512バイトの構成では2TBが容量上限と言うことになります。

ところで、HDDはセクタ単位でのアクセスなので2TBだとしても、
HDDの中に保存されているファイルはバイト単位でのアクセスとなりますから、
32ビットでは4GBまでしかアクセスできないことになります。
C言語でプログラムを書くとき、
あるファイルのoffsetバイト目を読みたいときなんかに
lseek(f,offset,SEEK_SET);
を実行したりしますが、
これだと4GBより先に届きません。
実際にはlseek()の第2引数off_t型は符号付きになるので2GBが限界となります。
FAT系ファイルシステムだと根本的に2GB以上のファイルが保存できないので
あまり気にする必要もないのですが、その他では十分にありえますし、
UNIX系のデバイスファイルで2TBのHDDを直接触るときなど
一体どうしているか疑問が浮かびます。
32ビットOSにだって4GB以上のファイルが扱えないと困りますし。

で、調べていって分かったのが、lseek()に対して
off64_t lseek64(int fd, off64_t offset, int whence);  
なる関数が用意されていることです。
Linux(32ビット)&C言語の場合ですが、
#include <sys/types.h>
#include <unistd.h>
の前に
#define _LARGEFILE64_SOURCE
を定義しておけば、
off64_t型(64ビット符号付き整数)とlseek64()関数が使えるようになり、
ファイルの2GBを超えた部分にポインタ移動ができるようになります。
いやー、勉強になりました。

0 件のコメント:

コメントを投稿