zoukankan      html  css  js  c++  java
  • linux环境下操作特大文件

    linux环境下操作特大文件 -D_FILE_OFFSET_BITS=64
    2010年06月04日 星期五 下午 1:57

    gcc -D_FILE_OFFSET_BITS=64

    In a nutshell for using LFS you can choose either of the following: Compile your programs with "gcc -D_FILE_OFFSET_BITS=64". This forces all file access calls to use the 64 bit variants. Several types change also, e.g. off_t becomes off64_t. It's therefore important to always use the correct types and to not use e.g. int instead of off_t. For portability with other platforms you should use getconf LFS_CFLAGS which will return -D_FILE_OFFSET_BITS=64 on Linux platforms but might return something else on e.g. Solaris. For linking, you should use the link flags that are reported via getconf LFS_LDFLAGS. On Linux systems, you do not need special link flags. Define _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE. With these defines you can use the LFS functions like open64 directly. Use the O_LARGEFILE flag with open to operate on large files. A complete documentation of the feature test macros like _FILE_OFFSET_BITS and _LARGEFILE_SOURCE is in the glibc manual (run e.g. "info libc 'Feature Test Macros'").

    linux环境下操作特大文件 -D_FILE_OFFSET_BITS=64

    今天特地仔细研究了一下linux环境下文件操作的一些细节,得到以下几个结论,如有不当之处,欢迎批评指正:)

    1:创建单个文件的的最大大小由底层文件系统决定。当然,这里的单个文件指的是不含空洞的文件。什么是空洞文件呢?
    简单地说,在对文件进行写操作时,如果设置的文件偏移量大于文件的长度,那么对该文件的写将加长该文件,并在文件中构成一个空洞,而没有被写过的字节都被 读为0。由于文件的空洞不需要占用存储区(其中具体的处理方式和文件系统的实现有关),因此利用这样的文件空洞特性,我们可以创建(2^63-1)B大小 的文件,远远超过硬盘的容量(可以用ls -lh filename以及od -c filename查看)。当然,这样的文件实际占用的存储区远远小于这个大小。关于为什么是(2^63-1)B的大小,后面讨论off_t类型时会谈到~

    2:可操作(读、写、修改)文件的最大大小为(2^63-1)B。那天xchen师兄的疑惑就在这里,因为像C标准库中的ftell函数的返回值为 long类型,在主流的GCC等编译器中对long类型变量分配的大小为4个字节,即32位。也就是说可操作的文件大小至多是(2^31-1)B。嗯,其 实我认为很多情况下单纯依赖C标准库是有限制的。像Windows和基于UNIX的系统其实都有相关的实现来以64位形式对文件进行操作。在linux 下,我们可以使用lseek系统调用(不要用C标准库中的fseek(),因为fseek也只支持32位)。lseek函数的原型可在 /usr/include/unistd.h 中查看(unistd.h只是使用extern对lseek函数进行声明,真正定义的位置在内核源码中):

    extern __off_t lseek (int __fd, __off_t __offset, int __whence) __THROW


    用户态使用的lseek接口是:

    off_t lseek(int fd, off_t offset, int whence);


    然,对于大多数系统,off_t类型默认也是32位(可用sizeof(off_t)查看)。那天在实验室机器上(ubuntu9.10)测试的时候 off_t是64位,然而今天在自己机器上一测,却发现是32位。。于是我继续在/usr/include中查找off_t类型的定义,找到了这个:

    #  ifndef __USE_FILE_OFFSET64
    typedef __off_t off_t;
    #  else
    typedef __off64_t off_t;


    从这段代码中可以看出,off_t其实拥有两种类型:__off_t和__off64_t,__off64_t恐怕就是我们所想要的吧:)而要使 off_t为__off64_t类型,必须#define __USE_FILE_OFFSET64.
    __USE_FILE_OFFSET64这个宏字面上看有点意思,于是继续搜索,在shell中:grep __USE_FILE_OFFSET64 /usr/include/* -r。 于是在<sys/types.h>找到了这个:

    #if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
    # define __USE_FILE_OFFSET64    1
    #endif



    哈,眼前一亮。我想这就是我所需要的:_FILE_OFFSET_BITS
    于是,做法很简单。编译时加上宏定义即可:gcc -o program program.c -D_FILE_OFFSET_BITS=64 。-D为宏定义,当然也可在应用程序中加入宏定义
    #define _FILE_OFFSET_BITS 64    (要注意的是,#define必须放在#include <unistd.h>之前。原因很简单,无需赘述。)
    可以自己动手验证一下:先生成一个4G(2^32)大小的文件,我在linux下可创建的最大文件为2G,因此不得不在Windows下生成一个,呵。命 名为large,用以下代码进行简单测试:

    //#define _FILE_OFFSET_BITS 64 
     #include <unistd.h>
     #include <sys/types.h>
     #include <sys/stat.h>
     #include <stdio.h>
     #include <stdlib.h>
    
     int main()
     {
      int fd = open("large", O_RDONLY);
      if (fd == -1)
      {
              fprintf(stderr, "Failed to open..");
              exit(EXIT_FAILURE);
      }
      printf("%d \n", sizeof(off_t));// 8
      off_t offset = lseek(fd, (off_t)3*1024*1024*1024, SEEK_SET);//访问位于3G位置处的字符
      if (offset == -1)
      {
              fprintf(stderr, "Failed to seek..");
              exit(EXIT_FAILURE);
      }
      char ch; 
      read(fd, &ch, 1); 
      printf("the character = %c\n", ch);
      close(fd);
      
      exit(EXIT_SUCCESS);
     }



    编译命令:gcc -o test test.c -D_FILE_OFFSET_BITS=64 -std=c99

  • 相关阅读:
    随题而学(二)多维数组转一维数组
    随题而学(一)
    谁能破解“无法定位程序输入点ucrtbase.abort与动态链接库api-ms-win-crt-runtime-l1-1-0.dll上”
    虚拟机8—tools安装失败
    win7介绍
    win xp安装
    Linux正则表达式,grep总结,sed用法
    Linux将用户添加到组的指令
    xxx is not in the sudoers file.This incident will be reported.的解决方法
    69-70连接查询
  • 原文地址:https://www.cnblogs.com/xiayong123/p/3717095.html
Copyright © 2011-2022 走看看