我正在尝试获取 /dev/sda2 的最后 1024 个字节。当我这样做时sudo tail -c 1024 /dev/sda2 | hd
,提示会一直挂起,直到我按下 Ctrl-C。但是,当 I 时tail -c 1024 ddfilecopyofsda2 | hd
,我立即得到文件最后 1024 个字节的不错输出。我在这里读到(https://unix.stackexchange.com/questions/60034/what-are-character-special-and-block-special-files-in-a-unix-system)“块设备通常是可查找的, “那我错过了什么?
Del*_*tik 10
这是获取块设备的最后 1024 个字节的一种方法:
last_bytes() { sudo dd if=$2 iflag=skip_bytes skip=$(($(sudo blockdev --getsize64 $2) - $1)) bs=1M ; } ; last_bytes 1024 DEVICE
Run Code Online (Sandbox Code Playgroud)
替换DEVICE
为设备路径。在你的情况下,你会使用/dev/sda2
.
现在来回答一个更有趣的问题……
tail -c 1024 /dev/sda2
搜索整个磁盘?原因是如何tail
实施。当tail
知道它正在读取的文件的大小时,它确切地知道要查找多少。否则,它必须一直读取文件或流以找出要倒计时多远。
使用管道,这是有道理的,例如cat /dev/sda2 | tail -c 1024
. tail
正在以流的形式接收内容,无法知道数据何时结束。
您可能希望tail -c 1024 /dev/sda2
能够计算出 的大小/dev/sda2
,但实际上,在tail
查找时/dev/sda2
,它是作为块设备而不是常规文件打开的。
实现细节是tail
调用fstat()
获取有关文件的信息。
tail
在常规文件上这strace
是tail
打开文件示例的相关部分:
21:30:27 open("/var/log/syslog", O_RDONLY) = 3
21:30:27 fstat(3, {st_dev=makedev(0, 22), st_ino=4715, st_mode=S_IFREG|0640, st_nlink=1, st_uid=104, st_gid=4, st_blksize=131072, st_blocks=54, st_size=175500, st_atime=2017/11/10-21:28:39.243133398, st_mtime=2017/11/10-21:30:20.438031639, st_ctime=2017/11/10-21:30:20.438031639}) = 0
21:30:27 lseek(3, 0, SEEK_CUR) = 0
21:30:27 lseek(3, 174476, SEEK_SET) = 174476
Run Code Online (Sandbox Code Playgroud)
fstat()
提供st_size=175500
. 现在tail
只需要倒数 1024 个字节:
175500 - 1024 = 174476
......这正是
tail
它的作用:Run Code Online (Sandbox Code Playgroud)lseek(3, 174476, SEEK_SET) = 174476
tail
在块设备上fstat()
这次不返回大小!:
21:29:43 open("/dev/sda", O_RDONLY) = 3
21:29:43 fstat(3, {st_dev=makedev(0, 6), st_ino=17488, st_mode=S_IFBLK|0660, st_nlink=1, st_uid=0, st_gid=6, st_blksize=4096, st_blocks=0, st_rdev=makedev(8, 0), st_atime=2017/11/10-09:21:15.643998960, st_mtime=2017/11/10-09:21:15.555998962, st_ctime=2017/11/10-09:21:15.555998962}) = 0
Run Code Online (Sandbox Code Playgroud)
没有st_size
,tail
无法知道要查找多远,所以它默认读取整个块设备直到结束。
这就是为什么您通常应该使用块设备工具dd
来操作块设备而不是用于常规文件的工具,例如tail
.
您可能会问,“如何blockdev --getsize64
快速获取块设备的大小?”
这是sudo strace -vvvfts1000 blockdev --getsize64 /dev/sda
:
21:53:15 open("/dev/sda", O_RDONLY) = 3
21:53:15 ioctl(3, BLKGETSIZE64, [512110190592]) = 0
Run Code Online (Sandbox Code Playgroud)
blockdev
用于获取块设备ioctls,并BLKGETSIZE64
获取块设备的大小。
至于为什么 tail
不这样做BLKGETSIZE64
,我不知道。的源代码显示:
#define IS_TAILABLE_FILE_TYPE(Mode) \
(S_ISREG (Mode) || S_ISFIFO (Mode) || S_ISSOCK (Mode) || S_ISCHR (Mode))
Run Code Online (Sandbox Code Playgroud)
我只从那行中知道,没有S_ISBLK()
,作者并不是要tail
支持块设备。
归档时间: |
|
查看次数: |
1256 次 |
最近记录: |