![dd 为何会导致主机无响应?](https://linux22.com/image/727626/dd%20%E4%B8%BA%E4%BD%95%E4%BC%9A%E5%AF%BC%E8%87%B4%E4%B8%BB%E6%9C%BA%E6%97%A0%E5%93%8D%E5%BA%94%EF%BC%9F.png)
我昨天以 root 身份
dd if=/dev/zero of=/var/lib/libvirt/images/dat.img bs=1G count=1000
这使得服务器在几个小时内完全没有响应。
RAID 控制器是 HP P410,带有 4 个磁盘(RAID 1+0)。
是我使用的问题bs=1G
还是 CentOS 需要内核参数,因此繁重的 I/O 不能使主机停止运行?
问题
谁能解释为什么会发生这种情况?
附言:下次我将创建一个稀疏文件,但是现在我想了解如何防止 I/O 超出主机最大容量。
答案1
简短回答:服务器变得无响应,因为您用脏页(即要刷新的数据)填充了几乎所有的内存。
长答案:通常,写入不会立即将数据推送到备份设备。相反,它们被缓存在页面缓存中。这样做是出于性能原因:与 CPU/内存相比,存储(尤其是 HDD)非常慢,因此尽可能多地缓存可以显著提高 I/O 速度。但是,如果你写入太多,页面缓存将疯狂地(并以高优先级)将尽可能多的数据刷新到磁盘。这会导致调用进程进入“深度睡眠” - 这意味着你不能中断它,因为它没有真的运行,而是等待被内核唤醒。而且,由于脏数据刷新是一项高成本、高优先级的操作,整个服务器会变得非常慢。
话虽如此,如何才能在不使服务器运行缓慢的情况下创建大型图像文件?你有不同的选择:
- 启动你的
dd
命令附加oflag=direct
选项:这将dd
导致绕过页面缓存,直接写入磁盘。我还建议使用较小的缓冲区,即:1 MB,使用类似的东西dd if=/dev/zero of=/var/lib/libvirt/images/dat.img bs=1M count=1000000
。请注意,上面的命令将要在执行过程中会稍微减慢服务器的速度(毕竟您正在写入磁盘),但不会达到您第一次尝试的速度; - 创建完全分配文件的更好方法是使用命令
fallocate
,即:fallocate /var/lib/libvirt/images/dat.img -l 1G
。通过元数据处理进行分配,而不是写入任何实际数据,此命令将几乎立即返回,不会造成任何减速。许多现代文件系统都支持它,但 ZFS 除外; - 最后,你可以使用稀疏文件- 具有名义大小但未实际分配的文件。您可以通过发出来创建它
truncate --size=1G /var/lib/libvirt/images/dat.img
。此命令将立即返回,基本上几乎不会引起任何 I/O。
答案2
dd
分配一个大小的缓冲区bs
- 如果这是相当大一部分内存,它将取代其他内存并导致交换。
更糟糕的是,bs
缓冲区在一次操作中就被写出。这可能会在一段时间内束缚你的存储系统。再加上上面的交换,这可能会严重束缚系统。
因此,对于您的任务来说,使用它是个合理的选择bs=16M
。它有足够大的缓冲区大小,可以实现高效的 I/O,同时粒度足够细,不会占用太多空间。