장 - 11
백업 사본 만들기
백업이 필요한 이유는 무엇인가요?
"예방은 언제나 치료보다 낫습니다." 백업은 데이터 재해 방지의 중요한 부분으로, 디스크 장애나 다른 유형의 데이터 손실을 극복하는 데 도움이 될 수 있습니다. 이번 장에서는 이전에 만든 백업을 사용하여 심각한 디스크 장애가 발생한 후에도 데이터를 복구하는 방법에 대해 논의하겠습니다.
이전에 저장된 백업을 사용하여 복구하는 경우 거의 항상 최대 100%까지 복구가 가능하지만, 일부 특정한 경우에는 디스크 오류 유형에 따라 복구 결과에 차이가 생길 수 있습니다.
백업을 사용하여 데이터를 복원하는 것은 매우 간단하고 빠르며 신뢰할 수 있는 프로세스로, 가장 좋은 결과를 얻을 수 있는 반면, 백업 없이 데이터를 복원하는 것은 복잡하고 혼란스러우며 많은 시간이 걸릴 수 있으며, 그렇게 하더라도 많은 경우 데이터의 100%를 얻지 못할까봐 걱정합니다.
언제, 무엇을 예약해야 하나요?
디스크에는 한 번 또는 다른 간격으로 복사해야 하는 여러 영역이 있습니다. 다음 표에서는 전체 백업에 포함되는 단계를 간략하게 설명하고 언제, 무엇을 백업해야 할지 파악하는 데 도움을 줍니다.
예약해야 할 것 |
백업은 언제 필요한가요? |
MBR 백업 |
FDISK 이후. MBR은 FDISK DOS 명령으로 생성됩니다. FDISK 후에 MBR을 백업할 수 있지만, FDISK로 생성한 파티션을 포맷한 후에도 MBR은 변경되지 않습니다. |
DBR 백업 |
포맷 후 각 논리 디스크에 대한 DBR 백업을 만듭니다. |
FAT 항목과 디렉토리를 백업합니다. |
FAT 및 디렉토리 항목은 파일이나 디렉토리를 만들거나 삭제할 때마다 변경됩니다. 따라서 매일 백업 사본을 만드는 것이 좋습니다. |
사용자 데이터 백업 |
정기적으로 수행해야 합니다. 이 유형의 백업은 디스크 이미지의 생성을 초래합니다. 그러나 이렇게 하는 것은 시간이 많이 걸리지만, 드라이브에 매우 민감한 데이터가 있는 대부분의 회사는 시간을 들여 디스크 이미지를 만드는 것을 선호합니다. 이렇게 하면 위에서 설명한 모든 정보를 백업할 수 있기 때문입니다. |
또한, 시스템의 비상 부팅 디스크도 만들어야 합니다. 하드 드라이브의 데이터에 사고가 발생하면 이 플로피 디스크를 사용하여 시스템을 부팅하고 드라이브의 오류를 분석할 수 있습니다.
MBR(Master Boot Record) 백업 및 사용법
MBR(마스터 부트 레코드) 또는 MPT(마스터 파티션 테이블)라고도 하는 것에는 하드 드라이브에서 활성(또는 부팅 가능한) 파티션을 로드하고 실행하기 위한 작은 프로그램이 들어 있습니다. 마스터 부트 레코드에는 4개의 기본 파티션에 대한 정보가 포함되어 있습니다.
MBR에 대한 자세한 내용은 이 책의 앞 부분에서 설명한 "디스크와 OS에 대한 논리적 접근 방식" 장을 참조하세요.
MBR은 절대 섹터 0에 위치하거나 실린더 0, 헤드 0, 섹터 1에 위치한다고 할 수 있습니다. FDISK.EXE DOS 명령을 실행하여 하드 디스크에 생성됩니다.
MBR 백업을 하는 이유:
MBR을 사용하면 시스템이 시작될 때 활성 파티션의 부트 섹터가 제어권을 얻을 수 있습니다.
POST(Power-On Self Test) 후, BIOS는 하드 드라이브에서 MBR(마스터 부트 레코드)을 메모리로 로드한 다음 실행합니다. 먼저, MBR은 하드 디스크에서 활성 파티션을 검사한 다음, DOS 부트 레코드(DBR)를 메모리에 로드하고 운영 체제 부트 코드에 제어권을 넘깁니다. 그런 다음 운영 체제 부트 레코드 코드가 나머지 운영 체제를 메모리에 로드합니다.
따라서 디스크의 MBR이 손상되면 하드 디스크가 실질적으로 작동하지 않고 시스템은 부팅이 불가능하거나 운영 체제를 실행할 수 없게 됩니다. 이 상태에서는 하드 드라이브에 저장된 모든 데이터에 접근할 수 없습니다. 일반적으로 오류 메시지는 다음과 같이 표시됩니다.
"잘못된 파티션 테이블" "운영 체제 로드 오류" "운영 체제 없음"
MBR 백업을 사용하여 무엇을 복원할 수 있습니까?
MBR을 백업하면 위의 오류 메시지를 제거하는 데 도움이 될 수 있습니다. 백업을 사용하면 다음과 같은 문제를 해결할 수 있습니다.
- 손상된 IPL(초기 프로그램 로더)로 인해 운영 체제를 로드하는 중 오류가 발생했습니다.
- 기본 파티션이 손실되었습니다
- 손상된 파티션 정보
- 잘못된 매직 넘버
MBR 백업을 생성하는 프로그램 작성:
/* MBR 백업을 만드는 프로그램 */
#include <bios.h>
#include <stdio.h>
int 메인(공백)
{
구조체 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 "의 백업);
gets(파일 이름);
// MBR 백업을 저장할 파일 열기 \\
if((fp=fopen(파일명,"wb"))==NULL)
{
printf("파일을 생성할 수 없습니다. 아무 키나 누르세요.
출구...");
getch();
종료(0);
}
printf("하드 디스크 드라이브에서 읽기를 시도 중입니다 :\n");
//// 지정된 디스크 섹터 읽기 \\\\
결과 = _bios_disk(_DISK_READ, &dinfo);
if ((결과 & 0xff00) == 0)
{
printf("하드 디스크 드라이브에서 읽은 디스크 :
성공했습니다.\n");
/// 512바이트의 MBR을 파일에 씁니다.
while(개수<512)
{
fprintf(fp, "%c",dbuf[개수] & 0xff);
카운트++;
}
fp를 닫습니다.
}
또 다른
printf("하드 디스크 드라이브를 읽을 수 없습니다. 상태 = 0x%02x\n", result);
0을 반환합니다.
}
프로그램 코딩에 대한 의견:
이전에 제시한 프로그램 코딩에서는 기본적으로 다음 작업을 단계별로 수행합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보를 포함하는 diskinfo_t 구조체를 가리킵니다.
- 디스크의 첫 번째 섹터를 읽고 싶으므로 섹터의 위치는 다음과 같습니다.
매개변수 |
그것이 의미하는 바 |
dinfo.드라이브 = 0x80 |
이는 첫 번째 하드 디스크 드라이브인 물리적 드라이브 80H를 나타냅니다. |
dinfo.헤드 = 0 |
0 번 헤드를 가리킨다 |
dinfo.트랙 = 0 |
0 번 트랙을 가리킵니다 |
dinfo.섹터 = 1 |
플로피의 첫 번째 섹터는 섹터 1 입니다. |
dinfo.섹터 = 1 |
> 읽기 작업을 위해 고려해야 할 섹터 수 = 1 |
dinfo.버퍼 = dbuf |
작업을 위한 데이터 버퍼 |
- 사용자가 지정한 파일 이름과 경로의 파일 스트림을 열어 정확히 512바이트의 MBR 백업을 저장합니다. 파일 이름과 경로는 문자 배열 filename에 저장됩니다.
- _bios_disk(_DISK_READ, &dinfo)는 dinfo로 지정된 하드 디스크의 첫 번째 섹터(80H)를 읽습니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생할 경우 화면에 오류 메시지를 표시하는 데 사용되는 result에 저장됩니다.
백업에서 MBR을 복원하는 프로그램:
MBR이 어떤 식으로든 손상된 경우, 다음에 제시된 프로그램은 MBR을 복구하는 데 도움이 됩니다.
이 프로그램을 불법적으로 사용하거나 지식이 부족한 상태에서 사용하면 하드 디스크에 있는 데이터 정보가 파괴될 수 있으며 전체 데이터에 액세스할 수 없게 될 수 있다는 점을 항상 명심해야 합니다. 무엇을 할 것인지 확실히 알아야 합니다. 그렇지 않으면 문제가 더 복잡해질 수 있습니다.
백업에서 MBR을 복원하는 프로그램:
프로그램의 코딩은 다음과 같습니다.
/* 백업 파일에서 MBR 백업을 복원하는 프로그램 */
#include <bios.h>
#include <stdio.h>
int 메인(공백)
{
구조체 diskinfo_t dinfo;
int 결과;
int 개수=0;
char filename[80]; /* 주어진 파일 이름을 저장합니다.
사용자 */
static char dbuf[512]; /* 512바이트 데이터 버퍼
*/
파일 *fp;
/* MBR 백업 파일 경로에 대한 사용자 입력 가져오기 */
printf("\n 백업 파일의 파일 이름과 경로를 입력하세요.
MBR \n ");
gets(파일 이름);
if((fp=fopen(파일명,"rb"))==NULL)
{
printf("백업 파일을 열 수 없습니다. 아무 키나 누르세요.
종료하려면...");
getch();
출구(1);
}
/* MBR 데이터는 정확히 512바이트여야 합니다. */
while(개수<512)
{
fscanf(fp, "%c", &dbuf[개수]);
카운트++;
}
fp를 닫습니다.
printf("하드 디스크 드라이브에 쓰기를 시도합니다 :\n");
dinfo.drive = 0x80; /* First의 드라이브 번호
하드디스크 */
dinfo.head = 0; /* 디스크 헤드 번호 */
dinfo.track = 0; /* 트랙 번호 */
dinfo.sector = 1; /* 섹터 번호 */
dinfo.nsectors = 1; /* 섹터 수 */
dinfo.buffer = dbuf; /* 데이터 버퍼 */
결과 = _bios_disk(_DISK_WRITE, &dinfo);
if ((결과 & 0xff00) == 0)
{
printf("MBR 백업을 디스크로 복원
부문: 성공.\n");
}
또 다른
printf("하드 디스크 드라이브에 쓸 수 없습니다. 상태 =
0x%02x\n", 결과);
0을 반환합니다.
}
프로그램 코딩에 대한 의견:
위에 제시된 프로그램 코딩에서 기본적으로 우리는 다음 작업을 단계별로 수행합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보를 포함하는 diskinfo_t 구조체를 가리킵니다.
- 디스크의 첫 번째 섹터에 쓰고 싶으므로 섹터의 위치는 다음과 같습니다.
매개변수 |
그것이 의미하는 바 |
dinfo.드라이브 = 0x80 |
이는 첫 번째 하드 디스크 드라이브인 물리적 드라이브 80H를 나타냅니다. |
dinfo.헤드 = 0 |
0 번 헤드를 가리킨다 |
dinfo.트랙 = 0 |
0 번 트랙을 가리킵니다 |
dinfo.섹터 = 1 |
플로피의 첫 번째 섹터는 섹터 1 입니다. |
dinfo.섹터 = 1 |
읽기 작업을 위해 고려해야 할 섹터 수 = 1 |
dinfo.버퍼 = dbuf |
작업을 위한 데이터 버퍼 |
- 사용자가 제공한 MBR 백업의 파일 이름과 경로는 문자 배열 파일 이름에 저장됩니다. MBR 정보는 정확히 512바이트여야 한다는 점을 명심해야 합니다.
- _bios_disk(_DISK_WRITE, &dinfo)는 dinfo에서 지정한 하드 디스크의 첫 번째 섹터(80H)에 데이터를 씁니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생할 경우 화면에 오류 메시지를 표시하는 데 사용되는 result에 저장됩니다.
DBR(DOS 부트 레코드) 백업 및 활용
파티션 테이블 다음으로 DOS 부트 레코드(DBR) 또는 DOS 부트 섹터라고도 하는 정보는 하드 드라이브에서 두 번째로 중요한 정보입니다.
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에서는 사용할 수 없음)
- 32MB보다 작은 파티션의 섹터 수(따라서 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 |
첫번째 하드디스크 드라이브인 Physical drive 80H를 나타냅니다. |
dinfo.헤드 = 1 |
그것은 1 번 머리를 가리킨다 |
dinfo.트랙 = 0 |
0 번 트랙을 가리킵니다 |
dinfo.섹터 = 1 |
플로피의 첫 번째 섹터는 섹터 1 입니다. |
dinfo.섹터 = 1 |
읽기 작업을 위해 고려해야 할 섹터 수 = 1 |
dinfo.버퍼 = dbuf |
작업을 위한 데이터 버퍼 |
여기서는 읽기/쓰기 섹터의 위치만 변경되는 것을 볼 수 있습니다. 여기서 CHS는 첫 번째 논리 드라이브의 DBR이 여기에 저장되므로 0-1-1로 지정됩니다.
완전한 디스크 이미징
이런 유형의 백업은 요즘 점점 더 인기를 얻고 있으며, 시스템에 매우 민감한 데이터가 있는 조직에서 가장 선호합니다. 사람들은 단 1%의 데이터 손실도 감수할 수 없습니다.
이러한 조직은 전체 디스크 이미지로 정기적으로 백업을 수행합니다. 시간이 좀 걸리지만 아무것도 놓치지 않을 것이라는 확신을 줍니다. 인기가 높아지면서 프로그래머는 디스크 이미징 소프트웨어를 점점 더 빠르게 만들어 이미징 프로세스에 걸리는 시간을 최소화하기 위해 최선을 다했습니다.
디스크 이미징은 좋은 아이디어입니다. 수십 분만 투자하면 주머니에 모든 것을 백업할 수 있다는 안도감을 얻을 수 있기 때문입니다. MBR, BDR, FAT, 루트 디렉터리와 같은 모든 요소가 대상 디스크에 그대로 복사됩니다.
디스크 이미징에 필요한 것은 우리의 귀중한 데이터가 있는 소스 하드 디스크와 동일한(또는 거의 동일한) 대상 하드 디스크입니다. 항상 명심해야 할 한 가지는 대상 디스크가 소스 디스크보다 작아서는 안 된다는 것입니다.
전체 이미지를 가져온 후, 디스크 이미지를 가져온 대상 디스크로 시스템을 부팅하면 일반적으로 모든 데이터를 그대로 얻게 됩니다.
완전한 디스크 이미징을 위한 프로그램 작성
디스크 이미징을 위한 프로그램이 다음에 제공됩니다. 이 프로그램은 INT 13H 확장을 사용하므로 대용량 디스크도 지원할 수 있습니다.
이 프로그램은 첫 번째 물리적 하드 디스크 드라이브(0x80)의 이미지를 두 번째 물리적 하드 디스크 드라이브(0x81)로 만듭니다. 따라서 백업 이미지를 만들기 전에 대상 디스크(0x81)의 모든 데이터가 섹터별 패턴으로 소스 디스크(0x80)의 데이터로 덮어쓰여진다는 점을 명심해야 합니다.
프로그램의 코딩은 다음과 같습니다.
/* 첫 번째 하드 디스크(0x80)의 이미지를 두 번째 하드 디스크(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 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] ; /* 절대 시작
블록 번호 */
} ;
///// 드라이브 매개변수를 가져오는 함수 \\\\\
unsigned long getdrivegeometry(int drive)
{
유니온 REGS i, o;
구조체 SREGS s;
구조체 기하 구조 g = { 26, 0, 0, 0, 0, 0, 0, 0 } ;
ihah = 0x48 ; /* INT 13H의 함수 번호 0x48
확장자 주석 보기
아래에 */
ihdl = 드라이브; /* 드라이브 번호 */
ixsi = FP_OFF ( (void far*)&g ) ;
s.ds = FP_SEG ( (void far*)&g ) ;
/* 세그먼트 레지스터 값을 사용하여 INT 13H 확장의 지정된 함수 번호를 호출합니다. */
int86x(0x13, &i, &o, &s);
printf("\n Head = %lu, 트랙당 섹터 = %lu, 실린더 =
%lu\n", g.머리, g.spt, g.cyl);
/* 드라이브 지오메트리 함수가 실패하면 오류 메시지를 표시하고 종료합니다. */
if(g.spt==0)
{
printf("\n 드라이브 지오메트리 가져오기 함수가 실패했습니다....");
printf("\n 확장이 지원되지 않습니다. 아무 키나 누르세요.
출구...");
getch();
출구(1);
}
return *g.sectors; /* 섹터 개수를 반환합니다.
드라이브에 */
}
////// 메인 시작 \\\\\\
void 메인()
{
부호 없는 긴 루프=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 최소한 두 개의 하드 디스크가 있어야 합니다.
이것을 실행하려면 컴퓨터에 연결하세요");
printf("\n 프로그램. 종료하려면 아무 키나 누르세요...");
getch();
출구(1);
}
/// 첫 번째 하드 디스크(0x80)의 매개변수 가져오기 \\\
Sectors_in_HDD1 = getdrivegeometry(0x80);
printf("첫 번째 하드 디스크의 총 섹터 = %lu\n\n",
HDD의 섹터1);
/// 두 번째 Hsrd 디스크의 매개변수 가져오기(0x81) \\\
Sectors_in_HDD2 = getdrivegeometry(0x81);
printf("두 번째 하드 디스크의 총 섹터 = %lu\n\n",
HDD2의 섹터)
/// 먼저 확인 후 진행하세요 \\\
printf("\n 두 번째 하드 디스크의 모든 데이터는
잃어버린 !!!");
printf("\n 계속하려면 \'Y\'를 누르세요. 그렇지 않으면 아무 키나 누르세요.
출구... ");
선택 = getche();
스위치(선택)
{
케이스 'y':
케이스 'Y':
부서지다;
기본:
종료(0);
}
/* 목적지는 소스보다 작을 수 없습니다. */
if(HDD2의 섹터<HDD1의 섹터)
{
printf("\n\n 대상 디스크는 더 작을 수 없습니다.
소스 디스크보다");
printf("\n 종료하려면 아무 키나 누르세요...");
getch();
종료(0);
}
/* 모든 것이 정상이면 소스 디스크의 모든 섹터를 대상 하드 디스크로 복사합니다. */
gotoxy(10,15); printf("절대 섹터 복사 중: ");
for(loop=0;loop< =Sectors_in_HDD1;loop=loop+120)
{
readabsolutesectors(0x80, 루프, 120, 버퍼);
writeabsolutesectors(0x81, 루프, 120, 버퍼);
gotoxy(36,15); printf("%ld",loop);
if(kbhit())
{
종료(0);
}
}
//// 완료 메시지 표시 \\\
printf("\n\n 디스크 이미징이 완료되었습니다. 아무 키나 누르세요.
종료하려면...");
getch();
}
//// 메인 끝
코딩에 대한 의견:
이전에 주어진 프로그램의 코딩에서 디스크 이미징을 위해 다음 작업을 수행합니다.
- 구조, geometry는 INT 13H 확장, 함수 번호 0x48을 사용하는 getdrivegeometry 함수에 의해 사용됩니다. INT 13H 확장에 대한 자세한 설명은 이 책의 앞부분에서 논의한 "대형 하드 디스크 처리" 장을 참조하십시오.
디스크의 여러 매개변수를 나타내는 데이터 유형은 다음과 같은 의미를 갖습니다.
데이터 유형 |
바이트 단위 크기 |
설명 |
부호 없는 int 크기 |
2바이트 |
버퍼 크기 |
부호 없는 int 플래그 |
2바이트 |
정보 플래그 |
부호 없는 긴 실린더 |
4바이트 |
드라이브의 물리적 실린더 수 |
서명 없는 긴 머리 |
4바이트 |
드라이브의 물리적 헤드 수 |
서명되지 않은 긴 spt |
4바이트 |
트랙당 물리적 섹터 수 |
부호 없는 긴 섹터[2] |
8바이트 |
드라이브의 총 섹터 수 |
부호 없는 int bps |
2바이트 |
섹터당 바이트 |
- 구조 diskaddrpacket은 readabsolutesectors 및 writeabsolutesectors 함수에서 사용됩니다. 디스크 주소 패킷의 형식은 다음 표에 나와 있습니다.
데이터 유형 |
바이트 단위 크기 |
설명 |
char 패킷 크기 |
1바이트 |
패킷 크기, 일반적으로 10H |
char 예약됨 |
1바이트 |
예약됨 (0) |
int 블록 카운트 |
2바이트 |
전송할 블록 수 |
char far *버퍼주소 |
4바이트 |
전송 버퍼에 대한 주소 |
부호 없는 긴 블록 번호[2] |
4바이트 |
시작 절대 블록 번호 |
- getdrivegeometry 함수는 지정된 Drive의 매개변수를 가져오는 데 사용됩니다. getdrivegeometry 함수는 INT 13H Extensions의 함수 번호 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);는 두 번째 하드 디스크(0x81)의 매개변수를 가져오고 두 번째 하드 디스크의 총 섹터 수를 반환합니다.
사용자가 이미징을 계속 진행하도록 확인한 후, 먼저 소스 하드 디스크의 크기가 대상 하드 디스크의 크기보다 크지 않아야 한다는 조건을 확인합니다. 대상이 더 작으면 오류 메시지를 표시하고 종료합니다.
모든 것이 제대로 진행 중이라면 소스 디스크의 섹터를 대상 디스크로 복사합니다. 여기서는 이미징 프로세스를 더 빠르게 하기 위해 한 번에 61440바이트(각각 512바이트인 120개 섹터)를 읽고 씁니다.
한 번에 64K의 한계를 넘어 더 많은 섹터를 사용하고 싶다면 대용량 메모리 모델에서 "거대한 포인터"를 사용하면 됩니다. 사양의 예는 다음과 같습니다.
char 거대한 배열[100000L];
- 함수, readabsolutesectors(0x80, loop, 120, buffer);는 부호 없는 긴 정수 loop로 지정된 섹터 번호부터 시작하여 첫 번째 하드 디스크(0x80)의 120개 섹터를 읽고 데이터 버퍼에 데이터를 저장합니다.
- 함수 writeabsolutesectors(0x81, loop, 120, buffer);는 부호 없는 긴 정수 루프로 지정된 섹터 번호부터 시작하여 두 번째 하드 디스크(0x81)의 120개 섹터에 데이터 버퍼의 데이터를 씁니다.
readabsolutesectors() 및 writeabsolutesectors() 함수의 코딩은 다음과 같습니다.
//// 절대 섹터를 읽는 함수 \\\\
int readabsolutesectors ( int 드라이브,
부호 없는 긴 섹터 번호,
int 섹터 수,
void *버퍼)
{
유니온 REGS i, o;
구조체 SREGS s;
구조체 diskaddrpacket pp;
pp.packetsize = 16 ; /* 패킷 크기 = 10H */
pp.reserved = 0 ; /* 예약됨 = 0 */
pp.blockcount = numofsectors ; /* 섹터 수
읽다 */
/* 데이터 버퍼용 */
pp.버퍼주소 = (char far*) MK_FP ( FP_SEG((void
far*)버퍼), FP_OFF((void far*)버퍼));
pp.blocknumber[0] = sectornumber ; /* 섹터 번호
읽다 */
pp.blocknumber[1] = 0 ; /* 블록 번호 */
ihah = 0x42 ; /* 함수 번호*/
ihdl = 드라이브; /* 물리적 드라이브 번호 */
ixsi = FP_OFF ( (void far*)&pp ) ; /* ds:si에 대한
버퍼 매개변수 */
s.ds = FP_SEG ( (void far*)&pp ) ; /* ds:say에 대한
버퍼 매개변수 */
/* 세그먼트 레지스터 값을 사용하여 INT 13H의 지정된 함수를 호출합니다. */
int86x(0x13, &i, &o, &s);
if ( oxcflag==1)
0을 반환합니다. /*실패 */
또 다른
return 1 ; /* 성공 */
}
//// 절대 섹터를 쓰는 함수 \\\\
int writeabsolutesectors ( int 드라이브,
부호 없는 긴 섹터 번호,
int 섹터 수,
void *버퍼)
{
노동조합 REGS i, o ;
구조 SREGS s;
구조체 diskaddrpacket pp;
pp.패킷크기 = 16; /* 패킷 크기 = 10H */
pp.예약됨 = 0; /* 예약됨 = 0 */
pp.블록카운트 = 섹터 수; /* 섹터 수
쓰여질 것이다 */
/* 데이터 버퍼용 */
pp.버퍼주소 = (char far*) MK_FP ( FP_SEG((void
far*)버퍼), FP_OFF((void far*)버퍼));
pp.blocknumber[0] = sectornumber ;/* 섹터 번호
쓰여질 것이다 */
pp.블록번호[1] = 0; /* 블록 번호 = 0 */
이하 = 0x43 ; /* 함수 번호 */
이할 = 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);
if ( oxcflag == 1)
0을 반환합니다. /* 실패 */
더
1을 반환합니다. /* 성공 */
}
코딩 주석:
두 함수에서 사용되는 매개변수는 다음과 같은 의미를 갖습니다.
매개변수 |
바이트 단위 크기 |
설명 |
pp.패킷크기 = 16; |
1바이트 |
패키지 크기 = 10H |
pp.예약됨 = 0; |
1바이트 |
예약됨 = 0 |
pp.블록카운트 = 섹터 수; |
2바이트 |
읽을 섹터 수 |
pp.버퍼 주소 = (char far*) MK_FP ( FP_SEG((void far*)버퍼), FP_OFF((void far*)버퍼)); |
----- |
데이터 버퍼 또는 전송 버퍼용 |
pp.블록번호[0] = 섹터번호; |
4바이트 |
읽고 쓸 섹터 번호(보통 이것만 필요합니다). 개별적으로만 가능합니다. 최대 2.1테라바이트까지 지원 가능합니다. |
pp.블록_번호[1] = 0; |
4바이트 |
블록 번호. 2.1테라바이트보다 큰 디스크에 액세스하는 경우 이 기능을 사용하세요. |
이하 = 0x42; 또는 ihah = 0x43; |
2바이트 |
기능 확장자 수 INT 13H |
할 = 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 함수를 호출합니다. |