職場では、Oracle VMゲストディスクイメージ用の環境)の一部としてスパースファイルを使用しています。同僚からのいくつかの質問(回答済み)の後、スパースファイルに関する質問が残りました、そしておそらくより広くiノード構造について-stat(2)とstatfs(2)(FreeBSDの場合)のmanページを読むと、Cをもっと知っていればもっと簡単に理解できると思いますが、私のCの知識せいぜい最小限です...
これのいくつかはファイルシステムのタイプに依存していることを理解しています。私は主にFreeBSD/Solarisとext4のUFSに興味があります-ZFSはプラスになるでしょうが、私は希望を持ち続けるつもりはありません:)
Solaris 10、FreeBSD 10.3、CentOS6.7を定期的に使用しています。ここでのコマンドはCentOS 6.7 VMで実行されていますが、FreeBSDと相互参照されています。可能であれば、POSIXの観点から理解を深め、それが不可能な場合はLinuxよりもFreeBSDを優先することに興味があります。
次の一連のコマンドを検討してください。
printf "BIL" > /tmp/BIL
dd of=/tmp/sparse bs=1 count=0 seek=10
dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=10
dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=17
dd of=/tmp/sparse bs=1 count=0 seek=30
dd if=/tmp/BIL of=/tmp/sparse bs=1 count=3 seek=30
ファイル/tmp/BIL
の内容(16進数)は4942 004c
である必要があるため、ファイル/tmp/sparse
をhexdump
すると、全体にこの組み合わせがわずかに表示されます。
%>hexdump sparse
0000000 0000 4942 004c 0000 0000 4942 004c 0000
0000010 4200 4c49 0000 0000 0000 0000 0000 4942
0000020 004c
0000021
%>cat sparse
BILBILBILBIL%
1。2番目の "BIL"が順不同で表示されるのはなぜですか?つまり、4200 4c49
ではなく4942 004c
?これは、3番目のdd
コマンドによって作成されました。
2。cat
および他のツールはどのようにして正しい順序で印刷することを知っていますか?
ls
を使用すると、使用されたとされるスペースと割り当てられたブロックを確認できます。
%>ls -ls /tmp/sparse
8.0K -rw-r--r--. 1 bil bil 33 May 26 14:17 /tmp/sparse
申し立てられたサイズは33バイトですが、割り当てられたサイズは8キロバイトです(ファイルシステムのブロックサイズは4Kです)。
。ls
のようなプログラムは、「申し立てられた」サイズと割り当てられたサイズをどのように区別しますか?
割り当てられたサイズが直接ブロックと間接ブロックを歩くことによって計算されている間にinodeに格納された「疑わしい」数値かどうか疑問に思いましたが、歩くことによる計算には時間がかかり、ls
などのツールがすぐに戻るためこれは正しくありません、非常に大きなファイルの場合でも。
4。iノード情報の問い合わせに使用できるツールは?
stat
を知っていますが、iノード内のすべてのフィールドの値を出力していないようです...
5。直接ブロックと間接ブロックを歩くことができるツールはありますか?
ディスク上の各アドレスと、データがどのように格納されるかについてもう少し理解するための内容を見るのは興味深いでしょう
上記の他のコマンドの後に次のコマンドを実行すると、ファイル/tmp/sparse
が切り捨てられます。
%>dd of=/tmp/sparse bs=1 count=0 seek=5
%>hexdump sparse
0000000 0000 4942 004c
0000005
6。dd
がファイルを切り捨てて、dd
または別のツールがファイルの途中に書き込むことができるのはなぜですか?
最後に、スパースファイルはスペースを事前に割り当てるための良いアイデアのように見えますが、コマンドがファイルを切り捨てたり、任意に大きくしたりしないというファイルシステムまたはオペレーティングシステムレベルの保証はないようです。
7。スパースファイルが縮小/拡大されるのを防ぐメカニズムはありますか?そうでない場合、なぜスパースファイルが役立つのですか?
上記の各質問は個別のSO質問である可能性がありますが、それらはすべて基礎となる理解に関連しているため、分析することはできません。
いくつかの簡単な答え:最初に、スパースファイルを作成しませんでした。これらの追加コマンドを試してください
dd if=/tmp/BIL of=/tmp/sparse seek=1000
ls -ls /tmp/sparse
サイズは512003バイトですが、必要なのは8ブロックだけです。 nullバイトはブロック全体を占める必要があり、ファイルシステム内でスパースになる可能性があるため、ブロック境界上にある必要があります。
「BIL」の2番目の出現が順不同であるのはなぜですか?
リトルエンディアンシステムを使用していて、出力をショートパンツで書き込んでいるためです。 catのようにバイトを使用します。
猫や他のツールはどのようにして正しい順序で印刷することを知っていますか?
それらはバイトで機能します。
Lsのようなプログラムは、「割り当てられた」サイズと割り当てられたサイズをどのように区別しますか?
ls
などは、次の2つの値を返すstat(2)
システムコールを使用します。
st_size; /* total size, in bytes */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
Iノード情報を調べるためにどのツールを使用できますか?
統計は良いです。
直接ブロックと間接ブロックを歩くことができるツールはありますか?
Ext2/3/4では、hdparm --fibmap
をファイル名とともに使用できます。
$ Sudo hdparm --fibmap ~/sparse
filesystem blocksize 4096, begins at LBA 25167872; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
512000 226080744 226080751 8
debugfs
を使用することもできます。
$ Sudo debugfs /dev/sda3
debugfs: stat <1040667>
Inode: 1040667 Type: regular Mode: 0644 Flags: 0x0
Generation: 1161905167 Version: 0x00000000
User: 127 Group: 500 Size: 335360
File ACL: 0 Directory ACL: 0
Links: 1 Blockcount: 664
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x4dd61e6c -- Fri May 20 09:55:24 2011
atime: 0x4dd61e29 -- Fri May 20 09:54:17 2011
mtime: 0x4dd61e6c -- Fri May 20 09:55:24 2011
Size of extra inode fields: 4
BLOCKS:
(0-11):4182714-4182725, (IND):4182726, (12-81):4182727-4182796
TOTAL: 83
Ddがファイルを切り捨てて、ddまたは別のツールがファイルの途中に書き込むことができるのはなぜですか?
はい、dd
は途中で書き込むことができます。 conv=notrunc
を追加します。
スパースファイルが縮小/拡大されるのを防ぐメカニズムはありますか?そうでない場合、なぜスパースファイルが役立つのでしょうか。
いいえ。スペースを取らないからです。
ファイルのまばらな側面は、プログラムに対して完全に透過的である必要があります。これは、プログラムがファイルを更新すると、まばらさが失われる場合があることを意味します。
一部のコピーユーティリティには、まばらさを維持するオプションがあります(例:tar --sparse
、rsync --sparse
)。
cp --sparse=always
を使用して、ファイル内の適切に配置されたゼロブロックをスパースネスに明示的に変換できます。逆に、cp --sparse=never
を使用して、スパーススペースを実際のゼロに変換できます。
Linuxでファイルレイアウトをダンプするためのより良いツールは、e2fsprogs
パッケージに含まれているfilefrag
ユーティリティです。これにより、ファイル内のすべてのエクステントが効率的かつコンパクトにダンプされます。
$ dd of=/var/tmp/sparse if=/dev/zero count=1
$ dd of=/var/tmp/sparse if=/dev/zero seek=1000 count=1
$ filefrag -v /var/tmp/sparse
Filesystem type is: ef53
File size of /var/tmp/sparse is 512512 (126 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 0: 3441408.. 3441408: 1:
1: 125.. 125: 3441533.. 3441533: 1: 3441409: last,eof
/var/tmp/sparse: 2 extents found
FIEMAP ioctlは、ほとんどの一般的なLinuxファイルシステム(ext4、XFS、Btrfsなど)で利用できますが、ZFSではまだ利用できません(開発中です)。