#undef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <dirent.h>
---------------------------------------
支持大文件的两种方式:
1、gcc 加 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE
2、注意一定要定义在include之前
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
建议两种方式都加上。
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文件最简单的方法。
如果用系统函数就稍微有些麻烦,因为涉及到宏的问题。我会结合一个实际例子详细说明,其中OPTION标志的就是测试项。
文件sparse.c:
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
int main(int argc, char **argv)
{
int fd, ret;
off_t offset;
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);
//if (ftruncate64(fd, offset) < 0)
if (ftruncate(fd, offset) < 0)
{
printf("[%d]-ftruncate64 error: %s/n", errno, strerror(errno));
close(fd);
return 0;
}
printf("OK/n");
}
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无作用。
首先声明一点, 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文件。
dd 的主要选项:
指定数字的地方若以下列字符结尾乘以相应的数字:
b=512, c=1, k=1024, w=2, m=1024k, g=1024m
大小写不限。
输入文件名,缺省为标准输入。
输出文件名,缺省为标准输出。
一次读入 bytes 个字节(即一个块大小为 bytes 个字节)。
一次写 bytes 个字节(即一个块大小为 bytes 个字节)。
同时设置读写块的大小为 bytes ,可代替 ibs 和 obs 。
一次转换 bytes 个字节,即转换缓冲区大小。
从输入文件开头跳过 blocks 个块后再开始复制。
从输出文件开头跳过 blocks 个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)
仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数。
用指定的参数转换文件。
使每一行的长度都为 cbs ,不足部分用空格填充。
不显示错误
不截短输出文件。
/proc/sys/kernel/file-max,要永久生效需修改/etc/sysctl.conf
随便baidu了一下
使用/proc文件系统来控制系统
/proc/sys/fs
/proc/sys/fs/file-max
该文件指定了可以分配的文件句柄的最大数目。如果用户得到的错误消息声明由于打开文件数已经达到了最大值,从而他们不能打开更多文件,则可能需要增加该值。可将这个值设置成有任意多个文件,并且能通过将一个新数字值写入该文件来更改该值。
缺省设置:4096
/proc/sys/fs/file-nr
该文件与 file-max 相关,它有三个值:
已分配文件句柄的数目
已使用文件句柄的数目
文件句柄的最大数目
该文件是只读的,仅用于显示信息。
所以不存在两个文件的配合修改问题,主要修改file-max就行了
3. ulimit -a中
open files (-n) 1024
也即是ulimit -n
-n The maximum number of open file descriptors (most systems
do not allow this value to be set)
ulimit -n 设置用户可以同时打开的最大文件数(max open files)
例如:ulimit -n 8192
如果本参数设置过小,对于并发访问量大的网站,可能会出现too many open files的错误
我看一些文章,建议在/etc/rc.d/rc.local中修改/proc/sys/fs/file-max、/proc/sys/fs/file-nr的内容
cat /proc/sys/fs/file-max
209695
cat /proc/sys/fs/file-nr
4483 3550 209695
请问这2个文件要如何配合修改?
3。采用ulimit -a出现如下描述
$ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) 4
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 7168
virtual memory (kbytes, -v) unlimited
其中的open files与上面现象有关系呢?
Too many open files 问题出现有两种情况:
一种是在搜索的时候出现,多半是由于索引创建完毕之后被移动过,如果创建索引的时候不出现该错误,搜索的时候也一般是不会出现的。如果出现了,有两种处理办法,一种是修改合并因子和最小合并因子,并且使用
IndexWriter.Optimize() 优化索引,这样会将索引文件数量减少到文件系统限制之内;另外一种办法是修改操作系统的打开文件数量限制。方法如下:
1. 按照最大打开文件数量的需求设置系统, 并且通过检查/proc/sys/fs/file-max文件来确认最大打开文件数已经被正确设置。
# cat /proc/sys/fs/file-max
如果设置值太小, 修改文件/etc/sysctl.conf的变量到合适的值。 这样会在每次重启之后生效。 如果设置值够大,跳过下步。
# echo 2048 > /proc/sys/fs/file-max
编辑文件/etc/sysctl.conf,插入下行。
fs.file-max = 8192
2. 在/etc/security/limits.conf文件中设置最大打开文件数, 下面是一行提示:
#
添加如下这行。
* - nofile 8192
这行设置了每个用户的默认打开文件数为2048。 注意"nofile"项有两个可能的限制措施。就是项下的hard和soft。 要使修改过得最大打开文件数生效,必须对这两种限制进行设定。 如果使用"-"字符设定, 则hard和soft设定会同时被设定。
硬限制表明soft限制中所能设定的最大值。 soft限制指的是当前系统生效的设置值。 hard限制值可以被普通用户降低。但是不能增加。 soft限制不能设置的比hard限制更高。 只有root用户才能够增加hard限制值。
当增加文件限制描述,可以简单的把当前值双倍。 例子如下, 如果你要提高默认值1024, 最好提高到2048, 如果还要继续增加, 就需要设置成4096。
另外一种情况是在创建索引的时候,也有两种可能,一种是 合并因子太小,导致创建文件数量超过操作系统限制,这时可以修改合并因子,也可以修改操作系统的打开文件数限制;另外一种是合并因子受虚拟机内存的限制,无法调整到更大,而 需要索引的doc 数量又非常的大,这个时候就只能通过修改操作系统的打开文件数限制来解决了。
在此基础上,我还修改了以下一个配置文件
vi /etc/sysctl.conf
添加:
# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 30
# Decrease the time default value for tcp_keepalive_time connection
net.ipv4.tcp_keepalive_time = 1800
# Turn off tcp_window_scaling
net.ipv4.tcp_window_scaling = 0
# Turn off the tcp_sack
net.ipv4.tcp_sack = 0
#Turn off tcp_timestamps
net.ipv4.tcp_timestamps = 0
然后 service network restart,这些都和TCP sockets有关的优化。
另外需要在 /etc/rc.d/rc.local里添加已使得重启的时候生效。
echo "30">/proc/sys/net/ipv4/tcp_fin_timeout
echo "1800">/proc/sys/net/ipv4/tcp_keepalive_time
echo "0">/proc/sys/net/ipv4/tcp_window_scaling
echo "0">/proc/sys/net/ipv4/tcp_sack
echo "0">/proc/sys/net/ipv4/tcp_timestamps
因为不是所有的程序都在root下跑的,所有linux有对hard 与soft open files 的区分,普通用户受hard的限制,无论ulimit -n $数值调到多高,都跑不到 /etc/security/limits.conf里nofile的值.
这样的优化后 lsof -p $java_pid|wc -l可以跑到4千以上都不会抛出too many open files。
但是我们通过以上的文章详细介绍知道,这样也是治标不治本,找到java哪个文件不关闭文件描述符或者被请求过多的原因才是最重要的!
1. 如何查看linux系统的位数(32/64):
* 直接看看有没有/lib64目目录的方法:
64位的系统会有/lib64和/lib两个目录,32位只有/lib一个
* getconf LONG_BIT:
32位的系统中int类型和long类型一般都是4字节,64位的系统中int类型还是4字节的,但是long已变成了8字节
* uname -a:
如果是64位,会有x86_64的字样
* 用编程的方法,sizeof( long 或 size_t )就是系统的位数
这个与编译器版本有关,有时会不相符。不建议使用。所以在编程中,用可以指定int的长度int32_t,int64_t,uint32_t和uint64_t等可以避免位数问题和增强可读性
2. linux下C语言操作大文件(4G以上)
一般情况下,64位操作系统可以操作任何大文件(2^64)。
以下讨论的是32位机器的情况。
首先32位机器用fopen/fclose打开大文件没有问题,顺序读写操作while(!feof(fp)){ fread / fgets / fscanf }或while(1){ fwrite / fputs / fprintf} 也没有问题。
由于32位机器下long是32位,故
fseek(FILE *stream,longoffset, intwhence)
long ftell(FILE *stream)不能访问4G以上文件
此时要用fseeko(FILE *stream,off_toffset, intwhence)
off_t ftello(FILE *stream);代替
类型off_t 的定义在 <sys/types.h>里面:
# ifndef __USE_FILE_OFFSET64
typedef __off_t off_t;
# else
typedef __off64_t off_t;
# endif
off_t在32位机器中是32bit,64位机器中是64bit。那么,在32位机器中,在include之前加入宏定义:#define _FILE_OFFSET_BITS 64,或者编译是加入-D_FILE_OFFSET_BITS 64告诉系统在文件内部使用64位的偏移地址,使off_t变成__off64_t类型。
这样,只要你用64bit的类型(off_t,long(64位机器),和long long(32位机器) 或int64_t/uint64_t)声明offset作为fseeko的参数输入,就可以操作4G以上的文件了。
许多人还提到在宏定义中多写上一些:
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
但另外两个的具体功能我现在尚未搞得很清楚,等以后了解完全再补上。
* 使用LINUX自己的库函数进行文件操作(*nix I/O操作),加入O_LARGEFILE选项:
#define __USE_LARGEFILE64
#include <fcnl.h>
int fp = open("myfile", O_WRONLY | O_TRUNC | O_CREAT |O_LARGEFILE, 644);
以下代码只作为参考!
file.cpp
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE
#define _LARGE_FILES
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#define SIZE 1024
static off64_t file_length(FILE *f);
int main(int argc, char *argv[])
{
char buf[SIZE ]={0};
FILE *fileA, *fileB;
if ((fileA = fopen64("1.dat", "rb")) == NULL)
{
printf(" The file can not be opened.\n");
return 1;
}
if ((fileB = fopen64("2.dat", "wb")) == NULL)
{
printf(" The desfile not be opened.\n");
return 1;
}
fread(buf, (off64_t)SIZE, (off64_t)1LL, fileA);
fwrite(buf, (off64_t)SIZE, (off64_t)1LL, fileB);
fseeko64(fileA, (off64_t)0LL, SEEK_SET);
fseeko64(fileB, (off64_t)0LL, SEEK_SET);
fclose(fileA);
fclose(fileB);
return 0;
}
static off64_t file_length(FILE *f)
{
off64_t pos;
off64_t end;
pos = ftello64(f);
fseeko64(f, (off64_t)0LL, SEEK_END);
end = ftello64(f);
fseeko64(f, (off64_t)pos, SEEK_SET);
return end;
}
makefile
# C++ = mipsel-linux-g++
# CC = mipsel-linux-gcc
# AR = mipsel-linux-ar
# RANLIB = mipsel-linux-ranlib
C++ = g++
CC = gcc
AR = ar
RANLIB = ranlib
CCFLAGS += -I.
CCFLAGS +=
# LDFLAGS += -Wl,-elf2flt="-s32768"
LDFLAGS := -lpthread -lm -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE
CCFLAGS += -I./include -w -Os
# CCFLAGS += -lstdc++
#LINKOPTS = -Lmipsel_lib
LINKOPTS =
LIBFILES =
#LIBFILES = mipsel_lib/libtelechipStreaming.a
CFILES := \
CPPFILES := \
file.cpp \
\
LOCAL_INCLUDES := \
-I./include \
OBJ += $(CFILES:.c=.o) $(CPPFILES:.cpp=.o)
EXE = test
all: $(EXE)
$(EXE) : $(OBJ)
$(C++) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(CCFLAGS) $(LDFLAGS) $(LINKOPTS) $(LIBFILES) -o $@
clean:
rm -f *.bak *.o *.gdb $(EXE)
.SUFFIXES: .cpp .o .c .o
.cpp.o:
$(C++) -c -o $*.o $(LOCAL_INCLUDES) $(CCFLAGS) $*.cpp
.c.o:
$(CC) -c -o $*.o $(LOCAL_INCLUDES) $(CCFLAGS) $*.c