第11章
バックアップコピーの作成
なぜバックアップが必要なのでしょうか?
「予防は常に治療よりも優れています。」バックアップはデータ災害防止の重要な部分でもあり、ディスク障害やその他の種類のデータ損失を克服するのに役立ちます。この章では、以前に作成したバックアップを使用するだけで、重大なディスク障害が発生した後でもデータを回復する方法について説明します。
以前に保存したバックアップを使用したリカバリは、ほぼ常に 100 パーセントまで可能ですが、特定のケースでは、ディスク障害の種類によってリカバリ結果が異なる場合があります。
バックアップを使用してデータを復元するのは、非常にシンプルで高速かつ信頼性の高いプロセスであり、最良の結果が得られます。一方、バックアップなしでデータを復元するのは複雑でわかりにくく、時間がかかる可能性があり、それでも多くの場合、データが 100 パーセント取得されないのではないかと心配になります。
いつ何を予約するか
ディスク上には、一度または異なる間隔でコピーする必要があるさまざまな領域がいくつかあります。次の表は、完全バックアップに含まれる手順の概要を示しており、いつ何をバックアップするかを判断するのに役立ちます。
予約が必要なもの |
バックアップはいつ必要ですか? |
MBRバックアップ |
FDISKの後。 MBR は FDISK DOS コマンドによって作成されます。 FDISK 後に MBR をバックアップできますが、FDISK によって作成されたパーティションをフォーマットした後でも、MBR は変更されません。 |
DBRバックアップ |
フォーマット後、各論理ディスクの DBR バックアップを作成します。 |
FAT エントリとディレクトリをバックアップします。 |
FAT およびディレクトリ エントリは、ファイルまたはディレクトリを作成または削除するたびに変更されます。したがって、毎日バックアップコピーを作成することをお勧めします。 |
ユーザーデータのバックアップ |
定期的に行う必要があります。このタイプのバックアップでは、ディスク イメージが作成されます。ただし、これは時間がかかりますが、ドライブに非常に機密性の高いデータがあるほとんどの企業は、上記のすべての情報をバックアップできるため、時間をかけてディスク イメージを作成することを好みます。 |
さらに、システム用の緊急ブート ディスクを作成する必要があります。ハード ドライブ上のデータに何らかの事故が発生した場合、このフロッピー ディスクを使用してシステムを起動し、ドライブのエラーを分析することができます。
MBR(マスターブートレコード)のバックアップとその使用方法
マスター ブート レコード (MBR)、またはマスター パーティション テーブル (MPT) と呼ばれることもあるこのレコードには、ハード ドライブからアクティブな (またはブート可能な) パーティションを読み込んで実行するための小さなプログラムが含まれています。マスター ブート レコードには、4 つのプライマリ パーティションすべてに関する情報が含まれています。
MBR の詳細については、この本の前半で説明した「ディスクと OS への論理的アプローチ」の章を参照してください。
MBR は絶対セクター 0、つまりシリンダー 0、ヘッド 0、セクター 1 にあります。これは、FDISK.EXE DOS コマンドを実行することによってハード ディスク上に作成されます。
MBR のバックアップを作成する理由:
MBR により、システムの起動時にアクティブ パーティションのブート セクターが制御を取得できるようになります。
電源投入時セルフテスト (POST) の後、BIOS はハード ドライブから MBR (マスター ブート レコード) をメモリにロードして実行します。まず、MBR はハード ディスクにアクティブなパーティションがあるかどうかを確認し、次に DOS ブート レコード (DBR) をメモリにロードしてオペレーティング システムのブート コードに制御を渡し、次にオペレーティング システムのブート レコード コードがオペレーティング システムの残りの部分をメモリにロードします。
したがって、ディスクの MBR が破損している場合、ハードディスクは事実上機能しなくなり、システムはオペレーティング システムを起動または実行することが完全に不可能になると言えます。この状態では、ハードドライブに保存されているすべてのデータにアクセスできなくなります。通常、エラー メッセージは次のように表示されます。
「無効なパーティション テーブル」 「オペレーティング システムの読み込みエラー」 「オペレーティング システムが見つかりません」
MBR バックアップを使用して何を復元できますか?
MBR をバックアップすると、上記のエラー メッセージを解消できます。バックアップを使用すると、次の問題を修正できます。
- IPL (初期プログラム ローダー) が破損しているため、オペレーティング システムのロード エラーが発生しました
- プライマリパーティションが失われました
- パーティション情報が破損しています
- 間違った魔法の数字
MBR バックアップを作成するプログラムの作成:
/* MBR バックアップを作成するプログラム */
#include <bios.h>
#include <stdio.h>
int メイン(void)
{
構造体 diskinfo_t dinfo; /* ストレージ用の構造体
ディスクパラメータ情報 */
結果 int;
整数の数=0;
char ファイル名[80]; /* 指定されたファイル名を保存します
ユーザー */
static char dbuf[512]; /* 512バイトのデータバッファ */
ファイル *fp;
dinfo.drive = 0x80; /* 最初のハードディスクのドライブ番号
ディスク */
dinfo.head = 0; /* ディスクヘッド番号 */
dinfo.track = 0; /* トラック番号 */
dinfo.sector = 1; /* セクター番号 */
dinfo.nsectors = 1; /* セクター数 */
dinfo.buffer = dbuf; /* データ バッファ */
printf("\n 保存するファイル名とパスを入力してください
MBR のバックアップ \n ");
ファイル名を取得します。
// MBR バックアップを保存するファイルを開く \\
if((fp=fopen(ファイル名,"wb"))==NULL)
{
printf("ファイルを作成できませんでした。任意のキーを押してください。
出口...");
getch();
終了(0);
}
printf("ハードディスクドライブから読み取りを試行しています:\n");
//// 指定されたディスクセクターを読み取ります \\\\
結果 = _bios_disk(_DISK_READ, &dinfo);
((結果 & 0xff00) == 0)の場合
{
printf("ハードディスクドライブからディスクを読み取りました:
成功しました。\n");
/// 512 バイトの MBR をファイルに書き込みます \\\\
while(カウント<512)
{
fprintf(fp,"%c",dbuf[count] & 0xff);
カウント++;
}
fp を閉じる
}
それ以外
printf("ハードディスクドライブを読み取れません。ステータス = 0x%02x\n", result);
0を返します。
}
プログラムコーディングに関するコメント:
前述のプログラムコーディングでは、基本的に次のタスクを段階的に実行していきます。
- dinfo は、_bios_disk 関数によって実行される操作に必要なパラメータの情報を含む diskinfo_t 構造体を指します。
- ディスクの最初のセクターを読み取りたいので、セクターの場所は次のようになります。
パラメータ |
それが意味するもの |
dinfo.ドライブ = 0x80 |
これは、最初のハードディスクドライブである物理ドライブ80Hを示します。 |
dinfo.head = 0 |
ヘッド番号0を指します |
dinfo.track = 0 |
トラック0を指します |
dinfo.セクター = 1 |
フロッピーの最初のセクター、つまりセクター1 |
dinfo.セクター = 1 |
>読み取り操作で考慮するセクター数 = 1 |
dinfo.バッファ = dbuf |
操作用のデータバッファ |
- ユーザーが指定したファイル名とパスのファイル ストリームを開き、正確に 512 バイトの MBR のバックアップを保存します。ファイル名とパスは、文字配列 filename に保存されます。
- _bios_disk(_DISK_READ, &dinfo) は、dinfo で指定されたハードディスクの最初のセクター (80H) を読み取ります。
- 返されたステータスは結果に保存され、操作が成功した場合にメッセージを表示したり、エラーが発生した場合に画面にエラー メッセージを表示したりするために使用されます。
バックアップから MBR を復元するプログラム:
MBR が何らかの理由で破損した場合、次に示すプログラムは MBR を復元するのに役立ちます。
このプログラムを違法に使用したり、知識不足で使用したりすると、ハードディスク内のデータ情報が破壊され、データ全体がアクセス不能になる可能性があることを常に念頭に置いてください。何をするかをよく理解しておく必要があります。そうしないと、問題がさらに複雑になる可能性があります。
バックアップから MBR を復元するプログラム:
プログラムのコーディングは次のとおりです。
/* バックアップファイルから MBR のバックアップを復元するプログラム */
#include <bios.h>
#include <stdio.h>
int メイン(void)
{
構造体 diskinfo_t dinfo;
int 結果;
整数カウント=0;
char filename[80]; /* 指定されたファイル名を格納する
ユーザーによる */
static char dbuf[512]; /* 512バイトのデータバッファ
*/
ファイル *fp;
/* MBR バックアップ ファイル パスのユーザー入力を取得します */
printf("\n バックアップファイルのファイル名とパスを入力してください
MBR \n ");
ファイル名を取得します。
if((fp=fopen(ファイル名,"rb"))==NULL)
{
printf("バックアップファイルを開けませんでした。任意のキーを押してください
終了するには...");
getch();
終了(1);
}
/* MBR データは正確に 512 バイトである必要があります */
while(カウント<512)
{
fscanf(fp,"%c",&dbuf[count]);
カウント++;
}
fp を閉じる
printf("ハードディスクドライブへの書き込みを試行しています:\n");
dinfo.drive = 0x80; /* 最初のドライブ番号
ハードディスク */
dinfo.head = 0; /* ディスクヘッド番号 */
dinfo.track = 0; /* トラック番号 */
dinfo.sector = 1; /* セクター番号 */
dinfo.nsectors = 1; /* セクター数 */
dinfo.buffer = dbuf; /* データ バッファ */
結果 = _bios_disk(_DISK_WRITE, &dinfo);
((結果 & 0xff00) == 0)の場合
{
printf("MBRのバックアップをディスクに復元する
セクター: 成功。\n");
}
それ以外
printf("ハードディスクドライブに書き込めません、ステータス =
0x%02x\n", 結果);
0を返します。
}
プログラムコーディングに関するコメント:
上記のプログラムコーディングでは、基本的に次のタスクを段階的に実行していきます。
- dinfo は、_bios_disk 関数によって実行される操作に必要なパラメータの情報を含む diskinfo_t 構造体を指します。
- ディスクの最初のセクターに書き込みたいので、セクターの場所は次のようになります。
パラメータ |
それが意味するもの |
dinfo.ドライブ = 0x80 |
これは、最初のハードディスクドライブである物理ドライブ80Hを示します。 |
dinfo.head = 0 |
ヘッド番号0を指します |
dinfo.track = 0 |
トラック0を指します |
dinfo.セクター = 1 |
フロッピーの最初のセクター、つまりセクター1 |
dinfo.セクター = 1 |
読み取り操作で考慮するセクター数 = 1 |
dinfo.バッファ = dbuf |
操作用のデータバッファ |
- ユーザーが指定した MBR のバックアップのファイル名とパスは、文字配列 filename に格納されます。MBR 情報は正確に 512 バイトである必要があることに注意してください。
- _bios_disk(_DISK_WRITE, &dinfo) は、dinfo で指定されたハードディスクの最初のセクター (80H) にデータを書き込みます。
- 返されたステータスは結果に保存され、操作が成功した場合にメッセージを表示したり、エラーが発生した場合に画面にエラー メッセージを表示したりするために使用されます。
DBR(DOSブートレコード)のバックアップとその使用
パーティション テーブルの次に、DOS ブート レコード (DBR) または DOS ブート セクターと呼ばれることもある情報は、ハード ドライブ上で 2 番目に重要な情報です。
DBR の詳細については、この本の前半で説明した「ディスクと OS への論理的アプローチ」の章を参照してください。
各 DOS パーティションの最初の論理セクターには、DOS ブート レコード (DBR) または DOS ブート セクターが含まれます。DBR の役割は、オペレーティング システムをハード ディスク ドライブからコンピューターのメイン メモリにロードし、ロードされたプログラムにシステムの制御を与えることです。
ハード ディスクの最初のパーティションの DOS ブート レコード (DBR) は、通常、絶対セクター 63 (ディスク ドライブの 64 番目のセクター) にあります。または、CHS 形式では、ほとんどのドライブで C–H–S = 0–1–1 になります。
ただし、この場所はドライブの SPT (トラックあたりのセクター数) によって異なる場合があります。たとえば、31 SPT しかない古い 245MB ドライブでは、ブート レコードは 32 番目のセクター (絶対セクター 31) に配置されていました。
DBR は、FDISK コマンドを使用してパーティション分割を行った後、DOS の FORMAT コマンドによって作成されます。DBR が存在するセクターは、DOS の特定のパーティションの論理セクター 1 になります。DOS で使用されるセクター番号は、DBR が存在する物理セクターから始まります。
DBR には、マスター ブート レコード (MBR) 実行可能プログラムによって実行される小さなプログラムが含まれています。すべての DOS パーティションには、マシンを起動する (つまり、オペレーティング システムをロードする) プログラム コードが含まれていますが、パーティション テーブル エントリでアクティブ パーティションとして指定されているマスター ブート レコードによって制御されるのは、そのパーティションだけです。
DBR をバックアップする理由:
DBR には、ディスク ジオメトリに関する重要な情報が含まれています。この情報は、各パーティションの最初のセクターに次のように保存されています。
- ジャンプコード + NOP
- OEM 名とバージョン
- セクターあたりのバイト数
- クラスターあたりのセクター数
- 予約セクター
- FATのコピー数
- ルート ディレクトリ エントリの最大数 (ただし FAT32 では利用できません)
- パーティション内のセクター数が 32 MB 未満 (したがって FAT32 では使用できません)
- メディア記述子 (ハードディスクの場合は F8H)
- FAT あたりのセクター数 (古い FAT システムで、FAT32 では利用できません)
- トラックあたりのセクター数
- ヘッドの数
- パーティション内の隠しセクターの数
- パーティション内のセクター数
- FAT あたりのセクター数
- FAT 情報記述子フラグ
- FAT32ドライブのバージョン
- ルートディレクトリの開始クラスタ番号
- ファイルシステム情報セクターのセクター番号
- バックアップブートセクターのセクター番号
- 予約済み
- パーティションの論理ドライブ番号
- 拡張署名 (29H)
- パーティションのシリアル番号
- パーティションのボリューム名
- FAT名
- 実行可能コード
- 実行可能マーカーまたはマジックナンバー (AAH 55H)
通常、画面には次のエラー メッセージが表示されます。
「ディスクの起動に失敗しました」
「非システムディスクまたはディスクエラー」
「無効なシステムディスクまたはディスクI/Oエラー」
「ディスクを交換して、任意のキーを押してください…」
DBR のバックアップで何を回復できますか?
DBR のバックアップは、上記のエラー メッセージを取り除くのに役立つ場合があります。画面上のこれらのエラー メッセージは、ユーザーが上記のプログラムが入った起動可能なディスクをフロッピー ドライブに挿入し、キーを押すまで待機します。
起動可能なフロッピーまたは CD からシステムを起動すると、ドライブにアクセスできるはずです。ハード ディスクは起動可能ではありませんが、通常、ディスク ドライブのデータへのアクセスには影響しません。起動可能なディスクを使用してシステムを起動すると、データにアクセスできます。
DBR のバックアップを復元することで、上記で説明したような問題を克服できます。
DBR のバックアップを作成および復元するためのプログラム:
DBR のバックアップを作成して復元するためのプログラムは、MBR のバックアップおよび復元のプログラムとほぼ同じです。
たとえば、ディスクの最初の論理ドライブの DBR のバックアップを作成し、それを復元するためのプログラムを作成する場合、dinfo 構造体で指定されるパラメータは次のように変更されます。
パラメータ |
それが意味するもの |
dinfo.ドライブ = 0x80 |
これは最初のハードディスクドライブである物理ドライブ80Hを示します> |
dinfo.head = 1 |
頭番号1を指します |
dinfo.track = 0 |
トラック0を指します |
dinfo.セクター = 1 |
フロッピーの最初のセクター、つまりセクター1 |
dinfo.セクター = 1 |
読み取り操作で考慮するセクター数 = 1 |
dinfo.バッファ = dbuf |
操作用のデータバッファ |
ここでは、読み取り/書き込みするセクターの場所のみが変更されていることがわかります。ここでは、最初の論理ドライブの DBR がここに保存されるため、CHS は 0-1-1 として指定されます。
完全なディスクイメージング
このタイプのバックアップは、最近ますます人気が高まっており、システム内に非常に機密性の高いデータを持つ組織に最も好まれています。これらの組織では、たとえ 1 パーセントでもデータ損失が発生する可能性を許容できません。
このような組織は、定期的にディスク全体のイメージとしてバックアップを作成します。多少の時間はかかりますが、何も見逃さないという保証が得られます。ディスク イメージング ソフトウェアの人気が高まっているため、プログラマーはイメージング プロセスにかかる時間を最小限に抑えるために、ディスク イメージング ソフトウェアをより高速化するために最善を尽くしてきました。
ディスク イメージングは良いアイデアです。数十分を費やすだけで、ポケットの中にすべてのバックアップがあるという安心感が得られます。MBR、BDR、FAT、ルート ディレクトリなどのすべての要素が、そのまま宛先ディスクにコピーされます。
ディスク イメージングに必要なのは、貴重なデータが入っているソース ハード ディスクと同一 (またはほぼ同一) のターゲット ハード ディスクです。ターゲット ディスクはソース ディスクより小さくしてはならないことを常に念頭に置いてください。
完全なイメージを取得した後、ディスク イメージを取得した宛先ディスクを使用してシステムを起動すると、通常、すべてのデータがそのまま取得されます。
完全なディスクイメージングのためのプログラムの作成
次にディスク イメージングのプログラムを示します。このプログラムは INT 13H 拡張を使用するため、大容量ディスクもサポートできます。
プログラムは、最初の物理ハード ディスク ドライブ (0x80) のイメージを 2 番目の物理ハード ディスク ドライブ (0x81) に作成します。そのため、バックアップ イメージを作成する前に、宛先ディスク (0x81) のすべてのデータが、ソース ディスク (0x80) のデータによってセクター単位で上書きされることに留意する必要があります。
プログラムのコーディングは次のとおりです。
/* 最初のハードディスク (0x80) のイメージを 2 番目のハードディスク (0x81) に作成するプログラム */
#include<stdio.h>
#include<dos.h>
#include<conio.h>
/* INT 13H 拡張機能、関数番号 0x48 を使用して getdrivegeometry 関数によって使用される構造体。 */
構造体ジオメトリ
{
unsigned int size ; /* (呼び出し) バッファのサイズ */
unsigned int flags ; /* 情報フラグ */
unsigned long cyl; /* 物理数
ドライブ上のシリンダー */
unsigned long heads ;/* 物理数
ヘッズオンドライブ*/
unsigned long spt ; /* 物理数
トラックあたりのセクター数 */
unsigned long sectors[2] ; /* 総数
ドライブ上のセクター */
unsigned int bps ; /* セクターあたりのバイト数 */
} ;
/* ディスク アドレス パケット形式の構造。関数 readabsolutesectors および writeabsolutesectors によって使用されます */
構造体ディスクアドレスパケット
{
char packetsize ; /* パケットのサイズ、通常は 10H */
char reserved ; /* 予約済み (0) */
int blockcount; /* 転送するブロック数 */
char far *bufferaddress; /* 転送先のアドレス
バッファ */
unsigned long blocknumber[2] ; /* 開始絶対値
ブロック番号 */
} ;
///// ドライブパラメータを取得する関数 \\\\\
符号なし long getdrivegeometry (int ドライブ)
{
ユニオン REGS i、o ;
構造体SREGs;
構造体ジオメトリ g = { 26, 0, 0, 0, 0, 0, 0, 0, 0 } ;
ihah = 0x48 ; /* INT 13H の関数番号 0x48
拡張機能 コメントを見る
下に */
ihdl = drive; /* ドライブ番号 */
ixsi = FP_OFF ( (void far*)&g ) ;
s.ds = FP_SEG ( (void far*)&g ) ;
/* セグメントレジスタ値を使用して、INT 13H拡張の指定された関数番号を呼び出します */
int86x ( 0x13, &i, &o, &s ) ;
printf("\n ヘッド = %lu、トラックあたりのセクター数 = %lu、シリンダ数 =
%lu\n", g.heads, g.spt, g.cyl);
/* ドライブジオメトリ取得関数が失敗した場合は、エラーメッセージを表示して終了します */
g.spt==0の場合
{
printf("\n ドライブジオメトリ取得関数が失敗しました....");
printf("\n 拡張機能はサポートされていません。任意のキーを押してください
出口...");
getch();
終了(1);
}
return *g.sectors; /* セクタ数を返す
ドライブ中 */
}
////// メインの開始 \\\\\\
void main()
{
符号なしロングループ=0、Sectors_in_HDD1=0、Sectors_in_HDD2=0;
unsigned char buffer[61440]; /* 61440のデータバッファ
時間を節約するために、一度に 512 バイトの 120 セクターを読み取り/書き込みます。 */
文字の選択;
clrscr();
/* 接続されているハードディスクの合計数が 2 未満の場合、エラー メッセージを表示して終了します。 */
if(((char)peekb(0x0040, 0x0075))<2)
{
printf("\n\n 少なくとも2台のハードディスクが必要です
これを実行するにはコンピュータに接続してください");
printf("\n プログラム。終了するには任意のキーを押してください... ");
getch();
終了(1);
}
/// 最初のハードディスクのパラメータを取得します (0x80) \\\
Sectors_in_HDD1 = getdrivegeometry (0x80);
printf(" 最初のハードディスクの合計セクター数 = %lu\n\n",
HDD内のセクター1);
/// 2 番目の Hsrd ディスクのパラメータを取得します (0x81) \\\
Sectors_in_HDD2 = getdrivegeometry (0x81);
printf(" 2 番目のハードディスクの合計セクター数 = %lu\n\n",
HDD2のセクター数);
/// 最初に確認してから続行します \\\
printf("\n 2台目のハードディスクにあるすべてのデータは
失った !!!");
printf("\n 続行するには\'Y\'を押してください。それ以外の場合は任意のキーを押してください
出口... ");
選択 = getche();
スイッチ(選択)
{
ケース 'y':
ケース 'Y':
壊す;
デフォルト:
終了(0);
}
/* 宛先はソースより小さくしてはいけません */
if(HDD2のセクター数<HDD1のセクター数)
{
printf("\n\n 宛先ディスクはこれより小さくてはいけません
ソースディスクよりも");
printf("\n 終了するには任意のキーを押してください...");
getch();
終了(0);
}
/* 問題がなければ、ソース ディスクのすべてのセクターを宛先ハード ディスクにコピーします */
gotoxy(10,15);printf("絶対セクターをコピーしています: ");
for(ループ=0;ループ< =HDD1のセクター;ループ=ループ+120)
{
絶対セクターを読み取ります ( 0x80, ループ, 120, バッファ );
絶対セクターを書き込みます ( 0x81, ループ, 120, バッファ );
gotoxy(36,15); printf("%ld",ループ);
if(kbhit())
{
終了(0);
}
}
//// 完了メッセージを表示する \\\
printf("\n\n ディスクイメージの作成が完了しました。任意のキーを押してください
終了するには...");
getch();
}
//// メイン終了
コーディングに関するコメント:
前述のプログラムのコーディングでは、ディスク イメージングのために次のタスクを実行します。
- 構造体、geometry は、INT 13H 拡張、関数番号 0x48 を使用して getdrivegeometry 関数によって使用されます。INT 13H 拡張の詳細な説明については、この本の前半で説明した「大容量ハード ディスクの処理」の章を参照してください。
ディスクのいくつかのパラメータを表すデータ タイプには、次の意味があります。
データタイプ |
サイズ(バイト) |
説明 |
符号なし整数サイズ |
2 バイト |
バッファのサイズ |
符号なし整数フラグ |
2 バイト |
情報フラグ |
符号なしロングシリンダー |
4 バイト |
ドライブ上の物理シリンダ数 |
符号なしロングヘッド |
4 バイト |
ドライブ上の物理ヘッドの数 |
符号なしロングspt |
4 バイト |
トラックあたりの物理セクター数 |
符号なしロングセクター[2] |
8 バイト |
ドライブ上のセクターの総数 |
符号なし整数bps |
2 バイト |
セクターあたりのバイト数 |
- 構造体 diskaddrpacket は、関数 readabsolutesectors および writeabsolutesectors によって使用されます。ディスク アドレス パケットの形式は次の表に示されています。
データタイプ |
サイズ(バイト) |
説明 |
文字パケットサイズ |
1 バイト |
パケットのサイズ、通常は10H |
文字予約済み |
1 バイト |
予約済み (0) |
intブロック数 |
2 バイト |
転送するブロック数 |
char far *バッファアドレス |
4 バイト |
転送バッファへのアドレス |
符号なしロングブロック番号[2] |
4 バイト |
開始絶対ブロック番号 |
- getdrivegeometry 関数は、指定されたドライブのパラメータを取得するために使用されます。関数 getdrivegeometry は、INT 13H 拡張の関数番号 0x48 を使用します。
パラメータの意味は次の表に示されています。
パラメータ |
それが意味するもの |
イハ = 0x48 |
INT 13H 拡張の機能番号 0x48 |
ihdl =ドライブ |
ドライブ番号 |
ixsi = FP_OFF ( (void far*)&g ) |
ds:siアドレスは、前述のドライブパラメータのバッファに格納されます。 |
s.ds = FP_SEG ( (void far*)&g ) |
ds:siアドレスは、前述のドライブパラメータのバッファに格納されます。 |
int86x(0x13, &i, &o, &s) 関数は、セグメント レジスタ値を使用して割り込み 13H を呼び出します。getdrivegeometry 関数は、ドライブ上の合計数を返します。
- main() 関数では、(char)peekb(0x0040, 0x0075); (関数 peekb は DOS.H で定義されています) は、システムに接続されているハードディスクの数を返します。
システムに接続されているハードディスクの数は、メモリ位置 0040H:0075H (セグメント 0040H: オフセット 0075H) に格納されているバイトで表されます。システムに接続されているハードディスクの数が 2 未満の場合、プログラムはエラー メッセージを表示して終了します。
Sectors_in_HDD1 = getdrivegeometry (0x80); 最初のハードディスクのパラメータ (0x80) を取得し、最初のハードディスク上のセクターの合計数を返します。
同様に、Sectors_in_HDD2 = getdrivegeometry (0x81); は、2 番目のハード ディスク (0x81) のパラメーターを取得し、2 番目のハード ディスク上のセクターの合計数を返します。
ユーザーがイメージ作成を続行することを確認した後、まず、ソース ハード ディスクのサイズが宛先ハード ディスクのサイズより大きくならないことを確認します。宛先が小さい場合は、エラー メッセージを表示して終了します。
すべてがうまくいけば、ソース ディスクのセクターを宛先ディスクにコピーします。ここでは、イメージング プロセスを高速化するために、一度に 61440 バイト (各 512 バイトの 120 セクター) を読み書きしています。
一度に 64K の制限を超えてさらに多くのセクターを使用したい場合は、大規模メモリ モデルの「巨大ポインタ」を使用することでそれが可能になります。仕様の例は次のとおりです。
char巨大配列[100000L];
- 関数 readabsolutesectors ( 0x80, loop, 120, buffer ); は、unsigned long integer loop で指定されたセクター番号から開始して、最初のハードディスク (0x80) の 120 セクターを読み取り、データをデータ バッファーに格納します。
- 関数 writeabsolutesectors ( 0x81, loop, 120, buffer ); は、unsigned long integer loop で指定されたセクター番号から開始して、データ バッファーのデータを 2 番目のハード ディスク (0x81) の 120 セクターに書き込みます。
関数readabsolutesectors() と writeabsolutesectors()のコーディングは次のとおりです。
//// 絶対セクターを読み取る関数 \\\\
int readabsolutesectors ( int ドライブ、
符号なし長整数セクター番号、
int セクター数、
void *バッファ)
{
ユニオン REGS i、o ;
構造体SREGs;
構造体ディスクアドレスパケットpp;
pp.packetsize = 16 ; /* パケットサイズ = 10H */
pp.reserved = 0 ; /* 予約済み = 0 */
pp.blockcount = numofsectors ; /* セクター数
読む */
/* データバッファ用 */
pp.bufferaddress = (char far*) MK_FP ( FP_SEG((void
far*)バッファの場合、FP_OFF((void far*)バッファ));
pp.blocknumber[0] = sectornumber ; /* セクター番号
読む */
pp.blocknumber[1] = 0 ; /* ブロック番号 */
ihah = 0x42 ; /* 関数番号*/
ihdl = drive ; /* 物理ドライブ番号 */
ixsi = FP_OFF ( (void far*)&pp ) ; /* ds:si の場合
バッファパラメータ */
s.ds = FP_SEG ( (void far*)&pp ) ; /* ds:say の場合
バッファパラメータ */
/* セグメントレジスタ値を使用して INT 13H の指定された関数を呼び出す */
int86x ( 0x13, &i, &o, &s ) ;
(oxcflag==1の場合)
0 を返す ; /*失敗 */
それ以外
1を返す; /* 成功 */
}
//// 絶対セクターを書き込む関数 \\\\
int writeabsolutesectors ( int ドライブ、
符号なし長整数セクター番号、
int セクター数、
void *バッファ)
{
労働組合REGS i、o;
構造 SREGS;
構造体ディスクアドレスパケットpp;
パケットサイズ = 16; /* パケットサイズ = 10H */
pp.reserved = 0 ; /* 予約済み = 0 */
pp.blockcount = セクター数; /* セクター数
書かれる */
/* データバッファ用 */
pp.bufferaddress = (char far*) MK_FP ( FP_SEG((void
far*)バッファの場合、FP_OFF((void far*)バッファ));
pp.blocknumber[0] = sectornumber ;/* セクター番号
書かれる */
pp.ブロック番号[1] = 0 ; /* ブロック番号 = 0 */
ihah = 0x43 ; /* 関数番号 */
ihal = 0x00 ; /* フラグエントリ、参照
コメント */
ihdl = ドライブ; /* 物理ディスク番号*/
/* バッファパラメータのds:si */
ixsi = FP_OFF ( (void far*)&pp ) ;
/* バッファパラメータのds:si */
s.ds = FP_SEG ( (void far*)&pp ) ;
/* セグメントレジスタ値を使用して指定されたINT 13H関数を呼び出す */
int86x ( 0x13, &i, &o, &s ) ;
(oxcflag == 1の場合)
0 を返します。 /* 失敗 */
もっと
1 を返します。 /* 成功 */
}
コーディングコメント:
両方の関数で使用されるパラメータの意味は次のとおりです。
パラメータ |
サイズ(バイト単位) |
説明 |
パケットサイズ = 16; |
1バイト |
パッケージサイズ = 10H |
pp.reserved = 0 ; |
1バイト |
予約済み = 0 |
pp.blockcount =セクター数; |
2バイト |
読み取るセクター数 |
pp.bufferaddress = (char far*) MK_FP ( FP_SEG((void far*)buffer), FP_OFF((void far*)buffer)); |
----- |
データバッファまたは送信バッファ用 |
pp.blocknumber[0] =セクター番号; |
4バイト |
読み取り/書き込みするセクター番号 (通常はこの番号のみが必要です)。別途のみ。最大2.1テラバイトまでサポートできます。 |
pp.ブロック番号[1] = 0 ; |
4バイト |
ブロック番号。 2.1 テラバイトを超えるディスクにアクセスする場合に使用します。 |
ihah = 0x42;または ihah = 0x43 ; |
2バイト |
機能 拡張数 INT 13H |
ihal = 0x00 ; |
1バイト |
書き込みフラグは書き込み機能でのみ使用され、00H、01H は検証なしの書き込みに使用され、02H は検証ありの書き込みに使用されます。 |
ihdl =ドライブ; |
2バイト |
物理ディスク番号 |
ixsi = FP_OFF ( (void far*)&pp ) ; |
------ |
バッファパラメータのds:si |
s.ds = FP_SEG ( (void far*)&pp ) ; |
------ |
バッファパラメータのds:si |
int86x ( 0x13, &i, &o, &s ) ; |
------ |
セグメントレジスタ値を使用して指定されたINT 13H関数を呼び出す |