Thursday, May 21, 2009

linux large file support

LFS support

在老的文件操作接口以及实现中,使用整形数来保存偏移或字节数,故在32bit机器上存在最大只能表示2G的问题.
像ftell,feek:
 int fseek(FILE *stream, long offset, int whence);
 long ftell(FILE *stream);

要支持2G以上大文件,有几个点要注意:物理文件系统,文件系统接口(包括kernel,libc),以及文件操作接口选择和编译.

==文件系统对大文件的支持情况==
FAT最大单个文件2G,FAT32最大4G,NTFS最大128G

nfs: version 2只能支持2G的文件,version 3支持LFS.如使用 nfs v2,则在fseeo超过2G的文件位置时会报错,非法参数.
一般nfs server支持version 2,version3, version 4版本的nfs传输.如要强制使用nfs version 3,可以在mount时加上参数, nfsvers=3.否则默认一般都是version2传输.内核mount nfs根文件系统时的参数同样可以加上这个参数:nfsroot=server-ip:root-dir,nfsvers=3.

ext2/3:支持大文件.

==kernel==
文件系统驱动是按照文件系统标准在实现,在系统调用这一层,也都默认能支持大文件.

==c库==
为此glibc/uclibc加入了LFS(large file support)的特性.一般的版本这个特性都是打开了的. 故要支持LFS,一般不用重新编译.

==c接口的使用和编译==
像ftell, fseek这两个接口,在标准c中的原型定义为:
       int fseek(FILE *stream, long offset, int whence);
       long ftell(FILE *stream);
故在32bit操作系统下,这两个接口是无法支持大文件的.必須使用其它接口.

其它文件接口,不存在上面的情况,要么是没有使用到跟offset,size相关的参数,像fopen等,要么其涉及到offset和size的参数用的是非标准数据类型(如off_t等),标准里对这种非标准数据类型没有定义.

故在实际glibc/uclibc中, 在实现涉及到offset和size等的非标准数据类型时,提供了两套.一套为32位的.一套为64位的. 使用宏来控制_LARGEFILE_SOURCE _LARGEFILE64_SOURCE _FILE_OFFSET_BITS 来控制.

故要在程序中支持大文件,只需要加上 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 的编译选项即可.

在有些文档中,会介绍64位的文件系统接口,如:
 fopen->fopen64
 stat->stat64
 fstat->fstat64
 lstat->lstat64
 fseeko->fseeko64
 ftello->ftello64

但不推荐直接这些函数,因为这属于glibc/uclibc内部函数, 不是标准函数.代码移植性比较差. 并且使用-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64宏达到的是类似效果.由编译器用宏展开或符号重名的方式来调用相应的64位的文件接口.

==其它==
1.如不打开上述编译控制宏, fopen默认情况下打开大文件会失败,报错: Value too large for defined data type

2. busybox有CONFIG_LFS选项来决定是否使用上述三个宏.


[[Category:文件系统]][[Category:linux]]