磁盘预分配

一、磁盘预分配—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;
}

测试结果

root@xxx.xxx.xxx.xxx:/data/tmp#gcc fruncate.c -o fruncate
root@xxx.xxx.xxx.xxx:/data/tmp#time ./fruncate 

real    0m0.001s
user    0m0.000s
sys    0m0.000s
root@xxx.xxx.xxx.xxx:/data/tmp#ll -h test.data.fruncate.txt 
-rw-r--r-- 1 root root 10G Oct 25 14:58 test.data.fruncate.txt
root@xxx.xxx.xxx.xxx:/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;
}
测试结果:

root@xxx.xxx.xxx.xxx:/data6#time ./posix_fallocate 
fallocate create 10.00G file

real    0m0.014s
user    0m0.000s
sys    0m0.014s
root@xxx.xxx.xxx.xxx:/data6#ll -h posix_fallocate.file.txt 
-rw-r--r-- 1 root root 10G Oct 25 15:45 posix_fallocate.file.txt
root@xxx.xxx.xxx.xxx:/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
root@xxx.xxx.xxx.xxx:/data6#fallocate -l 10G  2.txt
root@xxx.xxx.xxx.xxx:/data6#ll -h 2.txt   
-rw-r--r-- 1 root root 10G Oct 25 15:33 2.txt
root@xxx.xxx.xxx.xxx:/data6#du -sh 2.txt 
11G    2.txt
--------------------- 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
专业方向:软件工程-软件工程(ID:07701) 修订人:金虎 ________________________________________ 《操作系统大作业》教学大纲 第一部分 课程目的与任务 一、课程基础: 在学这门课之前,学生必须修过高级语言、数据结构、离散数学方面的基本知识,先修操作系统课程,延时完成操作系统大作业。 二、适应对象: 计算机科学与技术-计算机应用; 软件工程-软件工程; 电子信息科学类-电子信息科学与技术;管理类-信息管理专业 三、教学目的: 为配合《操作系统》课程的教学,通过模拟操作系统原理的实现,使学生能更深刻地领会操作系统工作原理和操作系统实现方法,并提高程序设计能力, 特开设此课程设计。 四、内容提要: 本课要求模拟采用多道程序设计方法的单用户操作系统,该操作系统包括进程管理、存储管理、设备管理和文件管理四部分。 第二部分 内容及基本要求 第1章、进程控制管理实现 ●基本要求:利用简单的结构和控制方法模拟进程结构、进程状态和进程控制。 ●参考学时:8学时 ●参考资料: 用PCB表示整个进程实体,利用随机数方法或键盘控制方法模拟进程执行中产生的事件。或者利用鼠标或者键盘中断的基于图形接口方式的进程控制管理。 1、 定义PCB(可以采用静态结构或动态结构):包括理论PCB中的基本内容,如内部ID、外部ID、进程状态、队列指针。由于无法实现真正的进程创建功能,在实验中只需建立PCB,用它代表完整的进程。 2、 定义进程状态转换方式:进程的状态转换是由进程内部操作或操作系统的控制引起,由于无法实现这些功能,学生可以采用随机数方法或键盘控制方法模拟,并实现对应的控制程序。随机方法指产生1-6的随机数,分别代表创建进程(c)、结束进程(e)、进程阻塞(b)、激活进程(w)、调度进程(p)、时间片到(t)等事件;键盘模拟方法指定义6种按键代表以上6种事件。 3、 根据四种事件处理就绪队列、阻塞队列和当前执行中的进程。 每次事件处理后应形象地显示出当前系统中的执行进程是哪一个,就绪队列和阻塞队列分别包含哪些进程。 第2章、请求分页式存储管理的地址转换过程实现: ●基本要求:实现分页式存储地址转换过程,在此基础上实现请求分页的地址转换。实现请求页式地址转换中出现的缺页现象时,用到的先进先出FIFO、最近最久未使用LRU、最佳OPT置换算法。 ●参考学时:8学时 ●参考资料: 利用键盘输入本模拟系统的物理块的大小,作业的页表中的块号;完成逻辑地址转换成相应的物理地址的过程。 1、建立一张位示图,用来模拟内存的分配情况,利用随机数产生一组0和1的数对应内存的使用情况。 2、输入块(页)的大小,通过模拟位示图为本作业分配内存空间建立相应的页表(长度不定); 3、录入逻辑地址转换成相应的物理地址 4、扩充页表,变成请求式的二维页表(增加存在位等)完成地址转换。 5、输入分配给本作业的块数,模拟作业执行的逻辑地址转换成页面调度次序; 6、分别采用OPT、FIFO、LRU置换算法,利用堆栈结构完成页面置换;记录被换出的页面和新换入的页面。 第3章、设备管理实现: ●基本要求:设备管理主要包括设备的添加和删除、设备的分配和回收、同时实现设备独立性。 ●参考学时:6学时 ●参考资料: 假定模拟系统中有键盘、鼠标、打印机和显示器四个设备,三个控制器和两个通道,采用安全分配方式。 1、设备管理子系统涉及到系统设备表(SDT)、通道控制表(CHCT)、控制器控制表(COCT)和设备控制表(DCT)来体现输入输出系统的四级结构和三级控制。我们模拟这样的数据结构来完成对外围设备的管理。 (1)添加设备:增加对应的设备控制表和系统设备表中的表项,如果需要新建对应的控制器控制表。 (2)删除设备:删除对应的设备控制表和系统设备表中的表项,如果需要删除对应的控制器控制表。 2、设备的分配和回收,进程申请设备的时候,建立起通路,即获成功;否则阻塞到通道、控制器或设备上面。进程回收设备的时候,把阻塞进程唤醒。 3、设备分配必须满足设备的独立性要求。为了实现设备独立性,要求在驱动程序之上设计一层设备无关软件,其主要功能可分为: (1)执行所有设备的公有操作,主要包括:(a)独占设备的分配与回收;(b)将逻辑设备名映射为物理设备(LUT),进一步可以找到相应物理设备的驱动程序。 (2)向用户层(或文件层)软件提供统一的接口。例如,对各种设备的读操作,在应用程序中都用read; 而对各种设备的写操作,则都使用write。 第4章、文件管理系统实现: ●基本要求:利用交互式命令实现树型目录结构和文件管理,同时利用位示图表示外存的分配情况,新建文件时分配必要的空间,模拟文件分配表记录文件在外存上的存储方式。 ●参考学时:8学时 ●参考资料: 在文件中保存目录内容,创建文件或子目录可以用命令行命令:MD、CD、RD、MK(创建文件)、DEL(删除文件)和DIR。目录项包括文件或目录名称、类型(文件、目录或空目录项)、创建日期以及下一个目录项指针、下一级目录项指针。 1、创建初始文件,建立根目录的“.”和“..”目录项。 2、显示命令提示符“$”。 3、输入命令后根据命令含义完成相应文件操作: MD:在目录文件中创建子目录,同时搜索当前目录最后一个目录项,并保存指针信息; CD:根据当前目录切换到指定目录; RD:搜索所要删除的目录是否为空目录,若是则删除; MK:在当前目录中创建文件名称;(申请空间利用位示图修改FAT) DEL:搜索所要删除的文件是否存在,若是则删除;(恢复位示图修改FAT) DIR:列出当前目录的所有目录项。 4、在创建文件的时候分配空闲的磁盘空间,采用显示链接的方式,利用文件分配表(FAT)记录文件在外存上的存储情况。 5、当删除文件时,回收外存上的空间,修改位示图和文件分配表。 第5章、进程调度算法的实现: ●基本要求:实现先来先服务FCFS、短作业优先SJF以及时间片轮转调度算法。 ●参考学时:6学时 ●参考资料: 根据创建进程的系统时钟,取相对时钟作为进程的到达时间,利用随机数产生每个进程的估计运行时间。利用模拟系统中提供的算法分别计算其相应的周转时间和带权周转时间。 1、利用绝对时间和相对时钟产生一组进程的到达时刻和运行时间。 2、实现FCFS算法:根据进程的到达时间的先后次序来完成对若干进程的调度。 3、实现SJF算法:根据当前时间已经到达进程的需要运行时间选取其中时间最小的进程最先运行。 4、实现时间片轮转算法:首先要求确定时间片的大小,依据进程的到达时间依次加入队列,每次分配一个时间片大小的时间,如果没有完成参与下一次的竞争,当最后需要一个小于等于时间片的时间时本进程完成,同时退出队列。 5、计算每种算法调度后,系统的平均周转时间和平均带权周转时间。
注意: 用vmware-vdiskmanager才完成扩容的第一步,接下来的事情请看我的博客。 http://blog.csdn.net/junglyfine/archive/2009/12/09/4974269.aspx 使用方法: vmware-vdiskmanager 命令语法: vmware-vdiskmanager [选项] VMware Virtual Disk Manager - build 44356. Usage: vmware-vdiskmanager [选项] 虚拟磁盘文件的名字。 #虚拟磁盘文件必须是.vmdk为扩展名。你能够指定一个你想要储存的虚拟磁盘文件的路径。如果你在你的宿主机中映射了网络共享,你也可以提供确切的虚拟磁盘文件的路径信息来创建虚拟磁盘在这个网络共享中。 -c 创建虚拟磁盘。 #你必须用-a, -s 和 -t 并指定选项参数,然后你需要指定所要创建的虚拟磁盘文件的文件名。 -r 转换已经指定类型的虚拟磁盘的类型。 #结果会输出创建一个新的虚拟磁盘。你必须用-t选项来指定你想要转换成的磁盘类型,并且指定目标虚拟磁盘的文件名。 #一旦转换完成,你可以先测试虚拟磁盘以确保它能够像你所希望的那样工作,然后再删除原来的那个虚拟磁盘文件。 #为了让虚拟机重新认识转换后的虚拟磁盘,你应该使用虚拟机设置编辑器先从虚拟机中移除先前存在的虚拟磁盘,然后添加转换好的虚拟磁盘给虚机。 -x [GB|MB] 增大虚拟磁盘到指定的容量。你必须指定新的更大尺寸的虚拟磁盘用GB或MB单位标示。你不能改变物理磁盘的大小。 #在你运行虚拟磁盘管理软件前,你应该先备份虚拟磁盘文件。因为vmware-vdiskmanager会向你的虚拟机配置文件里面写入新配置 -d 对指定的虚拟磁盘碎片整理。 #你只能磁盘碎片整理可增长的虚拟磁盘。你不能磁盘碎片整理分配的虚拟磁盘。 -p 为收缩磁盘做准备处理。 #如果虚拟磁盘被分成多个分区,每个分区必须被单独准备。分区(比如/email或/storage)必须用VMware DiskMount工具映射。 #在你对分区准备处理后,解除对此分区的映射。继续映射虚拟磁盘的其他每个分区,为收缩磁盘作准备处理直到完成虚拟磁盘上的所有分区的准备工作。 #你在同一时刻只能用VMware DiskMount映射虚拟磁盘的一个分区。你仅仅能在宿主机上进行虚拟磁盘的收缩分区准备工作。 -k 收缩指定的虚拟磁盘。你只能够收缩可增长磁盘。你只能在宿主机中用这种方法收缩虚拟磁盘。 #你不能够收缩有虚拟机快照的虚拟磁盘。你可以保持现有虚拟磁盘的状态,而用快照管理器删除所有快照。你也可以放弃自快照以来对虚拟磁盘所做的更改,恢复到快照时状态。 -a [ ide | buslogic | lsilogic ] 指定磁盘适配器的类型。你在创建新的虚拟磁盘时必须指定其类型。 #选择以下类型之一: #ide —— IDE接口适配器 #buslogic —— BusLogic SCSI接口适配器 #lsilogic —— LSI Logic SCSI接口适配器GB或MB做单位。你必须在创建磁盘时指定其大小。 #尽管你必须指定虚拟磁盘的大小,但当你增长它的大小时,你不能用-s可以指定的磁盘大小规定:IDE和SCSI适配器都为最小100MB,最大950GB。 -t [0|1|2|3] 你在创建一个新的虚拟磁盘或者重新配置一个虚拟磁盘时必须指定虚拟磁盘的类型。 #指定以下类型之一: #0 —— 创建一个包含在单一虚拟文件中的可增长虚拟磁盘 #1 —— 创建一个被分割为每个文件2GB大小的可增长虚拟磁盘 #2 —— 创建一个包含在单一虚拟文件中的分配虚拟磁盘 #3 —— 创建一个被分割为每个文件2GB大小的分配虚拟磁盘 -q 禁止虚拟磁盘管理程序写日志 #如果你允许记录日志,日志将会被虚拟磁盘管理程序产生并储存。在虚拟磁盘管理程序运行后,日志的名字和存放位置将会出现在命令行或终端中。 -n 重命名指定的虚拟磁盘。需要指定命名后的虚拟磁盘名字。 为了帮助大家理解,下面举几个例子: vmware-vdiskmanager -c -s 850Mb -a ide -t 0 myIdeDisk.vmdk 创建一个名称为myIdeDisk的大小为850Mb的IDE接口的在一个虚拟机文件中的可增长的磁盘 vmware-vdiskmanager -d myDisk.vmdk 对myDisk进行碎片整理 vmware-vdiskmanager -r sourceDisk.vmdk -t 0 destinationDisk.vmdk 将sourceDisk转换成在一个虚拟机文件中的可增长的磁盘,并命名为destinationDisk vmware-vdiskmanager -x 36Gb myDisk.vmdk 将磁盘myDisk增大至36G vmware-vdiskmanager -n sourceName.vmdk destinationName.vmdk 将磁盘sourceName改名为destinationName 如果在添加共享磁盘后发现只有一台机器能启动,另外一台因为不能打开共享磁盘文件而不能启动的时候,需要对配置文件进行修改: 分别打开两台虚拟机目录中的vmx文件,在最后一行添加: disk.locking="FALSE" scsi0:1.SharedBus="Virtual" scsi1:1.SharedBus="Virtual" 系统启动的时候会锁定磁盘,所以当启动linux1后共享磁盘被锁定了,linux2就起不来了,因此需要加入disk.locking = "false"。 一般来说,如果是scsi1:0,则n为1,也就是scsi1.sharedBus = "virtual" ,表示所有的bus都共享,vmare推荐这种做法。 如果说是不是所有的bus都共享的话,可以将上述scsi1.sharedBus = "virtual"改成scsi1:1.shared = "true" 。 注意: 以上只完成了第一步,想扩容成功请看我的另一个文章 http://blog.csdn.net/junglyfine/archive/2009/12/09/4974269.aspx

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值