web-dev-qa-db-ja.com

Linuxでブロックデバイスを調整するにはどうすればよいですか?

/ dev/sda2の最後の1024バイトだけを取得しようとしています。私がする時 Sudo tail -c 1024 /dev/sda2 | hd、Ctrl-Cを押すまでプロンプトがハングします。しかし、私がtail -c 1024 ddfilecopyofsda2 | hd、ファイルの最後の1024バイトのNice出力をすぐに取得します。私はここを読んだ( https://unix.stackexchange.com/questions/60034/what-are-character-special-and-block-special-files-in-a-unix-system ) 「ブロックデバイスは通常シーク可能です」ので、何が欠けていますか?

4
clearcom0

ブロックデバイスの最後の1024バイトを取得する1つの方法は次のとおりです。

_last_bytes() { Sudo dd if=$2 iflag=skip_bytes skip=$(($(Sudo blockdev --getsize64 $2) - $1)) bs=1M ; } ; last_bytes 1024 DEVICE
_

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_を検索すると、ではなくブロックデバイスとして開かれます。通常のファイル。

実装の詳細は、tailfstat() を呼び出してファイルに関する情報を取得することです。

通常のファイルの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
_

fstat()は_st_size=175500_を提供します。ここで、tailは1024バイトをカウントバックする必要があります。

175500-1024 = 174476

…そしてこれはまさにtailが行うことです:

_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
_

_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
_

blockdevはブロックデバイスのioctlを取得するためのものであり、_BLKGETSIZE64_はブロックデバイスのサイズを取得するためのものです。


whytailが_BLKGETSIZE64_を実行しない理由については、わかりません。 ソースコード は次のことを示しています。

_#define IS_TAILABLE_FILE_TYPE(Mode) \
  (S_ISREG (Mode) || S_ISFIFO (Mode) || S_ISSOCK (Mode) || S_ISCHR (Mode))
_

その行から、 S_ISBLK() がなければ、作者はtailがブロックデバイスをサポートすることを意味していなかったことがわかります。

8
Deltik