Categories Books | Hard | Hardware | Linux | MCU | Misc | Publish | Radio | Repository | Thoughts | Time | UNIX | Writing | プロフィール
USB メモリの普及により、フロッピィディスクは絶滅寸前の状況にありますが、このレガシィデバイスには Sense of wonder と、教科書には書かれていない多くの宝が眠っています。Linux 上に用意されている小洒落たツールを活用して、誰も見向くことのなくなってしまったフロッピィディスクに、ふたたびスポットライトをあててみましょう。
これからの実験は、是非とも手元に Linux 環境を用意し、実際に自分の手で実行してみることをお勧めします。Linux であれば、ディストリビューションは問いませんが、最近流行りの仮想環境はバツです。「ハードウェアを深く味わう」場合、仮想環境では役に立ちません。
なお、今後使用する各種のツールは Linux 上で誕生した特殊ツールであり、恐らく *BSD には存在しません(近い機能を持つものはあるかもしれませんが)。Linux カーネルのフロッピィディスク・ドライバは、異様なまでに高機能であり、廃人御用達のユーザースペースツールが各種取り揃えられています。
ツールを使う場合、フロッピィディスクのデバイス名として /dev/fd0 を指定しますが、このスペシャルファイルのオーナーおよびパーミッションは Debian etch の場合、次のようになっています。
$ ls -l /dev/fd0 brw-rw---- 1 root floppy 2, 0 2006-12-18 09:08 /dev/fd0
一般ユーザーに /dev/fd0 の読み書きは許可されておらず、スーパーユーザもしくは "floppy グループ" に属しているユーザのみ、フロッピィディスクを操作可能になっています。そこで、vigr コマンドなどを使い、あらかじめ自分を floppy グループに追加しておくか、コマンドをスーパーユーザ権限で実行してください。私は、自身を floppy グループに所属させています。
$ id uid=1000(wataru) gid=1000(wataru) groups=0(root),24(cdrom),25(floppy),40(src),1000(wataru)
それでは、消去しても構わないディスケットをドライブに挿入し、以下のコマンドを実行してください。
$ superformat /dev/fd0 Measuring drive 0's raw capacity In order to avoid this time consuming measurement in the future, add the following line to /etc/driveprm: drive0: deviation=-640 CAUTION: The line is drive and controller specific, so it should be removed before installing a new drive 0 or floppy controller. Verifying cylinder 79, head 1 mformat -s18 -t80 -h2 -S2 -M512 a:
Linux 界では有名な superformat コマンドです。フロッピィディスクの物理フォーマットには、一昔前まで fdformat コマンドが使用されていましたが、現在はなぜか superformat が主流となっています。ちなみに、superformat は Fdutils パッケージ、fdformat は util-linux パッケージに由来しています。
superformat の出力メッセージを観察すると、"Measuring drive 0's raw capacity" (etc/driveprm を登録している場合は表示されません)や、"mformat -s18 -t80 -h2 -S2 -M512 a:" という不可思議な処理内容が含まれています。実は、superformat は裏方で余分な作業をふたつ行っており、フォーマットに余計な時間がかかるのです。"Measuring ..." のメッセージが意味するところは、次回解析するとして、後者の mformat は前回紹介した MS-DOS FAT ファイルシステムでフロッピィディスクを初期化するための処理です。
世間一般では、「フォーマット」という表現が曖昧に使われているケースが多く、読者に誤解をもたらす原因になっているようです。フロッピィディスクにおいて「フォーマット」という言葉が使われた場合、その処理内容にはふたつの仕事が含まれていると考えて良いでしょう。具体的には、
のふたつです。
以前解説した通り、市販されている 3.5インチのフロッピィディスクは、フォーマット前には 16,000,000 ビット (2,000,000 バイト)の容量を有しています。この、「更地状態」にある磁気ビットは、物理フォーマットにより、緩衝帯・インデックスマーク・IDフィールド・データフィールドなどに区画整理されます。
データフィールドは、さらに4つのサブフィールドから構成され、先頭から順番に
が格納されています。一般的なシステムプログラミングの対象となるセクターの実体は、データフィールド中に格納されている「データ領域」です。
次回明らかになりますが、ディスクモーターの回転は比較的不安定であるため、読み込み・書き込み時の変動に耐えられるように、緩衝帯やビット同期機構、そしてエラーチェック機構(CRC コードの挿入)が設けられているのです。この結果、ディスク容量は物理フォーマット後に 1440 KiB まで目減りしてしまいます。
物理フォーマットが完了すると、ファイル群を管理するために必要な領域を確保し初期化する、ファイルシステムの作成が行われます。具体的には、MS-DOS の場合は、ディレクトリ領域, FAT 領域の初期化、UNIX では、スーパーブロックの作成・i-node 領域の初期化などが実行されます。
MS-DOS の FORMAT.COM コマンドは、物理フォーマットとファイルシステム作成(mkfs: MaKe FileSystem)を同時に行いますが、この慣習の影響か、「それでは、フロッピィディスクをフォーマットしましょう」という安易な表現をよく見かけます。正しい理解のためには、(物理)フォーマットと mkfs を厳密に区別して使うべきでしょう。
さて、superformat も FORMAT.COM コマンドと同様に、物理フォーマット後、自動的に FAT ファイルシステムを生成するため、mdir コマンドを実行するとディレクトリ構造を確認することができます。
mdir は、Mtools パッケージに含まれるコマンドのひとつであり(mformat も同パッケージ由来)、Linux 上から MS-DOS のシェル(COMMAND.COM)感覚で DIR 命令を実行することができます。
$ mdir a: Volume in drive A has no label Volume Serial Number is 50F4-8688 Directory for A:/ No files 1 457 664 bytes free
引数が /dev/fd0 ではなく、MS-DOS に倣い "a:" となっている点に注目してください。芸が細かいですね。出力結果は DIR 命令そのままで、使用可能領域は 1,457,664 バイトと表示されています。MS-DOS 標準フォーマット時のディスケット容量は 1,440 KiB (1,474,560 バイト)のはずですが、表示されている値が 16,896 バイト小さい理由は、FAT やディレクトリ領域がシステム用に予約されているためです。
さて、UNIX の素晴らしい点のひとつは、すべてのデバイスをファイルとして取り扱うことができる点です。初期化したフロッピィディスクの内容を dd コマンドを使い、バイナリイメージとして読み込んでみましょう。
$ dd if=/dev/fd0 of=superformat.boot bs=512 count=1 1+0 records in 1+0 records out 512 bytes (512 B) copied, 0.848674 seconds, 0.6 kB/s Etch: ~/CAS2/fdrawcmd $ hexdump -C superformat.boot 00000000 eb 3c 90 4d 54 4f 4f 4c 33 39 39 00 02 01 01 00 |?<.MTOOL399.....| 00000010 02 e0 00 40 0b f0 09 00 12 00 02 00 00 00 00 00 |.?.@.?..........| 00000020 00 00 00 00 00 00 29 2a 55 23 7d 4e 4f 20 4e 41 |......)*U#}NO NA| 00000030 4d 45 20 20 20 20 46 41 54 31 32 20 20 20 fa 31 |ME FAT12 ?1| 00000040 c0 8e d8 8e c0 fc b9 00 01 be 00 7c bf 00 80 f3 |?.?.???..?.|?..?| 00000050 a5 ea 56 00 00 08 b8 01 02 bb 00 7c ba 80 00 b9 |??V...?..?.|?..?| 00000060 01 00 cd 13 72 05 ea 00 7c 00 00 cd 19 00 00 00 |..?.r.?.|..?....| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 |................| 000001c0 01 00 01 01 12 4f 00 00 00 00 40 0b 00 00 00 00 |.....O....@.....| 000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U?| 00000200
if オプション(Input File)でフロッピィディスク、of オプション(Output File)で出力ファイル名、bs オプション(Block Size)でセクターのバイト長、count オプションで読み込みセクター数を指定しています。出力された 512 バイトの superformat.boot は、/dev/fd0 デバイスの先頭 512 バイト、すなわちブートセクターの内容に相当します(アスタリスクは、同じバイトデータが続いていることを示す)。
先頭付近に "MTOOL399" という、Mtools のサインが見えますし、最終尾(0x1FE-0x1FF)には "0x55 0xAA" というブートセクターであることを示す、disk signature が見えます。確かにフロッピィディスクのセクターイメージが、ブロックデバイスを通して読み込めています。
/dev/fd0 ブロックデバイスの全体は
Surface 0 / Track 0 / Sector 1 --> 18 Surface 1 / Track 0 / Sector 1 --> 18 Surface 0 / Track 1 / Sector 1 --> 18 Surface 1 / Track 1 / Sector 1 --> 18 Surface 0 / Track 2 / Sector 1 --> 18 Surface 1 / Track 2 / Sector 1 --> 18 ... Surface 0 / Track 79 / Sector 1 --> 18 Surface 1 / Track 79 / Sector 1 --> 18
の順で、合計 2880 セクターからなる単一ファイルに再構成されます。実際にこの順番で再構成されているのか、実験で確認してみましょう。最初に、ファイルシステム中に目印となるテキストファイルを作成しておきます。
$ uname -a > uname $ mcopy uname a: $ mdir a: Volume in drive A has no label Volume Serial Number is 7D23-552A Directory for A:/ uname 78 2007-02-02 2:00 uname 1 file 78 bytes 1 457 152 bytes free $ mtype a:uname Linux Etch 2.6.15-1-686-smp #2 SMP Mon Mar 6 15:34:50 UTC 2006 i686 GNU/Linux
uname コマンドの出力結果を uname ファイルとして作成し、mcopy コマンドを使いディスケット上に転送します。mtype は、FAT ファイルシステム上のテキストファイルをタイプするためのコマンドですが、確かに uname -a コマンドの結果が保存されています。
次に、現在のフロッピィディスクの全内容をバイトイメージとして、superformat.img ファイルに書き出します。
$ time dd if=/dev/fd0 of=superformat.img 2880+0 records in 2880+0 records out 1474560 bytes (1.5 MB) copied, 50.26 seconds, 29.3 kB/s real 0m50.263s user 0m0.004s sys 0m0.039s
/dev/fd0 デバイスの内容を丸ごと superformat.img ファイルとして出力していますが、2880 レコードの読み込み後に終了しています(dd コマンドは count オプションを指定しない場合、デバイスの全体を読み込む)。デフォルトのレコード長は 512 バイトであるため、トータルの読み込みサイズは 2880x512 = 1474560 バイト(1440 KiB)となります。読み込み完了までに、50秒かかっている事を覚えておいてください。
それでは、superformat.img ファイルを解析してみましょう。
$ hexdump -C superformat.img 00000000 eb 3c 90 4d 54 4f 4f 4c 33 39 39 00 02 01 01 00 |?<.MTOOL399.....| 00000010 02 e0 00 40 0b f0 09 00 12 00 02 00 00 00 00 00 |.?.@.?..........| 00000020 00 00 00 00 00 00 29 2a 55 23 7d 4e 4f 20 4e 41 |......)*U#}NO NA| 00000030 4d 45 20 20 20 20 46 41 54 31 32 20 20 20 fa 31 |ME FAT12 ?1| 00000040 c0 8e d8 8e c0 fc b9 00 01 be 00 7c bf 00 80 f3 |?.?.???..?.|?..?| 00000050 a5 ea 56 00 00 08 b8 01 02 bb 00 7c ba 80 00 b9 |??V...?..?.|?..?| 00000060 01 00 cd 13 72 05 ea 00 7c 00 00 cd 19 00 00 00 |..?.r.?.|..?....| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 |................| 000001c0 01 00 01 01 12 4f 00 00 00 00 40 0b 00 00 00 00 |.....O....@.....| 000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U?| 00000200 f0 ff ff ff 0f 00 00 00 00 00 00 00 00 00 00 00 |????............| 00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00001400 f0 ff ff ff 0f 00 00 00 00 00 00 00 00 00 00 00 |????............| 00001410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00002600 41 75 00 6e 00 61 00 6d 00 65 00 0f 00 2a 00 00 |Au.n.a.m.e...*..| 00002610 ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff |??????????..????| 00002620 55 4e 41 4d 45 20 20 20 20 20 20 20 08 00 12 10 |UNAME ....| 00002630 44 36 44 36 00 00 12 10 44 36 02 00 4e 00 00 00 |D6D6....D6..N...| 00002640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00004200 4c 69 6e 75 78 20 45 74 63 68 20 32 2e 36 2e 31 |Linux Etch 2.6.1| 00004210 35 2d 31 2d 36 38 36 2d 73 6d 70 20 23 32 20 53 |5-1-686-smp #2 S| 00004220 4d 50 20 4d 6f 6e 20 4d 61 72 20 36 20 31 35 3a |MP Mon Mar 6 15:| 00004230 33 34 3a 35 30 20 55 54 43 20 32 30 30 36 20 69 |34:50 UTC 2006 i| 00004240 36 38 36 20 47 4e 55 2f 4c 69 6e 75 78 0a 00 00 |686 GNU/Linux...| 00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00168000
先頭 512 バイトは、先ほどの結果と同様です。0x200, 0x1400 番地からは、12ビット版FAT のクラスターデータが記録されています(障害に備えてふたつのコピーが用意されている)。0x2600 番地からはディレクトリ情報が格納されており、ファイル名として "UNAME" が見えます(MS-DOS 上でのファイル名はすべて大文字で扱われる)。0x4200 番地からは、UNAME ファイルの実体である uname コマンドの出力メッセージが確認できます。
0x4200 / 512 = 33 であることから、0x4200 番地からの 512 バイトは、第34セクターの内容に相当することが分かります。1トラックは18セクターですから、ヘッド・トラック・セクターに換算すると、0x4200 番地は「ヘッド1・トラック0・セクター16」に相当するはずです。
なお、セクター通し番号(1-2880)から、ヘッド(0,1)・トラック(0-79)・セクター(1-18)番号への変換は、下記の計算で行うことができます。
ヘッド番号 = ((セクター通し番号ー1)/18)%2 トラック番号 = (セクター通し番号ー1)/36 セクター番号 = セクター通し番号%18
さて、ここで真打ち fdrawcmd に登場してもらいましょう。fdrawcmd は superforamt と同じく Fdutils パッケージに含まれていますが、名前が示す通り「FDC に raw command を送る」ためのコマンドです。
フロッピィディスク操作は、CPU から FDC に I/O コマンドを発行することで実行されますが、普段はこれらの操作は Linux カーネルが行っており、通常はユーザーの目に触れることはありません。しかし、fdrawcmd を使えば、カーネルに代わって私達ユーザーが直接 FDC を制御することが可能になるのです。
本シリーズの最初で解説した通り、初代 IBM-PC の FDC には日本電気のμPD765 が採用されました。その後はμPD765 互換の FDC が各社から開発され(Intel 82078 系が有名)、現在では Super I/O chip に互換品の FDC 機能が内蔵されています。
fdrawcmd の man page は貧弱であり、その全機能は記載されていません。fdrawcmd の能力を最大限に引き出すためには、そのソースリストと Linux カーネルのデバイスドライバーソース(drivers/block/floppy.c, 及び関連ヘッダーファイル)、そして FDC のデータシートを読み込む必要があります。幸い、Intel 82078 のデータシートは現時点でも公開されているため、今のうちに入手しておきましょう(ただし、この内容を理解するためには、"フロッピ・ディスク装置のすべて" などで基礎知識の習得が必要ですが)。
なお、Fdutils の doc ディレクトリに用意されている info マニュアルは、お勧めです。Linux カーネルのフロッピィディスク取り扱いに関する資料としては、この右に出るものはありません。フロッピィ野郎にとっては、必読の書ですね。
カーネルは、ディスク操作中にエラーが発生した場合、適切なエラー処理を行ってくれていますが、fdrawcmd の場合はユーザーが自己責任でエラー処理を行う必要があります。このため、しばらく遊んでいると fdrawcmd が下記のようなメッセージで異常終了することがあります。
raw cmd: Input/output error
この場合は、下記に示すふたつのコマンドを実行してください。最初が FDC の無条件リセット(--resetnow オプションは man page に未記載)、2番目がフロッピィディスク装置自体のリセットを行います(floppycontrol も Fdutils パッケージに所属)。この回避策さえ覚えておけば、大丈夫。フロッピィディスクが擦り切れるまで、ディスク内部の世界を堪能してください。
最初は、フロッピィディスクを初期化することから始めましょう。先ほど用意したディスケットがドライブにあることを確認し、次のコマンドを実行してください。
$ fdrawcmd recalibrate 0 0: 20 1: 0 no disk change
fdrawcmd の最初の引数は、FDC に実行させるコマンド名です。指定可能なコマンドの種類については、man 1 fdrawcmd で参照できます(隠しコマンドもあるため、最終的にはソースリストを読み込む必要がありますが)。
recalibrate は文字通り、キャリブレーションの再実行ですが、具体的には「ヘッドをトラック0まで戻す」作業が行われます。2番目の引数にはドライブ番号(0から開始)を指定しますが、通常ドライブは1台でしょうから、ゼロになります。ヘッドのシーク音が聞こえましたか?
ディスクのヘッドは、同心円状に80個存在するトラック(ドライブによっては81以上も可能)の上を移動しながら目的のセクターを読み込みます。今度は、ヘッドを目的のトラック上に移動させる seek コマンドに挑戦してみましょう。
$ fdrawcmd seek 0 79 0: 20 1: 4f no disk change Etch: ~ $ fdrawcmd seek 0 0 0: 20 1: 0 no disk change
先ほどと同じく2番目の引数はドライブ番号であり、3番目が移動先のトラック番号(0から開始)です。recalibrate コマンドでトラック0に位置していたヘッドが、シーク音と共にトラック79へ移動、再度トラック0へ戻っています。
なお、トラック番号には80を超える値も指定できますが(Over track と呼びます)、最大でも82位にしておいた方が無難です。無理矢理なシークはドライブに障害を与える恐れがあるため、注意してください。また、Over track を指定した場合は、ヘッドを確実にトラック0まで戻すために、recalibrate を2回実行する必要があります。
それにしても、操作中に音がするデバイスというのは、制御している実感があって良いものです。フロッピィディスクに比べると、USB メモリは無表情で面白味に欠けますね。フロッピィディスクが手に入る今の間に、しっかり堪能しておきましょう。
次はいきなり高度なコマンドになりますが、セクター読み込みに挑戦してみましょう。BASIC 時代は DSKI$, DSKO$ 命令で簡単にセクターに対する読み書きを実行できたのですが、Linux 上にこのようなライブラリ関数は存在しないため、やはり fdrawcmd に頼る必要があります。
目的のセクターは「ヘッド1・トラック0・セクター16」であり、先ほどの seek コマンドによりヘッドはトラック0に位置しているはずですから、このままヘッドを下ろせば問題ありません(昔のアナログレコードに針を落とすところをイメージしてください)。
セクター読み込みは read コマンドが担当していますが、まずは次のコマンドを実行してみてください。
$ fdrawcmd read 4 0 1 16 2 1 27 255 length=512 > uname.sec remaining= 0 0: 4 1: 0 2: 0 3: 0 4: 1 5: 11 6: 2 disk change
2番目の引数がゼロではなく4になっていますが、これはヘッド1を選択したためです。実は、2番目の引数は下位2ビット(B1,B0)がドライブ番号、3ビット目(B2)がヘッド番号を意味しています。recalibrate と seek コマンドの場合、ヘッド番号は関係ないのでヘッド0で指定していましたが、read/write のようにセクターアクセスを行うコマンドの場合は、ヘッド番号も考慮する必要があります。
3番目はトラック番号(0)、4番目はふたたびヘッド番号(1)、5番目がセクター番号(16)となります。残りの4つの引数に関する説明は、長くなるため割愛します。気になる方は、82078 のデータシート (28ページ)を参照してください。
なお、「2番目でヘッド番号を指定しておきながら、なぜ4番目で再度指定する必要があるのか?」疑問を持たれた方もいらっしゃることでしょう。とても良い着眼点です。この謎は、次回明らかになる予定です。
引数の最後に指定している length=512 は、FDC から読み込まれたデータの転送バイト数を意味しています。入力データは、UNIX らしく標準出力へそのまま出力されるため、リダイレクションで uname.sec ファイルへ記録しました(リダイレクションを忘れると、バイナリデータで画面が無茶苦茶になるため注意)。
それでは、得られた uname.sec の内容を見てみましょう。
$ hexdump -C uname.sec 00000000 4c 69 6e 75 78 20 45 74 63 68 20 32 2e 36 2e 31 |Linux Etch 2.6.1| 00000010 35 2d 31 2d 36 38 36 2d 73 6d 70 20 23 32 20 53 |5-1-686-smp #2 S| 00000020 4d 50 20 4d 6f 6e 20 4d 61 72 20 36 20 31 35 3a |MP Mon Mar 6 15:| 00000030 33 34 3a 35 30 20 55 54 43 20 32 30 30 36 20 69 |34:50 UTC 2006 i| 00000040 36 38 36 20 47 4e 55 2f 4c 69 6e 75 78 0a 00 00 |686 GNU/Linux...| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000200
見事、目的のセクター内容が現れました。これまでは一枚岩にしか見えなかったディスクイメージも、今ではディスケット上に散らばったセクターをひとつひとつ繋ぎ合わせたものとして理解できるようになりました。mcopy で色々なファイルを転送し、引き続きセクター探検をお楽しみ頂ければと思います。
それでは実験を続けましょう。今度は Windows 上で "フォーマット" したディスケットを準備してください。コマンドプロンプトから format a: を実行しても良いでしょうし、デスクトップ上から右クリックでフォーマットを選択しても構いません(この場合は、クイックフォーマットは選択しないでください)。
フォーマット(すなわち、物理フォーマットと mkfs)が終了したら、ディスケットを Linux ホストマシンのドライブに挿入し、dd コマンドでその内容を全て読み込みます。
$ time dd if=/dev/fd0 > /dev/null 2880+0 records in 2880+0 records out 1474560 bytes (1.5 MB) copied, 47.5733 seconds, 31.0 kB/s real 0m48.395s user 0m0.005s sys 0m0.014s
今回は転送時間のみを知りたいため、読み込んだ内容はリダイレクションで /dev/null に破棄しています。読み込み時間は48秒。superformat よりも2秒短いですが、これは誤差範囲なのでしょうか?
Windows に負けてしまうとは残念ですが、誤差ではありません。実験を繰り返しても、2秒の違いは確実に存在するのです。
このままでは悔しいので、一昔前まで現役を務めていた fdformat に登場してもらいましょう。
$ fdformat /dev/fd0 Double-sided, 80 tracks, 18 sec/track. Total capacity 1440 kB. Formatting ... done Verifying ... 79
superformat とは違い、とてもシンプルなメッセージです。この内容から分かる通り、fdformat では superformat とはことなり、FAT ファイルシステムは生成されず、物理フォーマットのみとなります。公平を期するために、superformat と同じように mformat を実行しておきます。
$ mformat -s18 -t80 -h2 -S2 -M512 a:
それでは出来上がったディスケットを dd コマンドで読み込んでみましょう。
$ time dd if=/dev/fd0 > /dev/null 2880+0 records in 2880+0 records out 1474560 bytes (1.5 MB) copied, 39.7112 seconds, 37.1 kB/s real 0m40.429s user 0m0.004s sys 0m0.009s
何やらアクセス音のリズムが妙に速いことに気づかれたでしょうか?結果は40秒と、これまでの中で最速です。
superformat, FORMAT.COM, fdformat。これら3つのディスク初期化プログラムで作成されたディスケットの容量はすべて同じ 1440 KiB です。アプリケーションはもちろん、カーネルから見ても、3つのディスケットは区別できません。にもかかわらず、どうして10秒にも及ぶ転送時間の差が生じたのでしょうか。この答えは、教科書や Google には書かれていません。
Magic number 1440 シリーズ、お楽しみはこれからなのです。