磁盘预分配

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huabiaochen/article/details/86672480

一、磁盘预分配—ftruncate
1. 使用lseek、ftruncate到一个固定位置生成的“空洞文件”是不会占据真正的磁盘空间的。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdint.h>

uint64_t file_size = 10*1024*1024*1024ULL;

int main()
{
    int fd = -1;

    fd = open("test.data.fruncate.txt", O_RDWR | O_CREAT, 0666);
    if(fd < 0){
      printf("open failed\n");
      return -1;
    }

    if(ftruncate(fd, file_size)){
        printf("ftruncate error\n");
        return -1;
    }

    lseek(fd, file_size - 1,SEEK_CUR);
    write(fd, "1", 1);
    
    close(fd);
    return 0;
}

测试结果

[email protected]:/data/tmp#gcc fruncate.c -o fruncate
[email protected]:/data/tmp#time ./fruncate 

real    0m0.001s
user    0m0.000s
sys    0m0.000s
[email protected]:/data/tmp#ll -h test.data.fruncate.txt 
-rw-r--r-- 1 root root 10G Oct 25 14:58 test.data.fruncate.txt
[email protected]:/data/tmp#du -sh test.data.fruncate.txt 
24K    test.data.fruncate.txt

2. fseek fputs填充文件的最后一个字节
#include <stdio.h>
#include <unistd.h>

int main()
{
    FILE *f = fopen("test.data", "w");
    fseek(f, 256*1024*1024 - 1, SEEK_CUR);
    fputc(0,f);
    return 0;
}

3. dd命令
         dd if=/dev/zero of=test bs=1M count=0 seek=1024

4. 额外补充:
1 .ls显示文件的“逻辑上”的size, 这不是文件真正占用磁盘空间大小,这部分空间也会被其他进程使用。
2 .du显示文件“物理上”的size,即du显示的size是文件在硬盘上占据了多少个block计算出来的

三、真:磁盘预分配—fallocate
1. 使用fallocate 或者posix_fallocate函数
请求tlinux内核大神后,原来还存在fallocate 和 posix_fallocate这样的函数, 还是自己太low, 其实fallocate 和 posix_fallocate两个最大的区别:

This is a nonportable, Linux-specific system call

废话也不多说, 还是直接上代码比较好一点, 一目了然

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>


uint64_t file_size = 10*1024*1024*1024ULL;


//int fallocate(int fd, int mode, off_t offset, off_t len);
//int posix_fallocate(int fd, off_t offset, off_t len);


int main()
{
   int fd = -1;
   int ret = -1;   

   fd = open("tmp.txt", O_CREAT|O_RDWR, 0666);
   if(fd < 0){
     printf("fd < 0");
     return -1;
   } 
   
   //ret = fallocate(fd, 0, 0, file_size);
   ret = posix_fallocate(fd, 0, file_size);
   if(ret < 0 ){
      printf("ret = %d, errno = %d,  %s\n", ret, errno, strerror(errno));
      return -1;
   }

   printf("fallocate create %.2fG file\n", file_size/1024/1024/1024.0);

   close(fd);
   
   return 0;
}
测试结果:

[email protected]:/data6#time ./posix_fallocate 
fallocate create 10.00G file

real    0m0.014s
user    0m0.000s
sys    0m0.014s
[email protected]:/data6#ll -h posix_fallocate.file.txt 
-rw-r--r-- 1 root root 10G Oct 25 15:45 posix_fallocate.file.txt
[email protected]:/data6#du -sh posix_fallocate.file.txt 
11G    posix_fallocate.file.txt


不仅可以占住空间,而且速度非常快(), 之前有过一个愚蠢的想法, 用dd命令直接创建10G文件,但是会造成IO毛刺,肯定不能这么玩,要是创造100G文件岂不是凉凉了。dd命令还是安安静静压测下磁盘性能或者创造一些小文件比较好。

2. 额外补充
磁盘空间预分配,不是所有linux系统都支持,有时候就分配失败,这就没有办法了。如下
ret = -1, errno = 95,  Operation not supported
1
linux命令磁盘预分配—fallocate
[email protected]:/data6#fallocate -l 10G  2.txt
[email protected]:/data6#ll -h 2.txt   
-rw-r--r-- 1 root root 10G Oct 25 15:33 2.txt
[email protected]:/data6#du -sh 2.txt 
11G    2.txt
--------------------- 

猜你喜欢

转载自blog.csdn.net/huabiaochen/article/details/86672480