advcal20161215
の編集
https://khfdpl.osask.jp:443/wiki/?advcal20161215
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
-- 雛形とするページ --
2016_10
2016_11
2016_12
BracketName
Essen
Essen0
Essen1
Essen2
Essen3
Essen4
EssenMemo0001
EssenMemo0002
EssenMemo0003
EssenMemo0004
EssenMemo0005
EssenMemo0006
EssenMemo0007
EssenMemo0008
EssenMemo0009
EssenMemo0010
EssenMemo0011
EssenR2
EssenR2_ess03f
EssenR2_ess03h
EssenR2_ess03i
EssenR2_ideas
EssenR2_jit00
EssenR2_jit01
FormattingRules
FrontPage
Help
IP
InterWiki
InterWikiName
InterWikiSandBox
K
KHPC
KHPC_v000doc01
KHPC_v001doc01
KHPC_v002doc01
KHPC_v003doc01
MenuBar
OSC
OSC20181027
OSC20190222
OSC20191123
OSC20230401
OSC20230528
OSC20231021
OSC20240310
OSC20241026
OSC20250221
PHP
PukiWiki
PukiWiki/1.4
PukiWiki/1.4/Manual
PukiWiki/1.4/Manual/Plugin
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/H-K
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/V-Z
RecentDeleted
SandBox
SltVA
VariableArray
WikiEngines
WikiName
YukiWiki
advcal20161205
advcal20161206
advcal20161209
advcal20161210
advcal20161215
eoml0001
eoml0002
essen_ex01_0001
impressions
kcl_malloc
khfdpl_result1
members
memo0001
memo0002
note0001
note0002
note0003
note0004
note0005
note0006
oldworks
oldworks00
oldworks06
oldworks12
oldworks13
osaskjp_index
persistent_C
populars
pr20161105
pr20161105b
scsc
seccamp2017
spam_test
uxf
uxf_01
uxf_02
uxp
* FAT16を発展させてみる(改訂版) -(by [[K]], 2016.12.15) ** (0) -この記事は、「自作OS Advent Calendar 2016」の12/15が空欄だったので急きょ書くことにした記事です。 --http://www.adventar.org/calendars/1666 -なんか最近アドベントカレンダばかり書いている気がする・・・。 ** (1) -MS-DOSはFATと呼ばれるファイルシステムを採用していました。ここでは特にFAT16について考えてみようと思います。 -FAT16はディスクを(最大で)65536個のクラスタの集合と考えて、「このクラスタを読み終わったら続きはここにあるよ」という情報を並べたものです。厳密には65536個ではないのですが、でも16ビットであるということを素直に活用すれば、最大は65536個程度にはなります。これがあるおかげでディスクの連続していない領域にもファイルを入れることができて、なかなかよくできた仕組みだと思います。 -ここでFAT16においてクラスタサイズ512バイトというのを考えましょう。・・・512バイトを2880個集めると1440KBになります。FAT16で2880個のクラスタを管理しようとすると6KBを要します。1440KBを管理するために6KBも管理領域が必要というのは、要するに0.42%が犠牲になったということなので、十分にOKです。 -クラスタサイズ512バイトの場合、FAT16の限界では32MBまで管理できることになります。 ** (2) -たったの32MBしか管理できないというのは使い物になりません。そこで世間ではFAT32とかに行くわけですが、FAT32はFAT領域のサイズが大きくなりすぎて全体をオンメモリに置くという簡単なアルゴリズムが使えません。また大きなファイルではFATを何度もたどる必要があり、効率が悪いです。ちなみにFAT32ではFATのサイズは最大で16GBになりえます。これに対してFAT16なら128KBが上限です(クラスタサイズに関わらず)。 -ということで、FAT16だけでどこまで頑張れるかを考えましょう。 -以下はFAT16におけるクラスタサイズと最大容量の対応表です。 |クラスタサイズ512バイト|最大容量32MB| |クラスタサイズ128KB|最大容量8GB| |クラスタサイズ32MB|最大容量2TB| --註:本来のFAT16ではクラスタサイズの最大は64KBですが、ここでは独自拡張をしてクラスタサイズの上限を拡張することを想定しています。 -クラスタサイズ128KBはまだ許せるとして(いやでも許しがたいけど)、クラスタサイズ32MBはちょっとひどい気がします。10バイトのファイルでも32MBを消費してしまいます。かといって最大容量が32MBとか8GBで我慢するというのも苦しいです。 -そこで1つのディスクを複数のFAT16で管理します。この領域はクラスタサイズ512バイトで、この領域はクラスタサイズ128KBで・・・といった具合です。ディスク内のどのファイルもどれか1つのFAT16にしか所属しません。 -どのファイルがどのFATに属するかはOSがファイルのサイズを見て決めます。小さいファイルならクラスタサイズ512バイトに積極的に割り当てます。大きいファイルならクラスタサイズ128KBとか1MBとかのFATに割り当てます。こうすることで、「大きなクラスタに小さいファイルがポツンとおかれて効率が悪い」という状況が起きないようにできます。クラスタサイズ128KBのところに11140KBのファイルを置けば末尾のクラスタは124KBが無駄になるわけですが、それは11140KBから見れば1.1%でしかないので、十分に許容範囲です。 -どのFAT16に入っていてもユーザは特に意識することもなく、普通にopenできてreadもwriteもできます。そこはOSががんばるのです。ただし従来のopenとは異なり、open時に想定ファイルサイズ上限を教えてやる必要はあります。それが分からないとどのFATにおくかを決められないからです。 -この仕組みはディスクをパーティションに分けるとは違います。パーティションはディスクイメージが分かれてそれぞれにルートディレクトリができますが、私の考えている方法はルールディレクトリは一つで、ただFATだけが複数あって、ディレクトリエントリにはファイルの先頭クラスタ番号だけではなく、FAT番号も書かれるのです。 ** (3) -複数のファイルを開く場合、それぞれのファイルの所属FATが異なるかもしれません。その場合はFATも複数オンメモリに置く必要が出てきます。それでも同時に開くファイルの数より多くのFATが必要になることはないので、たかが知れています。 -これらのFAT16はディスク内で一覧があって管理されています。そのディスク内のFAT16の位置とそれによって管理される領域とクラスタサイズが明記されています。たぶん32バイトもあれば1つのFATは記述できるでしょう。だから32KBくらいの領域があれば1024個のFATは登録できそうです。 -もし2TBの中をクラスタサイズ512バイトのFAT16だけで管理するとすると、FAT16は全部で65536個必要になります。これだけの個数のFAT16を管理するとなると、2MBくらいの領域が必要そうです。 -もっと具体的に考えます。 struct Fat16Table { // 32バイト. unsigned char signature[2]; unsigned char crusterSize; // 3:1バイト, 12:512バイト, 20:128KB, 28:32MB,... unsigned char reserved[9]; // とりあえずオールゼロ. unsigned short sizeAll, sizeFree; // クラスタの個数で書く. unsigned char lbaFat[8], lbaCruster[8]; }; -これが連続で並んでいれば、空きのあるFATは十分に高速に探せそうです。ディレクトリエントリには、ファイルの位置を表すところに、どのFATのクラスタ番号なのかを分かるように、FATの番号も書く必要があります。だから32バイトで1ファイルという方式はもうやめましょう。それだと8.3形式の名前しか入りませんしね。 --64バイトで1ファイルにして、以下のようにしたらどうでしょう。 struct Entry { unsigned int name[40]; unsigned int yy, mmddhhmmss; // 8バイト. unsigned short cruster0, flags; unsigned int fatId; // 8バイト unsigned int64 size; // 8バイト. }; ** (9) おまけの余談 -http://www.adventar.org/calendars/1666 の空きマスはだいぶ少なくなってきました。全部うまったらいいなー。 * こめんと欄 #comment
タイムスタンプを変更しない
* FAT16を発展させてみる(改訂版) -(by [[K]], 2016.12.15) ** (0) -この記事は、「自作OS Advent Calendar 2016」の12/15が空欄だったので急きょ書くことにした記事です。 --http://www.adventar.org/calendars/1666 -なんか最近アドベントカレンダばかり書いている気がする・・・。 ** (1) -MS-DOSはFATと呼ばれるファイルシステムを採用していました。ここでは特にFAT16について考えてみようと思います。 -FAT16はディスクを(最大で)65536個のクラスタの集合と考えて、「このクラスタを読み終わったら続きはここにあるよ」という情報を並べたものです。厳密には65536個ではないのですが、でも16ビットであるということを素直に活用すれば、最大は65536個程度にはなります。これがあるおかげでディスクの連続していない領域にもファイルを入れることができて、なかなかよくできた仕組みだと思います。 -ここでFAT16においてクラスタサイズ512バイトというのを考えましょう。・・・512バイトを2880個集めると1440KBになります。FAT16で2880個のクラスタを管理しようとすると6KBを要します。1440KBを管理するために6KBも管理領域が必要というのは、要するに0.42%が犠牲になったということなので、十分にOKです。 -クラスタサイズ512バイトの場合、FAT16の限界では32MBまで管理できることになります。 ** (2) -たったの32MBしか管理できないというのは使い物になりません。そこで世間ではFAT32とかに行くわけですが、FAT32はFAT領域のサイズが大きくなりすぎて全体をオンメモリに置くという簡単なアルゴリズムが使えません。また大きなファイルではFATを何度もたどる必要があり、効率が悪いです。ちなみにFAT32ではFATのサイズは最大で16GBになりえます。これに対してFAT16なら128KBが上限です(クラスタサイズに関わらず)。 -ということで、FAT16だけでどこまで頑張れるかを考えましょう。 -以下はFAT16におけるクラスタサイズと最大容量の対応表です。 |クラスタサイズ512バイト|最大容量32MB| |クラスタサイズ128KB|最大容量8GB| |クラスタサイズ32MB|最大容量2TB| --註:本来のFAT16ではクラスタサイズの最大は64KBですが、ここでは独自拡張をしてクラスタサイズの上限を拡張することを想定しています。 -クラスタサイズ128KBはまだ許せるとして(いやでも許しがたいけど)、クラスタサイズ32MBはちょっとひどい気がします。10バイトのファイルでも32MBを消費してしまいます。かといって最大容量が32MBとか8GBで我慢するというのも苦しいです。 -そこで1つのディスクを複数のFAT16で管理します。この領域はクラスタサイズ512バイトで、この領域はクラスタサイズ128KBで・・・といった具合です。ディスク内のどのファイルもどれか1つのFAT16にしか所属しません。 -どのファイルがどのFATに属するかはOSがファイルのサイズを見て決めます。小さいファイルならクラスタサイズ512バイトに積極的に割り当てます。大きいファイルならクラスタサイズ128KBとか1MBとかのFATに割り当てます。こうすることで、「大きなクラスタに小さいファイルがポツンとおかれて効率が悪い」という状況が起きないようにできます。クラスタサイズ128KBのところに11140KBのファイルを置けば末尾のクラスタは124KBが無駄になるわけですが、それは11140KBから見れば1.1%でしかないので、十分に許容範囲です。 -どのFAT16に入っていてもユーザは特に意識することもなく、普通にopenできてreadもwriteもできます。そこはOSががんばるのです。ただし従来のopenとは異なり、open時に想定ファイルサイズ上限を教えてやる必要はあります。それが分からないとどのFATにおくかを決められないからです。 -この仕組みはディスクをパーティションに分けるとは違います。パーティションはディスクイメージが分かれてそれぞれにルートディレクトリができますが、私の考えている方法はルールディレクトリは一つで、ただFATだけが複数あって、ディレクトリエントリにはファイルの先頭クラスタ番号だけではなく、FAT番号も書かれるのです。 ** (3) -複数のファイルを開く場合、それぞれのファイルの所属FATが異なるかもしれません。その場合はFATも複数オンメモリに置く必要が出てきます。それでも同時に開くファイルの数より多くのFATが必要になることはないので、たかが知れています。 -これらのFAT16はディスク内で一覧があって管理されています。そのディスク内のFAT16の位置とそれによって管理される領域とクラスタサイズが明記されています。たぶん32バイトもあれば1つのFATは記述できるでしょう。だから32KBくらいの領域があれば1024個のFATは登録できそうです。 -もし2TBの中をクラスタサイズ512バイトのFAT16だけで管理するとすると、FAT16は全部で65536個必要になります。これだけの個数のFAT16を管理するとなると、2MBくらいの領域が必要そうです。 -もっと具体的に考えます。 struct Fat16Table { // 32バイト. unsigned char signature[2]; unsigned char crusterSize; // 3:1バイト, 12:512バイト, 20:128KB, 28:32MB,... unsigned char reserved[9]; // とりあえずオールゼロ. unsigned short sizeAll, sizeFree; // クラスタの個数で書く. unsigned char lbaFat[8], lbaCruster[8]; }; -これが連続で並んでいれば、空きのあるFATは十分に高速に探せそうです。ディレクトリエントリには、ファイルの位置を表すところに、どのFATのクラスタ番号なのかを分かるように、FATの番号も書く必要があります。だから32バイトで1ファイルという方式はもうやめましょう。それだと8.3形式の名前しか入りませんしね。 --64バイトで1ファイルにして、以下のようにしたらどうでしょう。 struct Entry { unsigned int name[40]; unsigned int yy, mmddhhmmss; // 8バイト. unsigned short cruster0, flags; unsigned int fatId; // 8バイト unsigned int64 size; // 8バイト. }; ** (9) おまけの余談 -http://www.adventar.org/calendars/1666 の空きマスはだいぶ少なくなってきました。全部うまったらいいなー。 * こめんと欄 #comment
テキスト整形のルールを表示する