今天,刘斌师兄找我问了几个问题,是关于他毕设遇到的一个问题,处理大文件。
刚开始,刘斌问了一个大文件如何处理的问题,我说GCC有一个处理大文件的选项。后来,他又跟我说了一下他毕设的一些详细的资料。原来,他是要索引一个大文件,苦于文件比较大。
索引大文件,会遇到一些问题。首先就是内存的问题,当然不能够完全使用物理内存,需要使用交换分区。我们做了几个实验,来验证一下,程序分配大空间跟交换分区的关系。
1、在一个没有交换分区的机器上实验。
char *p = NULL;
for(int i = 0 ; i < 10; i ++){
p = malloc(100000000);
bzero(p, 100000000);
printf("###%#0x\n",p);
}
程序是分配10*100M的空间,远远大于系统的内存,结果程序出现段错误。如果是还一个小一点的数的话,就没有问题了(废话,就不就是要处理大文件吗)。
如果注释掉bzero一行的话,运行的时候,就会发现内存并没有占用多少。可以判定如果申请内存的时候没有赋值的话,实际上系统并没有分配。
2、在一个有交换分区的机器上实验。
char *p = NULL;
for(int i = 0 ; i < 10; i ++){
p = malloc(100000000);
bzero(p, 100000000);
printf("###%#0x\n",p);
}
物理内存:512M
交换分区:720M
分配没有问题,就是系统有一些慢。用free查看内存占用的话,就会发现,物理内存只剩下6M了,交换分区占用了500M。
ft,再实验,将数再改的大一些!
char *p = NULL;
for(int i = 0 ; i < 10; i ++){
p = malloc(150000000);
bzero(p, 150000000);
printf("###%#0x\n",p);
}
10*150M > 512M + 720M,这下看一下会不会出现段错误。
编译运行,哈哈,出现段错误了,看来预测是对的了。
3、增加交换分区,再实验
接下来就是要增加交换分区,再实验一下,其实结果应该很清楚了,不过还是想看一下。
增加交换分区有两个方法:增加一块硬盘作为交换分区,使用一个文件作为交换分区。
我的硬盘已经没有空的了,只好使用文件作为交换分区了。
dd if=/dev/zero of=./swapfile bs=1M count=500
mkswap ./swapfile
swapon ./swapfile
在运行刚才的程序,分配成功,Yes!
4、大内存访问实验。
虽然解决了大内存分配的问题,但是索引大文件还是需要对大内存进行随机访问,这就是一个问题了.
由于32位的机器实际上只能够访问4G的地址空间,如果文件有5G,那么怎么来访问4G之外的存储器呢?
正如上面,malloc一样,malloc的参数是一个size_t的数,最大才4G。我们只好拆开来分配。
访问也是一样,我们也可以拆开来访问吗?
5G=4G+1G
void *temp = p + 4G;
temp += 5G-4G
就可以访问到5G的区域了。