命令 dd 中的“seek”参数

use*_*508 25 dd

有人可以向我解释以下几行中发生的事情吗?

dd if=/dev/urandom bs=4096 seek=7 count=2 of=file_with_holes
Run Code Online (Sandbox Code Playgroud)

特别是搜索部分不清楚

手册页说:

 seek=BLOCKS
              skip BLOCKS obs-sized blocks at start of output
Run Code Online (Sandbox Code Playgroud)

什么是 obs 大小的块?

Mar*_*ick 24

dd旨在将数据从输入文件复制到输出文件。该dd块大小选项如下,从手册页

ibs=expr
    Specify the input block size, in bytes, by expr (default is 512).
obs=expr
    Specify the output block size, in bytes, by expr (default is 512).
bs=expr
    Set both input and output block sizes to expr bytes, superseding ibs= and obs=.
Run Code Online (Sandbox Code Playgroud)

dd seek选项类似于 UNIXlseek()系统调用1。它在文件内移动读/写指针。从手册页

seek=n
    Skip n blocks (using the specified output block size) from the beginning of the output file before copying. 
Run Code Online (Sandbox Code Playgroud)

UNIX 中的普通文件有一个方便的特性,您不必从头开始读取或写入它们;你可以在任何地方寻找并从那里开始读或写。所以bs=4096 seek=7意味着从输出文件的开头移动到 7*4096 字节的位置并从那里开始写入。它不会写入文件中 0 到 7*4096 字节之间的部分。

根本没有写入的普通文件区域甚至没有由底层文件系统分配。这些区域称为,文件称为稀疏文件。在您的示例中,file_with_holes开头将有一个 7*4096 字节的洞。(h/t @frostschutz 指出dd默认情况下会截断输出文件。)

读取这些未分配的区域是可以的;你得到一堆零。

[1] 回到dd编写时,类似的系统调用是seek().

  • 请注意,我试图寻找一个驱动器设备(例如:`dd if=/dev/zero bs=512 count=2eek=8388607998 of=/dev/sdd`),但那些“文件”/描述符不是可查找:`dd:/dev/sdd:无法查找:无效参数 0+0 条记录在 0+0 条记录中复制了 0 个字节,0.00765396 秒,0.0 kB/秒` (2认同)

fro*_*utz 7

其他答案解释它了,但如果你有任何疑问,你可以看到什么dd与做strace

$ strace dd if=/dev/urandom bs=4096 seek=7 count=2 of=file_with_holes
# output is shortened considerably
open("/dev/urandom", O_RDONLY)          = 0
open("file_with_holes", O_RDWR|O_CREAT, 0666) = 1
ftruncate(1, 28672)                     = 0
lseek(1, 28672, SEEK_CUR)               = 28672
read(0, "\244\212\222v\25\342\346\226\237\211\23\252\303\360\201\346@\351\6c.HF$Umt\362;E\233\261"..., 4096) = 4096
write(1, "\244\212\222v\25\342\346\226\237\211\23\252\303\360\201\346@\351\6c.HF$Umt\362;E\233\261"..., 4096) = 4096
read(0, "~\212q\224\256\241\277\344V\204\204h\312\25pw9\34\270WM\267\274~\236\313|{\v\6i\22"..., 4096) = 4096
write(1, "~\212q\224\256\241\277\344V\204\204h\312\25pw9\34\270WM\267\274~\236\313|{\v\6i\22"..., 4096) = 4096
close(0)                                = 0
close(1)                                = 0
write(2, "2+0 records in\n2+0 records out\n", 312+0 records in
2+0 records out
) = 31
write(2, "8192 bytes (8.2 kB) copied", 268192 bytes (8.2 kB) copied) = 26
write(2, ", 0.00104527 s, 7.8 MB/s\n", 25, 0.00104527 s, 7.8 MB/s
) = 25
+++ exited with 0 +++
Run Code Online (Sandbox Code Playgroud)

它打开/dev/urandom用于读取 ( if=/dev/urandom),打开file_with_holes用于创建/写入 ( of=file_with_holes)。

然后它截断file_with_holes4096*7= 28672bytes ( bs=4096 seek=7)。截断意味着该位置之后的文件内容丢失。(添加conv=notrunc以避免此步骤)。然后它寻求28672字节。

然后它从 读取4096字节(bs=4096用作ibs/dev/urandom,将4096字节(bs=4096用作obs)写入到file_with_holes,然后是另一个读取和写入(count=2)。

然后它 closes /dev/urandom, closes file_with_holes,并打印它复制了2*4096=8192字节。最后它退出没有错误(0)。


Gra*_*eme 5

obs是输出块大小,ibs是输入块大小。如果您指定bswithoutibsobsthis 用于两者。

因此,在输出开始时,您的搜索将是 7 个 4096 或 28672 字节的块。然后,您将从输入开始到输出中的这一点复制 2 个 4096 或 8192 字节的块。