您的位置:首页 > 运维架构 > Linux

linux中创建超过4g文件的方法-o_largefile

2015-08-18 15:50 344 查看
linux c 大文件使用 - O_LARGEFILE

2010-07-20 10:09

支持大文件的两种方式:

1、gcc 加 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE

2、注意一定要定义在include之前

#define _LARGEFILE_SOURCE

#define _LARGEFILE64_SOURCE

#define _FILE_OFFSET_BITS 64

建议两种方式都加上。

如何create大文件
要大就非常大,1T吧。
有两种方法:

一.dd
dd if=/dev/zero of=1T.img bs=1G seek=1024 count=0

bs=1G表示每一次读写1G数据,count=0表示读写0次,seek=1024表示略过1024个Block不写,前面block size是1G,所以共略过1T!

这是创建大型sparse文件最简单的方法。

二.ftruncate64/ftruncate

如果用系统函数就稍微有些麻烦,因为涉及到宏的问题。我会结合一个实际例子详细说明,其中OPTION标志的就是测试项。
文件sparse.c:

//OPTION 1:是否定义与大文件相关的宏

#define _LARGEFILE_SOURCE

#define _LARGEFILE64_SOURCE

#define _FILE_OFFSET_BITS 64

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <errno.h>

#include <string.h>
#define FILENAME "bigfile"

#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int main(int argc, char **argv)

{
int fd, ret;
off_t offset;
int total = 0;
if ( argc >= 2 )
{
total = atol(argv[1]);
printf("total=%d\n", total);
}

//OPTION 2:是否有O_LARGEFILE选项
//fd = open(FILENAME, O_RDWR|O_CREAT|O_LARGEFILE, 0644);
fd = open(FILENAME, O_RDWR|O_CREAT, 0644);
if (fd < 0) {
perror(FILENAME);
return -1;
}
offset = (off_t)total *1024ll*1024ll*1024ll;
printf("offset=%ld\n", offset);

//OPTION 3:是否调用64位系统函数
//if (ftruncate64(fd, offset) < 0)
if (ftruncate(fd, offset) < 0)
{
printf("[%d]-ftruncate64 error: %s\n", errno, strerror(errno));
close(fd);
return 0;
}
close(fd);
printf("OK\n");
return 0;

}

测试环境:

linux:/disk/test/big # gcc --version

gcc (GCC) 3.3.5 20050117 (prerelease) (SUSE Linux)

linux:/disk/test/big # uname -a

Linux linux 2.6.11.4-20a-default #1 Wed Mar 23 21:52:37 UTC 2005 i686 i686 i386 GNU/Linux

测试结果(伪码表示):

1.宏定义完全的情况下:


IF {O_LARGEFILE=TRUE && ftruncate64=TRUE}
OK;

ELSEIF {O_LARGEFILE=FALSE && ftruncate64=TRUE}
OK;

ELSEIF {O_LARGEFILE=FALSE && ftruncate64=FALSE}
运行不报错,但是不支持>4G;

ELSEIF {O_LARGEFILE=TRUE && ftruncate64=FALSE}
运行不报错,但是不支持>4G;

结论】:在宏定义完全的情况下,是否调用ftruncate64,是决定支持4G以上文件的关键,O_LARGEFILE无作用。

2.宏定义不完全:缺少_FILE_OFFSET_BITS

首先声明一点,O_LARGEFILE需要定义_LARGEFILE64_SOURCE。

IF {O_LARGEFILE=TRUE && ftruncate64=TRUE}
产生不正常超大文件;

ELSEIF {O_LARGEFILE=FALSE && ftruncate64=TRUE}
产生不正常超大文件;

ELSEIF {O_LARGEFILE=FALSE && ftruncate64=FALSE}
运行不报错,但是不支持>2G;

ELSEIF {O_LARGEFILE=TRUE && ftruncate64=FALSE}
运行不报错,但是不支持>4G;

结论】:未定义_FILE_OFFSET_BITS的情况下,ftruncate64调用是非法的,会产生无法预料的后果,这里的测试就是产生一个超大文件(>1T),我也无法解释其原因;O_LARGEFILE的作用就是在32位系统中支持大文件系统,允许打开那些用31位(2G)都不能表示其长度的大文件;此外,off_t为 unsigned int类型,也就是说最多只能达到4G,所以ftruncate最大支持4G文件。

总结一下:如果要支持超过2G的文件,至少需要定义 _LARGEFILE64_SOURCE宏,并且设置O_LARGEFILE选项;如果要支持超过4G,需要定义所有上述的宏,并且调用 ftruncate64;其余的搭配都是错误的!

】:

dd 的主要选项:

指定数字的地方若以下列字符结尾乘以相应的数字:

b=512, c=1, k=1024, w=2, m=1024k, g=1024m

大小写不限。
if=file

输入文件名,缺省为标准输入。
of=file

输出文件名,缺省为标准输出。
ibs=bytes

一次读入 bytes 个字节(即一个块大小为 bytes 个字节)。
obs=bytes

一次写 bytes 个字节(即一个块大小为 bytes 个字节)。
bs=bytes

同时设置读写块的大小为 bytes ,可代替 ibs 和 obs 。
cbs=bytes

一次转换 bytes 个字节,即转换缓冲区大小。
skip=blocks

从输入文件开头跳过 blocks 个块后再开始复制。
seek=blocks

从输出文件开头跳过 blocks 个
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: