SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|

2008-06-08(Sun) USBメモリを素因数分解する

  Fedora9、××チューンシリーズはもう少し続くが、今日は小休止。ネタとしては似たようなもんだが。

  オイラは以前にSIRENというメーカのUM-100-512SというUSBメモリを名指しで購入したのだが、最近になってそのチップがSLC構造だと知った。かなりの時を経てのイキナリのポイントアップだ。

  オイラは過去に、特に下調べせずに買ったCD-RドライブであるCD-R56S-600、主力機が死んで慌てて買ったマザーボードであるCUB-Xと、かなり使い込んだ後で、それが名機であったことに気づかされることが度々あるが、それを想起させる。

  で、改めてそれをモバイルCVSレポジトリにしようと思い、ゴチャゴチャとした中身を吸い出して、フォーマットしようとしたのだが、悩んだのがvfat領域をどうするかということ。やはり、ちょっと使いたい時のためにWindowsからも使える領域があった方がいい。

  fdiskしてジオメトリを確認してみる。

Disk /dev/sdc: 523 MB, 523632640 bytes
255 heads, 63 sectors/track, 63 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

  全部で63シリンダだ。するってーと、ext3に49、vfatに14、あたりで割るのがいいかなぁ……っと、そうだ。その前に、スッキリとゼロクリアしておくか。ついでにパフォーマンスも計っておこう。

# time dd if=/dev/zero of=/dev/sdb
dd: writing to `/dev/sdb': デバイスに空き領域がありません
1022721+0 records in
1022720+0 records out
523632640 bytes (524 MB) copied, 248.831 seconds, 2.1 MB/s
real    4m8.864s
user    0m0.742s
sys     0m3.612s

  よし、改めてfdisk、と……あ、あれ?

Disk /dev/sdb: 523 MB, 523632640 bytes
17 heads, 59 sectors/track, 1019 cylinders
Units = cylinders of 1003 * 512 = 513536 bytes

  なんか、さっきとジオメトリが変わってるような……いや、さっきは間違いなく63シリンダだったハズッ!! なんだこれぇ!? ヘッドやセクタって装置に固有だったんじゃないのぉ!?

  こんなことが起きると、ちょっと計算してみたくなる。ヘッドxセクタxシリンダ数……いわゆるCHSで使える容量と、一番上のバイト数との差だ。

17 x 59 x 1019 x 512 = 523,293,184
523,632,640 - 523,293,184 = 339,456

  結構な差がある。つまり、この339KB強は端数であり使えない領域なわけだ。こんな無駄はなくしたい。つーか、もしかして、このあたりの数値ってfdiskで指定できたりなんかしちゃったりして……

# man fdisk
 
-H heads
 Specify the number of heads of the disk. (Not the physical
 number, of course, but the number used for partition tables.)
 Reasonable values are 255 and 16.
 
-S sects
 Specify the number of sectors per track of the disk. (Not the
 physical number, of course, but the number used for partition
 tables.) A reasonable value is 63.

  ……できるじゃんッ!? もちろん物理番号じゃないぜ、って書いてあるけど、もともとこれらは物理的な概念でしょーが。驚いたなぁ、もう。

  となると、うまくすれば、無駄な領域をゼロにできるんでない? manページには255と63がリィズナボォ(妥当)とあるけど、その論理がわからん。いいや、試しちゃえ。

  で、ここでリングに上がるのが素因数分解。昔、授業で習ったよね。523,632,640 をガッツンガッツンと2で割るぜッ!!

  2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 5 x 799ッ!!

  799って素数っぽいけど、素数だっけ? 確かめるために「素数」でググる……わ。素数じゃないっぽいぞ。確か、デカい数値の素因数分解って、RSA暗号の基礎理論であり困難だと聞くが(ケタが違うって)……できるかいな。3で割って、7で割って……ダメだ。ヤケクソで17で割って……

  799/17=47

  ……あ、割れた。素数リストを見ると、17も47も素数だ。素因数分解完了ッ!!

  これの値をどう使うかというと、こう使う。

# fdisk -H 47 -S 17 /dev/sdb
Disk /dev/sdb: 523 MB, 523632640 bytes
47 heads, 17 sectors/track, 1280 cylinders
Units = cylinders of 799 * 512 = 409088 bytes

  どれどれ、シリンダ数は……1280か。17 x 47 x 1280 x 512は523632640……523632640ッ!! で、出たッ!! ホールインワンッ!!

  つーわけで、USBメモリの端から端までキッカリと確保することに成功したようだ。こりゃあ気分がいい。例によって、先頭をちょっと空けてふたつの領域に切る。

Disk /dev/sdb: 523 MB, 523632640 bytes
47 heads, 17 sectors/track, 1280 cylinders
Units = cylinders of 799 * 512 = 409088 bytes
Disk identifier: 0x00000000
 
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               3        1024      408289   83  Linux
/dev/sdb2            1025        1280      102272    6  FAT16

  1シリンダのサイズが400KB程度と小さいから、先頭に空けておく領域も1MB以下で済んでいる。なんだよー、こんなことなら、プライマリドライブとして使っているコンパクトフラッシュも工夫すればよかったよ。

  こっちは、16,240,345,088バイトだから……(2^27) x 11 x 11ッ!! こっちもキレイに割れるじゃんッ!!

  一方で、セカンダリドライブである16GBのSDカードは、16,071,000,064バイトだから……2^19×7×29×151……少し微妙だが、7と29を使えば、こっちもキッカリと使い切ることができる。うわぁ、フォーマットをやり直してぇ!!

  なお、このジオメトリという概念は、記憶領域の一部に記録されているものではなく、パーティションテーブルの「雰囲気」や、単純に固定値が採用されるようである。fdiskのソースは以下のようになっている……

    922     get_kernel_geometry(fd);
    923     get_partition_table_geometry();
    924 
    925     heads = user_heads ? user_heads :
    926         pt_heads ? pt_heads :
    927         kern_heads ? kern_heads : 255;
    928     sectors = user_sectors ? user_sectors :
    929         pt_sectors ? pt_sectors :
    930         kern_sectors ? kern_sectors : 63;

  ……ユーザが指定すれば、言い値が採用されることがわかる。しかし、CHSがここまで、観念的な概念に落ちぶれていたとは意外だなぁ。

  ひとつ疑問が残ったのは、そもそもフラッシュディスクの総容量がどう決まっているのか、ということ。相手が円盤なら端数も出そうなもんだが、ゴ盤の目のような構造(たぶん)のメモリで、こんな素数が出てくる道理がわからない。

  CRCや欠陥セクタの領域を除外した結果なのだろうか? どっちにせよ、フラッシュの内部的な物理記録の単位となんらかの関連があるかもしれない。キッカリ合わせると書き込みが効率化するなんて御利益があったりしたりしてね。ほんじゃ。