cccc언어로언어로 설명한설명한 임베디드임베디드 파일파일...

252
C 언어로 언어로 언어로 언어로 설명한 설명한 설명한 설명한 베디드 베디드 베디드 베디드 파 시스템 시스템 시스템 시스템 www.winde.co.kr www.winde.co.kr www.winde.co.kr www.winde.co.kr ver ver ver ver 1.0 1.0 1.0 1.0 Copyright by opyright by opyright by opyright by winde winde winde winde2000 2000 2000 2000@winde winde winde winde.co co co co.kr kr kr kr

Upload: others

Post on 24-Jan-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

CCCC 언어로언어로언어로언어로 설명한설명한설명한설명한 임베디드임베디드임베디드임베디드 파일파일파일파일

시스템시스템시스템시스템

www.winde.co.krwww.winde.co.krwww.winde.co.krwww.winde.co.kr

ver ver ver ver 1.01.01.01.0

CCCCopyright byopyright byopyright byopyright by

winde winde winde winde2000200020002000@@@@windewindewindewinde....cocococo....krkrkrkr

목차목차목차목차

머리말머리말머리말머리말

1111 부부부부 FAT FAT FAT FAT 에에에에 대한대한대한대한 이론이론이론이론

1111 장장장장 File System File System File System File System 이란이란이란이란????

2222 장장장장 Media( Media( Media( Media(하드디스크하드디스크하드디스크하드디스크, , , , 메모리카드메모리카드메모리카드메모리카드))))에에에에 대해대해대해대해 이해하기이해하기이해하기이해하기

01010101. . . . Cyinder Cyinder Cyinder Cyinder ((((실린더실린더실린더실린더), Head(), Head(), Head(), Head(헤드헤드헤드헤드), Track, Sector (), Track, Sector (), Track, Sector (), Track, Sector (트랙트랙트랙트랙, , , , 섹터섹터섹터섹터) ) ) )

02020202. . . . 논리논리논리논리 섹터와섹터와섹터와섹터와 물리섹터물리섹터물리섹터물리섹터

03030303. . . . FFFFlash Memorylash Memorylash Memorylash Memory

04040404. . . . Cluster Cluster Cluster Cluster ((((클러스터클러스터클러스터클러스터) ) ) )

05050505. . . . 파일파일파일파일

06060606. . . . 파일시스템파일시스템파일시스템파일시스템

07070707. . . . 포맷포맷포맷포맷

3333 장장장장 OS OS OS OS 와와와와 FAT FAT FAT FAT 의의의의 관계관계관계관계

01010101. . . . OSOSOSOS 의의의의 구조구조구조구조

02020202. . . . BootingBootingBootingBooting 이란이란이란이란????

03030303. . . . NAND BootNAND BootNAND BootNAND Boot

04040404. . . . NAND Flash InterfaceNAND Flash InterfaceNAND Flash InterfaceNAND Flash Interface

2222 부부부부 FAT FAT FAT FAT 파일파일파일파일 시스템을시스템을시스템을시스템을 분석하기분석하기분석하기분석하기 위한위한위한위한 기본기본기본기본 툴들툴들툴들툴들

1111 장장장장. Disk Editor (. Disk Editor (. Disk Editor (. Disk Editor (시만텍시만텍시만텍시만텍 사사사사))))

2222 장장장장. . . . 첨부된첨부된첨부된첨부된 Utility Utility Utility Utility 프로그램들프로그램들프로그램들프로그램들

01010101. . . . Diskview Diskview Diskview Diskview ( ( ( ( DosDosDosDos 용용용용 ) ) ) )

02020202. . . . InFat InFat InFat InFat ( ( ( ( DosDosDosDos 용용용용 ) ) ) )

03030303. . . . hexcopyhexcopyhexcopyhexcopy

04040404. . . . windewindewindewinde ( windows ( windows ( windows ( windows 용용용용 ---- win win win win9999x x x x , , , , winxp winxp winxp winxp ))))

3333 부부부부 파일파일파일파일 시스템시스템시스템시스템 분석하기분석하기분석하기분석하기

1111 장장장장 FAT FAT FAT FAT 이해하기이해하기이해하기이해하기

01010101. . . . FATFATFATFAT 의의의의 역사역사역사역사

02020202. . . . FATFATFATFAT12121212

03030303. . . . FATFATFATFAT16161616

04040404. . . . FATFATFATFAT16161616 의의의의 한계한계한계한계

05050505. . . . FATFATFATFAT16161616 에서에서에서에서 FAT FAT FAT FAT32323232 로로로로

06060606. . . . FATFATFATFAT32323232

07070707. . . . 빈공간빈공간빈공간빈공간 재계산재계산재계산재계산 억제억제억제억제

08080808. . . . 파일파일파일파일 저장의저장의저장의저장의 고속화고속화고속화고속화

09090909. . . . 신뢰성과신뢰성과신뢰성과신뢰성과 효율성효율성효율성효율성 향상향상향상향상

2222 장장장장 FAT FAT FAT FAT 분석하기분석하기분석하기분석하기

00000000. . . . 용어용어용어용어정리정리정리정리....

01010101. . . . FATFATFATFAT 구조구조구조구조

02020202. . . . MBRMBRMBRMBR 구조구조구조구조

03030303. . . . Patition TablePatition TablePatition TablePatition Table

04040404. . . . RDE RDE RDE RDE 및및및및 실제실제실제실제 DATA DATA DATA DATA 를를를를 찾기찾기찾기찾기 위한위한위한위한 과정과정과정과정

05050505. . . . FATFATFATFAT 의의의의 사용사용사용사용 메모리메모리메모리메모리 크기크기크기크기 계산계산계산계산

06060606. . . . 유효유효유효유효 cluster cluster cluster cluster 계산과계산과계산과계산과 사용된사용된사용된사용된 용량용량용량용량 계산계산계산계산

4444 부부부부 실전실전실전실전 프로그래밍프로그래밍프로그래밍프로그래밍

1111 장장장장 물리물리물리물리 하드하드하드하드 디스크디스크디스크디스크 읽고읽고읽고읽고 쓰기쓰기쓰기쓰기

01010101. . . . INTINTINTINT13131313h h h h 이해하기이해하기이해하기이해하기

02020202. . . . HDD Access HDD Access HDD Access HDD Access 함수함수함수함수 만들기만들기만들기만들기

2222 장장장장 정보정보정보정보 가져오는가져오는가져오는가져오는 프로그램프로그램프로그램프로그램 만들기만들기만들기만들기

01010101....간단한간단한간단한간단한 disk viewer disk viewer disk viewer disk viewer 만들기만들기만들기만들기....

02020202. . . . MMMMBR BR BR BR 프로그래밍해프로그래밍해프로그래밍해프로그래밍해 보기보기보기보기....

03030303. . . . BR BR BR BR 프로그래밍해프로그래밍해프로그래밍해프로그래밍해 보기보기보기보기....

3333 장장장장 간단한간단한간단한간단한 응용프로그램응용프로그램응용프로그램응용프로그램 만들기만들기만들기만들기

01010101. . . . format format format format 프로그램프로그램프로그램프로그램 만들기만들기만들기만들기

02020202. . . . 간단한간단한간단한간단한 파티션파티션파티션파티션 분할기분할기분할기분할기 만들기만들기만들기만들기

03030303. . . . 디렉터리디렉터리디렉터리디렉터리 List List List List 가져오기가져오기가져오기가져오기

4444 장장장장 상용상용상용상용 프로그램들프로그램들프로그램들프로그램들 분석해분석해분석해분석해 보기보기보기보기

맺음말맺음말맺음말맺음말

참고참고참고참고 문헌문헌문헌문헌, , , , 용어용어용어용어 설명설명설명설명....

CCCC 언어로언어로언어로언어로 설명한설명한설명한설명한 임베디드임베디드임베디드임베디드 파일시스템파일시스템파일시스템파일시스템, FAT , FAT , FAT , FAT

머리말머리말머리말머리말

FAT 와 대한 자세한 내용은 이 파일 시스템을 만든 Microsoft 사가

가장 잘 알 것입니다.

그리고, Samsung 과 같은 하드디스크 관련 회사나, SD 나 MMC 카드

같은 저장매체를 만드는 회사에서 관련 기술에 대한 더 정확한

기술서가 존재할 것입니다.

그러한 것들을 보기를 필자도 원합니다. 그러나, 전문지식이 없는

일반사람들이 그러한 관련 기술 정보를 구하기란 힘듭니다.

따라서, 찾아 다니는 수고를 덜어 주는 것이 이 문서의 목적이라고

하겠습니다.

더불어, 필자가 실무에서 경험하고 만들어 본 기본코드들을

이야기한다면, 파일시스템에 관심이 있었던 분, OS 를 공부하시는 분,

그리고, 파일시스템을 알게 되었는데 어떻게 활용하실지 궁금하신

분들에게 조금이나마 도움이 될 것입니다.

이 문서는 크게 이론과 예제로 이루어져 있습니다.

이론에 웬만큼 아는 사람은 예제로 바로 넘어가도 상관이 없습니다.

하지만, 이 문서를 보시는 대부분의 사람들은 이론 부분에서 정보를

얻으려고 할 것입니다.

이 문서를 보시는 분들은 대부분 PDA 나, mp3 플레이어, embeded

시스템에 종사하시는 분들일 것입니다.

또는, OS 를 공부하시는 학생이나 드라이버 제작하시는 분들이 보실

지도 모릅니다.

이 문서는 그러한 분들에게 도움이 되도록 만들었습니다.

그렇다고 해서, 어렵게 쓰여 졌다고 생각하지는 않습니다.

일반인들도 이해할 수 있도록 전문 용어 보다는

되도록 쉬운 용어를 사용하고, 말보다는 그림과 예제를 보여드리기

위해 노력했습니다.

용어에 대한 자세한 설명과 만들어진 배경 전부를 설명하진

않았습니다.

그러한 것들을 다 설명한다면, 이 문서는 필자가 원했던 FAT 의

파일시스템을 프로그램 실습하기 위한 것을 할 수 없습니다.

따라서, 그러한 배경지식 및 자세한 역사는 필자가 참고한

홈페이지이나 문헌, 서적을 찾아보시면 도움이 될 것입니다.

이 문서를 읽어 주시는 모든 분께 감사를 드리며, 관련 종사자들에게

도움이 되었으면 좋겠습니다.

일러두기일러두기일러두기일러두기

독자독자독자독자 선정선정선정선정

이 문서는 C 언어의 기본만 알고 있으면 프로그램을 할 수 있도록

만들었습니다.

변수, 루프, 조건문 등의 기본상식과 파일시스템이 어떤 의미인지

알아야 합니다.

또한, 일부분의 코드는 어셈블로 만들어져 있습니다.

그렇다고 어셈블을 공부하고서 이 문서를 보기에는 어셈블 코드는

적게 나와 있습니다.

따라서, 어셈블로 된 부분은 설명만 읽어 보시고 나중에 어셈블을

공부하게 되면 다시 확인해 보셔도 될 것입니다.

파일시스템을 설명하기 위해서 프로그래밍 언어 중 가장 기초로

배우는 Turbo-C 를 이용해서 프로그래밍화 하였습니다.

그리고, FAT 파일시스템만을 중점적으로 다루기 때문에 win98 및

dos 환경에서 컴파일 되었다는 것을 생각해 주시기 바랍니다.

이이이이 문서문서문서문서를를를를 읽는읽는읽는읽는 순서순서순서순서

이 문서는 크게 이론 과 실습 2 부분으로 나누어져 있습니다.

주된 내용은 이론이고 실습은 이론을 이해하기 위해서 만들어진

부분이라고 생각하시면 됩니다.

실습에서 일부분은 이론의 부분을 되풀이 하지만, 기본적으로 앞에서

차근 차근 읽어 가시는 것이 도움이 되실 것입니다.

또는 이론 부분에서 관심있는 부분을 먼저 읽으신 다음에 실습 부분을

실험해 보셔도 됩니다.

준비해야준비해야준비해야준비해야 할할할할 것들것들것들것들

제 생각에는 test 컴퓨터가 있어야 된다고 생각합니다.

물론, test 컴퓨터는 windows 98 또는 Dos 가 설치가 되어 있고요.

main 컴퓨터에는 Turbo-C 또는 Boland C 또는 visual C 가 설치

되어 있으며 됩니다.

컴파일은 main 컴퓨터에서 그리고 테스트는 test 컴퓨터에서 하는

것이 나중에 자신이 만든 code 들을 잃어버리지 않는 최선의 길입니다.

이 문서는 그 만큼 OS 및 파일시스템의 중요한 부분을 건드리는

경우가 많으므로 주의를 요합니다.

예를 들어, MBR 을 ‘ 0 ’ 으로 밀어 버리면, 일반 상식으로는 그

하드를 다시 format 을 하는 경우가 대부분이기 때문입니다.

하지만, 이 문서를 정말 잘 이해하시게 된다면, 몇 몇 Disk Editor 의

tool 로 간단히 원상태로 복구하거나 자료를 살리는 방법을 알게 될

것입니다.

이 문서에서 필요한 것이 있는 데, 실험에 쓰일 tool 들과 테스트

code 들입니다.

tool 들은 제가 만든 프로그램과 freeware 로 나오는 프로그램들을

위주로 집어 넣었고, Disk Editor 와 같은 상용화된 프로그램은

첨부하지 못했습니다.

테스트 code 들은 테스트된 code 들이라 특별히 하드웨어가 틀리지

않는 한 정상적으로 동작할 것입니다.

만약, 동작 중에 이상이 있을 수도 있으므로, 앞서서 말씀 드렸듯이 꼭

test 컴퓨터를 하나 구하셔서 테스트해 보시기 바라며,

동작상 이상이 있으신 분들은 http://www.winde.co.kr 의 방명록에

버그 및 바라는 사항을 적어 주시면 적극 방영토록 노력하겠습니다.

1111 장장장장 파일파일파일파일 시스템이란시스템이란시스템이란시스템이란? ? ? ?

파일 시스템의 목적을 간단히 말하면 파일을 효율적으로 관리하기

위함이다.

파일 또는 data 를 우리가 얼마나 효율적으로 쓸 수 있게 구성이 되어

편리하게 쓸 수 있는가에 파일시스템의 존재 목적이 있다.

효율적으로 존재하기 위해, 많은 파일시스템들은 진화해 왔으며

앞으로 더욱 진화할 것이다.

데이터의 암호화와 압축 및 권한 부여 등도 이렇게 파일시스템을

효율적으로 다루기 위한 도구인 것이다.

그림 1) DATA 관리 예 (도서관)

한 번 상상을 해 보자, 우리가 잘 가는 도서관을 이야기로 하자면,

문서를 찾기 위해선, 먼저 문서가 있는 정보를 검색해야 한다.

그림 1 과 같이 도서정보가 있는 곳에 가서 자신이 읽고 싶은 문서의

위치 정보를 찾는 작업을 할 것이다.

그런 다음에 ' B 열 203 ' 이란 정보를 얻었으면, 문서가 꽂혀진 장소로

가서 문서를 선택하게 되는 것이다.

우리는 도서정보 검색, 도서정보 관리, 도서정보 저장소 등등을

이용하게 되는 것이다.

만일, 우리가 그러한 것을 사용하지 않는다고 생각해 보자.

마찬가지로 도서관에 갔다고 치면, 도서검색을 할 수 없으므로, 우리는

도서를 처음부터 끝까지 검색을 하게 될 것이다.

다행히, 문서의 수가 10 개 또는 100 개 정도로 우리가 셀 수 있다면

다행이지만, 대부분의 도서관에서는 몇 천 또는 몇 만 이상의 문서를

보유하고 있을 것이다.

당연히 그렇게 일일이 검색을 하는 작업은 시간낭비일 뿐 아니라,

다른 사람들도 같은 작업을 한다면, 혼란만 가중되어서 그

도서관에서는 제대로 된 문서를 찾기 어려울 것이다.

사람들은 그래서, 그러한 정보를 도서를 관리하는 관리자를 두어

정보를 적게끔 했다.

도서를 관리하는 사람이 문서를 찾아 오는 사람에게 어디에 뭐가

있다고 가르쳐 줌으로서 이용자는 빠르게 문서를 볼 수 있게 되는

것이다.

그리고, 현재에 이르러서는 워낙 많은 양의 데이터를 찾아 주는 일을

컴퓨터가 대신하게 되었다.

그림 2) DATA 관리 예 (FAT)

그림 2 를 보면, 그림 1 과 별 다르지 않다는 것을 알게 될 것이다.

FAT 이란 놈이 실제 데이터를 찾아 주는 어떤 지도 또는 정보를

가지고 있음을 알 수 있다.

FAT 은 ‘ File Allocation Table ’ 의 약자를 의미하며, 해석하면,

File 이 위치해 있는 Table 지도 같은 것이고, 곧 Data 와 1:1

매칭이 된다는 얘기가 된다.

따라서 OS 는 FAT 을 보고서 데이터가 어디에 있구나 하고 그

데이터를 찾아서 읽고 쓰기를 한다.

물론, 이러한 동작이 가능하기 위해서는 몇 가지 규칙을 따라야 하는

귀찮음이 생기지만, 크게 보면 이러한 것을 한다고 머릿속에 기억해

두면 좋을 것이다.

그러면, 어떠한 규칙들이 존재하는 것일까?

그림 3) FAT 의 구조

그림 3 의 구조를 보면 이해할 수 있을 것이다.

‘ 헉, FAT 말고도 MBR, BR, RDE 이렇게 모르는 단어가

나오잖아요.’ 라고 말씀하시는 독자분 들이 계시겠지만, 처음 보면

당황하게 되는 이 용어도 이 문서를 다 읽게 될 때는 단어 하나만

들으면 금방 이해가 될 것이다.

우리가 언어를 처음 배우면 생소한 것이 많지만, 많이 다루다 보면

자연스럽게 알게 되므로 그렇게 걱정하지 않아도 된다.

이 문서의 대부분의 내용은 ‘ Norton Disk Editor ’ 의 내용을

기초로 분석하므로, 2 부에서 파일시스템을 분석하기 위한 tool 들을

설명할 때에 유의해서 봐주었으면 한다.

MS 에서 나오는 명칭과 왜 틀리나요? 하고 생각하시는 분이

계신데, 용어만 약간씩 차이가 있을 뿐이지 하는 동작이나 행동은

같기 때문에 걱정하지 않아도 된다.

MBR ( Master Boot Record )는 Partition Entry 와 처음 부팅하는데

필요한 Boot code 가 들어 있다.

이것에 대한 내용을 알기 위해서는 시스템이 Boot 하는 과정에

대해서 알아야 한다.

모든 시스템은 ROM 이란 것이 존재하게 된다.

ROM 은 ‘ Read Only Memory ’ 란 뜻인데, 글자 그대로 단지 읽을

수만 있는 Memory 란 뜻이다.

이곳에는 Program 이 동작하기 위한 code 들이 들어가 있는데,

시스템이 전원이 켜지면, 이 ROM 이란 곳에서부터 Program

counter 가 동작해서 순서대로 시스템이 동작하게 되는 것이다.

ROM 은 단지 읽기만 가능한 것이므로, ROM 에 있는 내용을 읽어서

RAM( Radom Access Memory) 이란 곳에 옮겨진 후, 읽고 쓰기를

하게 되는데, Booting 이란 과정으로 가기위한 Code 들도 바로

MBR 이란 곳에 있어서, MBR 의 내용도 RAM 에 load 된 후에

동작하게 된다.

잠깐잠깐잠깐잠깐 요요요요!!!!

컴퓨터가 Boot 하기 위해서는 아래와 같이 동작하게 된다.

처음 컴퓨터를 켜면, 메인보드에 있는 Bios(Basic Input Output System)이 동작 하게 된다.

Bios 는 현재 메인보드에 있는 CPU, RAM , PCI, ISA, AGP , IDE 장치 , USB 장치 , 기타

등등의 메인보드에 연결되어 있는 장치들에게 규약 된 신호를 보내서 제대로 된 정보가

들어오는가를 점검해서 문제가 있으면, 스피커로 beep 음을 보낸다.

모든 장치를 검색하고, 하드디스크를 찾게 되면, Int 19h 를 걸어서 MBR, 즉 하드디스크의

물리섹터 0 번으로 컨트롤이 넘어가게 된다.

MBR 을 분석해 보면 63 번섹터에 있는 BR(Boot Record)로 점프를 하게되고, BR 에서는

io.sys, msdos.sys 등의 시스템 파일을 메모리에 load 시켜서 우리가 잘 아는 windows 로

부팅하게 되는 것이다.

IBM 호환 PC 는 대부분 MBR 부터 프로그램이 동작하게 되는 것이다.

Linux 도 MBR 부터 시작하는데, 따로 Boot loader 를 두어서 MBR 에서 Boot loader 가

있는 섹터로 점프하도록 도와주는 것이다.

그림 4) booting 과정

MBR 이 동작하게 되면, BR 로 control 이 넘어가게 되는데, BR 에는

FAT 이 동작하기 위한 ‘ cluster 당 섹터수 ’ , ‘ FAT 크기 ’ , ‘ FAT

수 ’ 등등의 많은 정보들이 존재하게 된다.

앞서도 말했지만, FAT 은 실제 DATA 의 mapping 이기 때문에,

BR(Boot Record)는 그 FAT 과 실제 DATA 의 연관을 지어주는

역할을 해 준다.

RDE(Root Directory Entry)는 우리가 잘 아는 ‘ c:\ ' 을 생각하면

된다.

즉, Root 드라이브를 나타내는 것이다.

뿌리가 갈라져서 무수한 디렉토리가 만들어지는 것처럼, 처음의

디렉토리가 있어야 한다.

Root Directory 가 바로 그 시작하는 위치가 되는 것이다.

다시 정리를 해서 말하면, MBR 은 하드디스크 전체에 대한 정보

기록 장소, BR 는 patition 정보 기록 장소, RDE 는 파일과

Directory 에 대한 기록 장소 로 생각하면 된다.

지금은 이해가 안 가도 자꾸 언급하는 것을 자주 들으면 언젠가는

이해할 것이니 너무 걱정하지 말기 바란다.

FAT12, FAT16, FAT32 는 어떻게 나누는 것일까?

라는 궁금증을 가진 분들이 계실 것이다.

필자도 FAT 을 접하지 않았을 때 항상 궁금했던 내용이었다.

그림 5) FAT12, FAT16, FAT32 의 차이

그림 5 에 답이 나와 있다.

FAT12 는 예를 들어 ‘ 0101 0011 1010 ’ 과 같이 12bit 의 FAT 로

이루어진 파일시스템이고, FAT16 은 16bit , FAT32 는 32bit 로

이루어진 파일 시스템이라는 얘기다.

그림 3 에서 FAT 이란 영역에 그림 6 과 같은 값들이 들어 가 있는

것이다.

단, FAT12, 16, 32 에 따라서 값이 틀리게 들어가 있다.

그림 6) FAT12 의 실제 값

그림 6 은 Norton Disk Editor 로 본 FAT12 의 디스크 내용이다.

Intel 계열의 데이터 저장은 그림과 같이 Hex 값으로 저장된다.

Hex 로 나오니까, 머리 아파하시는 분들이 계실지

모르겠지만, 나중에는 이해 하기 위해서 이 값을 확인하려고 할

것이다.

물론, 이 문서를 읽고 있는 분들은 이런 Editor 를 즐겨 쓴다고 필자는

생각하고 싶다.

이 HEX 값을 분석하는 것은 뒤로 미루기로 하자.

아무리 좋은 음식도 한꺼번에 너무 많이 먹으면 배탈 나기 때문이다.

이번 절 에서는 이정도의 내용만 알고 넘어가도 되겠다.

왜냐면 우리가 바라는 목표는 이러한 내용을 바탕으로 C 언어로

프로그램을 하는 것이 때문에, 나머지의 세세한 내용은 실제로

프로그램을 하면서 더 설명할 것이다.

또한 그러다 보면 앞서 말한 내용도 언급할 때가 있을 것이고, 되풀이

되는 것도 있을 것이다.

만일 그러한 내용이 나온다면, 필자가 좀 더 자세하고 강조하고

싶어서 그런가 보다 하고 넘어가 주시면 될 것 같다.

2222 장장장장 Media ( Media ( Media ( Media (하드디스크하드디스크하드디스크하드디스크, Flash memory), Flash memory), Flash memory), Flash memory)에에에에 대해대해대해대해 이해하기이해하기이해하기이해하기

하드디스크는 컴퓨터가 발명된 후부터 지금까지 없어서는 안 되는

아주 중요한 매체이다.

현재 Flash 메모리가 나와서 그 자리를 매우고 있지만, Flash

메모리의 용량과 가격이 하드디스크보다 더 나아지지 않는 한

하드디스크는 없어지지 않을 것이다.

이번 장은 바로 하드디스크와 Flash 메모리의 물리적인 구조와

차이점에 대해서 이야기 하려고 한다.

그림 7) 실린더, 헤드, 섹터

01010101. . . . Cylinder Cylinder Cylinder Cylinder ((((실린더실린더실린더실린더), Head(), Head(), Head(), Head(헤드헤드헤드헤드) , Track, Sector () , Track, Sector () , Track, Sector () , Track, Sector (트랙트랙트랙트랙, , , , 섹터섹터섹터섹터))))

우리가 자주 얘기하는 ‘ 하드 디스크 ’ 는 크게 3 가지로 나누어 진다.

Cylinder, Head , Sector 로 나누어 지고, 예전에 하드 용량이

2G 전일때만 해도 이 값은 cmos setup 에서나 patition 을 나눌때는

꼭 필요한 정보였었다.

하지만, 지금은 8G 정도의 하드디스크는 벌써 석기시대의 유물처럼

여기는 사람들이 있을 정도로 업신 여기는 풍조지만,

온고지신(溫故知新, 옛것을 익혀 새것을 배운다) 이라는 옛 성현의

말씀처럼 과거의 지식도 배워 놓으면 도움 될 때가 꼭 있다.

헤드는 코팅된 자성체를 자화/소거하여 정보를

저장/삭제(write/delete)하거나 저장된 정보를 읽는(read) 장치이다.

그림 8) 디스크와 헤드

일반적으로 헤드의 수는 디스크(플래터)수의 두 배이다.

한 장의 디스크는 앞 뒤 면에 하나씩의 헤드가 있다.

FDD 의 헤드는 디스켓 표면에 직접 접촉하여 읽기나 쓰기를

하지만, HDD 의 헤드는 디스크의 표면과 미세한 간극을 유지한 채

떠있는 상태(‘ 부동고도 ’ 또는 ‘ 비행고도 ’라고함 )로 읽기와 쓰기를

한다.

HDD 의 헤드가 디스크와 접촉하여 회전하면 마찰력이 발생하여

속도가 느려질 뿐 아니라 마찰열과 헤드 및 디스크의 물리적 마모

때문에 수명이 크게 단축된다.

HDD 를 3 년 이상 계속 사용하여도 쉽게 고장이 나지 않는 이유가

여기에 있다. 그러나 헤드와 디스크의 간격이 워낙 좁아서 ( 머리카락

굵기의 1/100 ) HDD 동작 중에 물리적인 충격을 주면 헤드가

디스크와 순간적으로 직접 마찰하여 디스크 표면에 상처(scratch)를

만들 수 있으며 상처가 난 부분은 대부분 bad 섹터가 되어서 사용할

수 없게 될 가능성이 있다.

그러므로 HDD 를 이동시킬 때는 반드시 전원을 끄고 디스크가

완전히 정지한 다음에 움직여야 한다.

그림 9) 트랙 , 섹터

섹터는 플로피 디스크와 하드디스크 기록 단위의 하나로서 자기

매체에 늘어선 동심원으로 구획된 하나하나를 트랙이라 부르고 (그림

7, 그림 9 참조) 그 트랙들은 다시 섹터로 나뉜다.

실린더는 다수개의 디스크의 트랙을 수직적으로 관통하는 3 차원적인

집합을 말한다.

따라서, 하드 디스크의 용량은 아래와 같이 나타낼수 있다.

하드용량=(헤드수) * (실린더수) * (섹터수) * (섹터당 기록용량)

여기서 섹터당 기록 용량은 보통 512KB 이다.

동심원을 동일한 각도로 나누어 데이터를 기록할 경우 내부 섹터와

외부 섹터의 실제 기록 밀도는 상당한 차이가 있다. 즉, 안 쪽

실린더에는 길이에 비해 기록 밀도가 매우 높다. 따라서 기록 밀도가

높은 곳은 그만큼 데이터 안정성에 문제가 있을 수 있다. 이런 이유

때문에 모든 섹터가 같은 길이를 갖도록 데이터를 기록하는 방식을

사용하는 것이 일반적인 추세이다. 이를 위해 하드디스크의 헤드

위치에 관한 정보를 읽을 수 있는 별도의 헤드를 하나 더 사용하기도

한다.

02020202. . . . 논리논리논리논리 섹터와섹터와섹터와섹터와 물리물리물리물리 섹터섹터섹터섹터

예전에 컴퓨터를 만든 사람들은 컴퓨터의 하드디스크가 이토록 커질

것이라고 생각을 못한 것 같다.

Intel cpu 를 만든 사람들도 RAM 이 1MB 면 충분할 것이라고

생각했지만, 요즘에는 1G 의 메모리를 쓰는 사람들도 많다.

MS 사도 MBR ( Master Boot Record )의 파티션 entry 에 실린더,

헤드 , 섹터를 쓰는 곳도 시작 섹터 3 바이트 , 끝 섹터 3 바이트로

정의해 버리는 오류를 범했기 때문에 실제적으로 최대 실린더 1023,

섹터 63, 실린더 255 밖에 표현할 수 없다.

즉, 1023 * 63 * 255 = 16,434,495 섹터 까지만 주소가 가능하다.

16,434,495 섹터 = 8,414,461,440 Byte = 8GB 의 하드만이 인식

가능한 것이다.

그림 10) LBA 모드와 CHS 모드

요즘에는 그러한 컴퓨터가 없었지만, 몇 년 전에만 해도 ' Bios 에서

8G 이상의 하드디스크를 지원하지 못해서 동작 못 한다 ‘ 라는

이야기를 들을 수 있었을 것이다.

바로 이 부분 때문에 그러한데, 요즘의 BIOS 들은 이 부분을 참조하지

않고, 뒤에서 설명하겠지만, LBA(Logical Block Array)방식을

이용해서 하드디스크의 크기를 나타낸다.

하드 디스크의 크기를 알 수 있는 방식은 크게 CHS 모드와 LBA

모드로 나눌 수 있다.

CHS ( Cylinder Head Sector ) 모드는 실린더, 헤드, 섹터로

나누어서 전부 곱하면 하드의 크기를 알 수 있는 방법이다.

LBA 는 그러한 계산 없이 크기가 계산된 양을 그림 10 에 보이는 것

처럼 노란색 테두리가 쳐져 있는 ‘ 0x0D8930F9 ’ 부분이 그

파티션의 크기가 되는 것이다.

만일 파티션이 나누어져 있지 않다면 그 부분이 하드디스크 전체

크기를 나타낼 수 있을 것이다.

0xFFFFFFFF = 4,294,967,295 섹터까지 표현할 수 있으므로,

4,294,967,295 * 512 = 2,199,023,255,040 Byte 의 용량까지 컨트롤

할 수 있는 것이다.

나중에 하나의 하드 디스크의 크기가 2TByte ( T = Tera )가 넘어가는

시대가 온다면 또 어떠한 방법으로 위의 한계를 극복할지 궁금하다.

필자의 막연한 생각으로는 현재 CHS 모드로 쓰고 있는 장소도 같이

할애하지 않을 까? 하는 추측을 해본다.

03030303. . . . Flash MemoryFlash MemoryFlash MemoryFlash Memory

하드 디스크와 메모리 카드는 외형적으로나 물리적 구성이나 구동

방식에서 많은 차이가 있다.

하지만, windows XP 와 같은 운영체제에 연결되면 둘은 단지

DATA 를 담아 놓는 똑같은 하드디스크처럼 동작하게 된다.

왜 그런 것일까?

지금부터 그 이유를 알아보자.

하드 디스크는 앞 절에서 말했듯이, 실린더,헤드,섹터로 구성되어

있다. ( 앞절 그림 참조 )

하드의 내부에는 원으로 되어 있는 판이 있는데, 이것을 디스크라고

한다고 앞절에서도 언급했다.

그림 11) 하드디스크와 메모리의 구조

반면, 메모리는 하드디스크처럼 어떠한 디스크를 가지고 있지는 않다.

단지 메모리셀 이라 불리는 작은 저장 장소가 많이 조합되어 있어서

메모리셀의 크기가 얼마나 크게 되느냐에 따라 메모리의 용량이

결정되는 것이다.

이렇게 물리적으로 틀린 성질을 가지고 있지만, 하드웨어와 연결 시켜

주는 ‘ 드라이버’ 라는 sw 가 단지 저장 매체로 인식하게끔 만들어

주기 때문에 우리가 생각하는 하드디스크처럼 동작할 수 있는 것이다.

잠깐잠깐잠깐잠깐 요요요요!!!!

그럼그럼그럼그럼 메모리는메모리는메모리는메모리는 어떻게어떻게어떻게어떻게 나누어지나요나누어지나요나누어지나요나누어지나요????

그림 12) 삼성전자의 Memory Tree

메모리 만드는 방법에 따라서 많은 메모리로 나누어지겠지만, 우리가

쓰는 메모리는 대략 그림과 같이 나누어 질수 있다.

메모리는 크게 RAM 과 ROM 으로 나뉘어 진다.

요즘에는 NAND 와 NOR 그리고 ONENAND, SuperAND 같은 다시

Write 가능한 ROM 들이 나와서 RAM 과 ROM 의 구분이 모호해 지고

있지만, 메모리의 흐름에 따라서 그림과 같이 인지해 주면 좋겠다.

EPROM 은 자외선으로 지워 다시 쓸 수 있는 메모리이다. 주로 예전의

컴퓨터에서 BIOS 쪽에 많이 쓰였던 메모리인데, 현재는 EEPROM

이나 Flash Memory 로 대체되어 거의 볼 수가 없다.

EEPROM 은 EPROM 의 단점인 자외선으로 지우는 방법 대신

전기적으로 지우는 방법을 쓰는 메모리이다.

쓰이는 곳은 컴퓨터의 BIOS 쪽이나 임베디드 시스템의 부팅을 위한

메모리로 사용된다.

FLASH 메모리는 현재 가장 많이 쓰이고 있는 메모리로, 핸드폰이나

USB 저장매체, MP3 플레이어, PMP 플레이어 등등에 쓰이고 있다.

셀의 구성에 따라 NOR 와 NAND 로 나누어 진다.

그림 13) DRAM 과 SRAM 의 구조 ( 자료 출처 hynix )

이렇듯, 전기가 공급되지 않아도 메모리의 내용이 저장되어 있는

메모리를 비휘발성 메모리라고 하고, RAM 과 같이 전기의 공급이

끊기면 메모리의 내용이 없어지는 메모리를 휘발성 메모리라고 한다.

휘발성 메모리라 함은 휘발유가 공기 중에 닿으면 금방 날라 가듯,

메모리에 전기를 넣어 주지 않으면 메모리의 내용이 없어지는 것을

뜻한다.

대표적인 휘발성 메모리는 바로 RAM 이다.

그림 14) 메모리 분류 ( 자료출처 hynix )

RAM 에서는 우리가 가장 잘 알고 있는 DRAM 이 있다. 우리의

컴퓨터에서 메모리라고 말하면 떠올리는 바로 그것이 DRAM 이다.

그림 15) DRAM 의 실제 쓰이는 곳 ( 자료 출처 hynix )

DRAM 은 Dynamic RAM 으로서 풀어서 설명하면, 동적메모리

일정시간동안 reflash 를 해 주지 않으면 메모리의 내용을 유지할 수

없는 메모리를 말한다.

반면, SRAM 은 Static RAM 이라고 해서 정적 메모리 즉, reflash 를

하지 않고 그냥 전기를 넣어 주면 그 내용을 유지하는 메모리이다.

SRAM 이 DRAM 보다 속도도 빠르고 안정적이라 할 수 있으나 더

비싸기 때문에 속도를 요하는 곳에서 쓰이고 있다.

이외에도 FeRAM 과 MRAM 등이 있는데, 비휘발성의 RAM 들이다.

ROM 에서도 다시 write 할수 있는 NAND 나 NOR flash 메모리가

있듯이, RAM 에서도 비휘발성의 메모리들이 만들어지는 추세라고

생각해 보면 된다.

위의 Memory 에 대한 정보를 자세히 얻고 싶으시면, www.sec.co.kr

이나 www.hynix.co.kr 에 가시면, 필자가 적고 있는 내용보다 더

상세한 내용을 얻을수 있을 것이다.

모바일이나, 임베디드 시스템에서 FAT 이나 여러 다른 파일 시스템을

구동시킬려면, 메모리나 하드디스크와 같은 저장매체를 구동시킬수

있는 프로그램(driver)가 필요하다는 것은 다 아는 사실이다.

즉, 필자도 메모리에 관련해서 이렇게 지면을 할애하는 것은 그 만큼

중요한 부분이라는 것을 강조하고 싶다.

모바일쪽에서 주로 쓰이는 대표적인 저장매체는 바로 NAND Flash

메모리이다.

앞으로 또 새로운 메모리가 만들어져 대표주자가 바뀔지는 모르겠으나,

현재는 PC 에서 하드디스크가 없으면 안되는 것처럼 모바일이나

Embeded 시스템에서 없어서는 안되는 존재가 되어 있다.

Flash 메모리에는 NOR Flash Memory 와 NAND Flash Memory 로

나눌수 있다.

셀을 만드는 방법에 따라 이렇게 나누어지는데, 필자도 그 그림을

봤지만, 더 자세한 내용까지는 모르겠고, 아래의 표와 같이 우리가

쓸수 있는 부분에서 이해하면 되겠다.

그림 16) Nor 동작의 이해 ( 자료 출처 hynix )

그림 17) Nand 동작의 이해 ( 자료 출처 hynix )

NOR 플레쉬 메모리와 NAND 플레쉬 메모리의 차이

NOR 기존값 입력 OR NOR

0 0 0 1

0 1 1 0

1 0 1 0

1 1 1 0

표 1) NOR 의 계산

데이터를 표시할 때 0 과 1 로 나타내고, 그러한 것들이 바로

Digital 이라는 것을 모르는 독자는 별로 없을 것이다.

NOR 즉, NOT OR = OR 가 아니다 라는 의미가 된다.

예를 한 번 들어 보자.

표를 보면 기존 값은 0 이고 그 위에 0 이 들어오면( Tm 는 동작을

하면 ), NOR 의 경우는 1 이 된다.

그래서, 만일 메모리 데이터의 내용이 ‘ 0x4D ’ 라고 하고, 그 위에

‘ 0xCE ' 를 쓴다고 하면,

0100 1101 ( 0x4D ) 과 1100 1110 을 bit 별 Nor 연산을 하게

되어서,

0100 1101 <----- 기존값 0x4D

1100 1110 <----- 입력값 0xCE

---------

0011 0000 <----- 결과값 0x30

0x30 의 값이 될 것이다.

NAND 기존값 입력 AND NAND

0 0 0 1

0 1 0 1

1 0 0 1

1 1 1 0

표 2) NAND 의 계산

마찬가지로 위의 값을 Nand 연산을 하게 되면,

0100 1101 <----- 기존값 0x4D

1100 1110 <----- 입력값 0xCE

---------

1011 0011 <----- 결과값 0xB3

0xB3 이 되어서 우리가 원하는 값이 되지 않게 된다.

이러한 이유 때문에 NAND 또는 NOR flash 메모리로 어떤 데이터를

저장하려고 할 때에는 꼭 Erase 를 하게 되는 것이다.

다시 하드디스크로 돌아 오면, 하드디스크는 NAND 나 NOR flash

메모리 처럼 동작하지 않는다.

0100 1101 <----- 기존값 0x4D

1100 1110 <----- 입력값 0xCE

---------

1100 1110 <----- 결과값 0xCE

즉, 우리가 쓰고자 하는 ' 0xCE ' 를 쓰면 그곳이 바로 ' 0xCE ' 로

바뀌게 된다.

따라서, 저장매체로 NAND 나 NOR flash 메모리를 쓰게 되면, FAT 을

올리기 전에 Flash 메모리와 interface 를 할 수 있는 management

code 들이 꼭 필요하게 된 것이다.

SMC Card 나 그냥 NAND Flash, NOR Flash 메모리는 control ic 가

없지만, mmc card 나 sc card , cf card , ms card 등의 가지고 다니는

메모리는 control ic 가 있어서, 데이터를 읽고 쓰기를 할때

하드디스크처럼 Erase 작업 없이 프로그램을 가능하게 해 준다.

다시 말하면, control ic 가 내부에서 하드디스크처럼 동작을 시켜주는

것이다.

그림 18) 메모리 특성 비교 ( 자료 출처 hynix )

우리가 메모리의 성격을 알고자 하는 궁극적인 목적은 메모리에

데이터를 저장함에 있다.

하지만, 메모리 속도가 안 난다면?

아무리 뛰어나고 좋은 제품이라도 저장매체로서의 매력이 없을 것이다.

또한 가격도 좋고 속도가 아무리 뛰어나도 크기가 너무 커서 소형화

제품에 쓸수 없다면 그 또한 매력이 없다.

따라서, 우리는 그림에서 보듯이 각각 메모리의 특성을 파악해서

필요한 곳에서 적시적소로 써야할 것이다.

각각의 개발하는 회사들마다 틀리겠지만, 파일시스템을 개발하는

입장에서는 하드디스크처럼 쓰고 싶은 내용을 쓰면, 바로 적용이 되는

메모리가 좋다.

그래서, 요즘에 SuperAND 나 DOC H3 같이 controler 가 내장되고

NOR+NAND 가 된 퓨전 메모리들이 나오고 있는 추세이다.

04040404. . . . Cluster Cluster Cluster Cluster ((((클러스터클러스터클러스터클러스터) ) ) )

섹터의 그룹이며 도스에 의해 인식되는 최소 기억단위이다. 보통

클러스터는 2 의 누승개의 섹터를 갖고 있다. 작게는 16 부터 많게는

64 혹은 128 개 이상의 섹터를 하나의 클러스터로 사용한다.

그렇다면 왜 섹터를 클러스터로 묶는가?

디스크에 512 바이트의 섹터 단위로 기록해도 아무런 문제가 없다.

사실 섹터 단위로 기록하면 데이터를 촘촘히 기록할 수 있기 때문에

기록 밀도는 훨씬 높아진다. 그러나 1024 실린더, 16 헤드. 63 섹터의

특성을 갖는 하드디스크를 생각해보자 섹터 단위로 기록을 한다면

자그마치 1,032,192 개의 어드레스가 필요하다.

하드디스크에 기록되는 파일은 대부분 512 바이트 보다 작지 않다.

따라서 512 바이트 단위를 초과할 때마다 연결된 데이터가 위치한

포인터가 필요하게 된다. 이것은 곧 바로 하나의 파일을 읽기 위해

수십 혹은 수 천 개의 포인터를 계산하여 읽어 들여야 한다는 것이다.

이것은 너무나 비효율적이기에 클러스터 묶어서 데이터를 처리하게

되는 것이다.

이렇게 클러스터 단위로 묶어서 데이터를 처리함으로서 계산과정 및

표현할 수 있는 것이 단순화 되어서, 데이터 관리에 장점이 되는 반면,

데이터의 슬랙화라는 단점을 가지게 되었다.

슬랙이란, 고정길이 레코드에 짧은 데이터를 기억시키게 되면,

레코드의 남은 공간이 생기는데 이부분이 바로 슬랙이다.

Disk Editor 에서 Boot Record 를 보면, ‘ Cluster 당 섹터 수 ’ 라는

항목이 있다.

보통 win9x 계열에서는 ‘16’으로 나와 있을 것이다.

1cluster 당 16 섹터 그리고, 1 섹터당 512byte 인경우가 대부분이기

때문에 16 x 512 = 8192 byte , 즉 8KB 가 파일의 최소 단위인

셈이다.

그림 19) Cluster 당 섹터 수

실제적으로 그런지는 그림 3 과 같이 Disk Editor 를 사용해 보면

확실히 알 수 있겠지만, 우선 Disk Editor 가 없는 분들은 간단히

테스트를 통해 자신의 Cluster 당 섹터 수의 값을 유추할 수 있겠다.

새로 만들기로 텍스트 문서를 만들고, 그 문서에 자신이 원하는 값을

써 넣는다.

간단히, ‘1’을 집어넣고, 파일의 등록정보를 보면, 크기가 8,192byte

인 것을 알 수가 있다.

사용된 바이트는 1byte 이고, 파일의 크기가 8,192byte 인 것이다.

즉, 사용 안 된 나머지 8191byte 는 슬랙 byte 인 셈이다.

만일, 16,384 바이트로 나온다면, 1sector 가 512byte 라는 조건하에,

Cluster 당 섹터 수의 값이 32 라는 것을 유추할 수 있다.

그림 20) 파일의 크기

클러스터 크기 최소 파티션 크기(GB) 최대 파티션 크기(GB)

4KB 0.5 8

8KB 8 16

16KB 16 32

32KB 32 !?

표 3) 클러스터와 파티션크기

파티션 크기 4kb cluster 8kb cluster 16kb cluster 32kb cluster

8GB 8MB 4MB 2MB 1MB

16GB 16MB 8MB 4MB 2MB

32GB 32MB 16MB 8MB 4MB

64GB 64MB 32MB 16MB 8MB

2TB(2,048G) -- 1,024MB 512MB 256MB

표 4) 파티션 크기의 증가에 따른 FAT 의 크기 변화

05050505. . . . 파일파일파일파일

파일은 cluster 들의 집합이다.

그림 4 와 같이 ‘1’이라는 값을 하나 집어넣는다면, cluster 는 1 개만

필요할 것이다.

하지만, 8,192byte 이상의 값을 집어넣는다면, 2 개의 cluster 가

필요해져서, 16,384byte 를 차지하게 된다.

마찬가지로, 더 많은 데이터를 집어넣는다면, n 개의 cluster 가

필요해지게 되는 것이다.

섹터-> Cluster -> 파일 -> 디렉토리 크기로 증가하게 되는데, 앞서도

봤겠지만, 섹터는 512byte , Cluster 는 일정크기의 섹터수로 그리고

파일은 최소크기의 cluster 부터 많은 양의 클러스터까지 차지하고

디렉토리는 데이터라기 보다는 구획을 정해주는 개념으로 보면 된다.

따라서, 우리는 데이터라고 부를 때 파일을 연상하게 되는 것이다.

1 개의 파일은 최대 얼마까지 만들 수가 있을까?

win98 일 경우 1 개의 파일이 최대 2G 까지 만들 수 있는데,

잠깐요!

하드디스크의 사용된 용량 및 사용 안 된 용량은 어떻게 구하나요?

간단히 말하면, FAT 이 실제 데이터의 1:1 매칭이므로 FAT 을

계산해서 사용되지 않은 cluster 를 세어서 계산하면 된다.

FAT 에는 DATA 가 기록될 시에 같이 check 가 된다.

‘ 이것은 사용되었으니 다음에 계산 할 때는 이곳을 쓰면 안 된다. ’

라고 기록이 되기 때문에 다음에 다른 파일이나 데이터를 쓸 때에

빈곳을 찾아서 check 를 하게 되는 것이다.

이것은 Disk Editor 를 사용하게 된 후에 더 자세히 다루게 될 것이다.

그림 20 에서 보면 우리가 잘 아는 ‘ 조각모음 ’ 프로그램이 있다.

쓰이는 곳은 녹색으로 표시되어 있고, 최적화 된 곳은 파란색으로

표시되어 있고, 없는 곳은 흰색으로 표시되어 있다.

조각 모음 프로그램의 원리는 FAT 에 있는 cluster 단위의 데이터

들이 떨어져 있으면, 하드디스크 구조상 읽고 쓰는데 느려질 수밖에

없다.

그래서, 같은 cluster 묶음으로 처음부터 순서대로 배열해 주는 작업을

하는 것이다.

최적화 되었다는 의미는 그런 식으로 해석해 볼 수 있다.

xp 에서 제공해 주는 조각모음은 이전의 조각모음과 다른데 ( 그림 21

참조 ) 이것은 최적화 시킨 데이터들은 처음부터 배열해 주는 대신

원래의 자리 그대로 두고 조각난( Cluster 가 연속되지 않은 것을

뜻함) 파일을 조각모음을 해주기 때문에 이전의 조각모음보다 훨씬

빠르게 조각모음을 할 수 있는 것이다.

그림 21) 조각모음

그림 22) xp 에서의 조각모음

06060606. . . . 파일시스템파일시스템파일시스템파일시스템

파일 시스템을 하드디스크나 플로피디스크 등의 기록 매체에 파일을

기록하는 방법으로 운영체제와 매체에 따라 달라진다. 운영체제에

관계없이 CD-ROM 은 CD 파일시스템(CDFS)을 사용하고,

플로피디스크는 FAT 파일 시스템을 사용한다. FAT(file allocation

table)파일 시스템은 파일 할당표에 파일에 대한 인덱스가 기록되어

있는 방식으로 FAT12, FAT16, FAT32 파일 시스템이 있다. FAT

다음에 붙어 있는 숫자는 파일에 대한 정보를 기록하는 단위를

의미하는 것으로 각각 12 비트, 16 비트, 32 비트를 의미한다. FAT16

파일시스템을 보통 FAT 파일 시스템이라 한다.

FAT32 파일 시스템을 사용하면 최대 2TB 볼륨을 만들 수 있고

8GB 이하의 볼륨에서는 4KB 단위의 클러스터로 사용하기 때문에

FAT16 에 비해 하드디스크를 훨씬 더 효율적으로 사용할 수 있다.

클러스터크기 하드디스크용량

FAT16 FAT32

디스켓 0.5KB 사용불가

17~128MB 2KB 사용불가

8129~256MB 4KB 사용불가

257~512MB 8KB 사용불가

513MB~1GB 16KB 4KB

1~2GB 32KB 4KB

2~8GB 사용불가 4KB

8~16GB 사용불가 8KB

16~32GB 사용불가 16KB

32~2048GB 사용불가 32KB

표 5) 하드디스크 볼륨 크기별 클러스터 크기 비교표

07070707. . . . 포맷포맷포맷포맷

2 부 6 장에 보면 format 만들기란 섹션이 있다.

그래서, 우리는 이곳에서 포맷이란 무엇인지 알고 가야 한다.

필자는 많은 종류의 포맷 프로그램을 봐 왔다.

하지만, 각각의 프로그램들은 각자의 포맷의 의미를 조금씩 다르게

규정하고 있는 것이 사실이다.

Bios level 에서 말하고 있는 포맷이 있고, OS level 에서 말하고 있는

포맷도 있고, 또 단순히 Delete File 만 하는 프로그램을 가지고

포맷이라고 말하는 이도 있다.

필자도 정확한 역사를 알지 못하고 있기 때문에 단지 몇몇의 포맷

방법을 논하고자 한다.

그림 23) 포맷의 분류

필자가 나누는 방법은 그림 22 처럼 나누고 싶다.

- Low level format : 이 이름을 누가 붙인 것인지는 모르겠지만,

아마 Bios 제조업체중 어느 한 곳에서 이렇게 붙인것이 시초가 된 듯

싶다.

예전에 Bios 업체에서 만든 CMOS 설정 프로그램에 들어가 보면, low

level format 이라는 것이 있었다.

이것은 하드디스크를 ' 0xFF ' 또는 ' 0x00 ' 의 한 값으로 하드의

처음부터 끝 섹터까지 쓰는 것을 이야기한다.

물론, 그렇게 하면서 disk 검사도 같이 동작하는 것도 있지만,

정확히 말하면, 이것은 format 이 아니라 초기화시키는 개념이다.

- format : 이것은 우리가 알고 있는 포맷의 개념이다.

FAT 을 구성하기 위해선 시스템적인 섹터들이 있는데, 그러한 섹터들

중에서 FAT 의 내용과 RDE 의 내용 그리고, 실제 DATA 가 있는

부분을 FAT 크기에 맞게 바꾸어 주는 역할을 한다.

이것은 실제 DATA 가 읽고 쓸수 있는지도 검사하고 FAT 과

DATA 의 크기를 맞게끔 고쳐주는 작업을 하기 때문에 오래걸린다.

- Quick format : 실제적으로 존재하는 데이터를 초기화 시키지 않고

FAT 와 RDE 만을 초기화 시켜주는 작업이다.

실제 데이터를 초기화 시켜주지 않기 때문에 굉장히 빠르게 포맷을 할

수 있다.

요즘에는 일반적으로 하드의 bed sector 가 생기는 경우가 거의 없기

때문에, Quick format 을 해도 동작하는데 문제는 없다.

하지만, 만일 물리적인 bed 섹터가 의심된다던가 아님 bed cluster

같이 커다란 시스템 오류가 있었고, 포맷을 하게 된다면 일반적인

format 을 하기 바란다.

3333 장장장장 OS OS OS OS 와와와와 FAT FAT FAT FAT 의의의의 관계관계관계관계

OS 란 무엇일까? 그것을 알고자 한다면, OS 에 관련된 문서를 사서 공부해

보라고 권하고 싶다. 물론, 현재 보고 있는 문서를 먼저 보고 OS 에 대해

공부한다면 더더욱 잘 이해할 것이라고 장담한다.

이번 장에서는 NAND Flash 메모리와 관련된 OS 를 얘기하고자 한다.

전체적인 구성은 win98 , win2000, winxp , linux , 그 외 embeded RTOS

가 같다.

즉, 필자가 쓰고 있는 내용을 잘 이해한다면, 어떠한 파일시스템이든, OS 든

배경지식은 문제가 없을 것이라고 생각한다.

참고로, 필자가 windows 프로그램에서 embeded 프로그램으로 약간의 업종

변경(?)이 가능 했던 것은 전체적인 이해를 할 수 있었기 때문이었다.

01010101. . . . OSOSOSOS 의의의의 구조구조구조구조

OS 를 분석하는 방법은 여러 가지가 있을 수 있다.

우리가 공부하는 파일시스템도 그 방법 중 하나이다.

인터럽트, 메시지, 세마포어 등등과 같이 시스템 프로그램을 배우는 것도 그

방법의 하나일 수 있고,

또한, 디바이스 드라이버를 공부해서 전체적인 시스템을 알아가는 것도 또

하나의 방법일 수 있다.

그럼, 도대체 OS 란 무엇일까?

Operating System, 즉 어떤 장치를 동작하게 하는 프로그램쯤으로 알아두면

된다.

장치를 동작하게 하는 프로그램? 그럼 시스템 프로그램을 말하나? 라는

의문을 가질 수 있겠지만, 포괄적으로는 같은 의미가 되겠다.

linux 에서는 커널프로그램을 하는 사람들을 시스템 프로그래머로 보기

때문이다.

어쨌든, 우리의 접근 방식은 그런 것과는 조금 틀리다.

어떻게 보면 좀 더 하드웨어에 가깝고 또한 개념도 쉽게 잡을 수 있다.

왜냐하면, 우리는 저장매체에만 신경을 쓰면 되기 때문이다.

embeded 시스템에서 우리가 OS 를 구성하려고 한다면, 우리는 어떤 작업을

해야할까?

예를 들어 핸드폰이라면,

우리는 CPU , RAM , FLASH Memory , USB 나 UART 와 같은 IO , LCD ,

마이크 , 스피커 같은 것이 필요할 것이다.

물론, 속안에는 또 나름데로 I2C, I2S 같은 프로토콜이 필요할 것이고, 또

각각의 장치에 따라 Device controller 가 존재할 수도 있다.

즉, 장치가 있고, 장치를 구동(직접 액세스하는)시키는 소프트웨어가 필요할

것이다.

이것을 Device Driver 이라고 한다.

하지만, Device(장치)들이 하나씩 동작한다면 문제가 없겠지만, 우리가

키패드를 두드리는 동안에 안에서는 많은 작업이 이루어진다.

따라서, 이러한 동작을 하나씩 동작하는 것은 요즘같이 빠른 연산속도를

가진 cpu 에겐 너무나 따분한 일이 아닐 수 없다.

그래서, 프로그래머는 멀티태스킹(다중작업)을 할 수 있는 방법을 생각해

냈고, 그러한 것이 하나의 OS 형태로 발전한 것이다.

즉, 작업의 관점을 사람보다는 OS 에 맞추어서 프로그램을 하지만, 그러한

프로그램의 궁극적인 목적은 좀 더 편리한 사용에 있다.

그래서, 우리는 좀 더 편리하고 예쁘게 사용하기 위해서 GUI (Graphic User

Interface )에 신경을 쓰게 되고 그러한 것을 프로그램하기 위한 방법 및

툴들이 나오게 되었다.

그래서, 그림 19 와 같이 간략히 나눌 수 있다.

물론, 이것은 OS 에 따라 조금씩 다르지만, 대부분은 흡사하다.

그림 24)

windows2000 의 경우는 FAT 대신 NTFS 파일 시스템이 들어가고

Driver 와 Application 사이에 커널이 들어가는 정도일까?

아무튼, 우리가 쓰고 있는 mp3 player 나 PMP player, 핸드폰과 같은

대부분의 장치들은 이러한 구조를 가지고 있다.

GUI 같은 경우는 우리가 프로그램할 때 쓰는 visual basic 이나 visual c++

같은 것으로 프로그램을 하는 경우라고 할 수 있고, Application 프로그램은

GUI 외에 백그라운드로 동작하는 프로그램이라고 볼수 있고, Driver 나

커널은 FAT 또는 Device 를 돌리는 프로그램이라고 생각할 수

있고, FAT 은 저장매체와 연관하고 record 방식을 결정하고, Device 는

실제 동작하는 장치로 생각할 수 있겠다.

이렇게 간단히 얘기하면, 정말 OS 도 별거 아니구나 라는 생각이 들지만,

실제로는 알아야 하는 과정이 많고, 위의 어느 한 분야도 정확히 알기가

힘들다는 것을 유념해 두어야 한다.

하지만, 너무 복잡하게 생각하지 않고 넓게 보면 단순하다 라고 생각하고

자신에게 자신을 주는 것도 좋은 생각이다.

실제로 공부하다 보면 별것이 아닐 수 있기 때문이다.

02020202. . . . Booting Booting Booting Booting 이란이란이란이란????

앞서 Booting 의 과정을 간략히 설명한 적이 있다. 다시 되풀이 하는

이유는 그만큼 중요하다고 생각하고 또한 Booting 이란 과정을 통해서

원자분열이 일어나듯 복잡한 계산이 가능한 컴퓨터가 동작하게 되는

것이다.

Booting 이란, 하드디스크나 플로피디스크, Flash memory , CD-ROM

과 같은 보조 기억장치로부터 컴퓨터 주 메모리 특정 영역에

운영체제를 load 시키는 작업이다.

cpu 는 프로그램을 동작할 때 잠시 동안 계산 과정을 담아놓는 장소가

필요한데, 그러한 곳이 바로 RAM 이다.

cpu 는 그래서 동작할 때는 모든 장치를 RAM 에다 올리는 작업을

한다.

그림 25) 부팅과정

그것을 control 하는 cpu 는 규칙에 따라서 ( 어셈블 코드를

해석해서 ) 제어권을 옮긴다.

BIOS 의 내용을 RAM 에 옮기는 최초의 작업은 CPU 가 한다.

그리고는 RAM 에서 프로그램이 동작하게 되는데, 그 첫 번째 과정은

장치를 scan 해서 규격에 맞는 장치가 있으면, RAM 에 Load 시키는

작업을 하고 마지막으로 HDD 와 FDD 를 검색해서 Boot 할 작업을

한다.

다른 계열의 Cpu 의 경우는 어떤지 모르겠지만, Intel 계열의 cpu 특히

우리가 잘 알고 있는 80x86 계열의 CPU 의 경우는 첫 부팅하는

장소는 그 보조장치의 첫섹터(512byte)로 부팅을 시작하게 되는

것이다.

이것이 HDD 이라면, MBR 가 이역할을 하게되고, FDD 라면 BR 가 이

역할을 하게 된다.

MBR 이 있는 이유는 후에도 말하겠지만, 파티션을 나누기 위한

장소라는 것을 알아 두면 된다.

따라서, 하나의 드라이브에서 동작하는 FDD 같은 경우는 MBR 이

필요 없게 된 것이다.

03030303. . . . NANNANNANNAND BootD BootD BootD Boot

Arm processor 는 embeded 나 또는 모바일쪽에서는 PC 상의 Intel cpu 처럼 많이 쓰이는

프로세서이다.

NAND Boot 도 여러 cpu 로 설명하면 더욱 좋겠지만, 어차피 하나의 embeded 시스템의

NAND Boot 를 알면, 다른 프로세서의 NAND Boot 도 거의 같기 때문에 하나의 시스템을

집중 분석해 보도록 하겠다.

사실, 크게 보면 NAND Boot 도 HDD Boot 와 별반 차이가 없다.

Program Counter 가 어디에 현재 위치해 있는지 그리고 어느 주소인지만 알면, 그렇게

힘들지 않을 것이다.

그림 26) NAND Boot 진행

x86 계열의 INTEL cpu 도 처음 부팅할 때 0xfffff0000 번지에서 첫 동작이 이루어지기

때문에 첫 코드가 들어가고, 그 데이터를 RAM 에 load 한후 마찬가지로 MBR 을 읽어서,

RAM 에 올린 후, MBR 의 내용이 또 동작을 하게 되는 것이다.

NAND 도 마찬가지로 ARM 내부의 4k byte 의 jump code 가 있어서( 이것은 ARM

프로세서 종류에 따라 다를수 있다. ) NAND 의 LOADER 부분을 읽어서 SDRAM 에 올려

준다.

이때, NAND flash 의 LOADER 의 위치는 ARM core 내부에 프로그램하는 사람마다

틀리겠지만, 보통 NAND flash 의 0 번지부터 읽도록 프로그램을 한다.

대신, SDRAM 에서는 0 번지 말고 다른 위치( 예를 들면, 0x100000 같은 위치 )에

load 하게 된다.

처음의 jump code 의 하는 역할은 NAND flash 에서 읽어서 SDRAM 에 load 하는

역할이었기 때문에, 그 역할이 끝나면, Program Counter 를 SDRAM 의 load 된 번지로

돌리게 된다.

그리고, 이후 부터는 load 된 번지부터 프로그램이 수행되게 된다.

그러면, Loader 는 이제 NAND flash 로부터 어플리케이션 프로그램을 읽어서, SDRAM 에

0 번지에 copy 를 한다.

이렇게 다른곳에 있는 내용을 SDRAM 에 재 정렬 작업을 하는 작업을 remapping 이라고

한다.

remapping 을 하는 이유는 SDRAM 에서 부팅을 하고 싶기 때문이다.

우리가 pc 상에서 warm boot 라고 하는 작업도 사실 DRAM 에서 부팅을 하는 것을 뜻한다.

전원을 껐다가 다시 켜는 것과 Ctrl+Alt+del key 를 눌러서 재부팅하는 것과의 차이라고

생각하면 정확하다고 할 수 있다.

이제 SDRAM 의 0 번지에 우리가 원하는 어플리케이션의 code 가 올라 왔으므로,

소프트웨어 reset 을 하면 ARM 은 jump code 부터 동작하지 않고 바로 SDRAM 으로부터

동작을 하게 된다.

이로서 사람들이 원하는 NAND 로 Boot 를 할 수 있는 것이다.

사실, 예전에는 NAND flash 가 하는 역할을 ROM 이 대신했었다.

하지만, NAND 나 NOR 같은 비휘발성 flash 메모리가 개발되면서 현재 PC 상에서도

boot 할 때 flash 메모리를 쓰는 추세이다.

일반적으로 BIOS 를 upgrade 한다고 할 때 그러한 것이 가능할 수 있는 것이 바로 flash

메모리를 쓰기 때문이다.

만일, flash 메모리를 잘못된 것을 쓴다면?

예를 들어, jump 하는 메모리 번지가 상이한 곳으로 점프하게끔 프로그램을 해서 flash

메모리로 쓴다면?

우리가 잘 알고 있는 CIH 바이러스 ( 일명 ‘ 체르노빌 바이러스 ’ ) 같은 동작을 하게 된다.

메인보드가 동작을 안 하기 때문에, HDD 로 Program Counter 가 넘어가지 않을 것이고,

HDD 에서 DRAM 으로 어플리케이션이 load 가 안되기 때문에 그 다음 진행이 이루어지지

않아, 컴퓨터 화면은 검은색을 띄고 있을 것이다.

또한, 더 장난을 친다면 어차피 MBR 을 지워 버리면 그 하드는 다른 곳에서는 부팅조차도

할 수 없고 다른 PC 에 Slave 로 붙여도 ‘ 포맷 하시겠습니까? ’ 라는 메시지만 보게 될

것이다.

NAND Flash 는 ROM 이다.

즉, NAND Flash , NOR Flash, 또는 EEPROM 같은 ROM 은 비휘발성이기 때문에 시스템이

부팅 시에 도와주는 역할을 해 준다.

실제적으로 프로그램이 load 되어 동작되는 부분은 SDRAM, DRAM, DDRRAM 과 같은

RAM 에서 동작하게 된다는 것을 알면, 위의 시스템을 다른 ROM 으로 대체할 수도 , 다른

RAM 으로 대체할 수도 있게 된다는 것을 독자가 이해한다면, 이번 장에서 필자가 의도한

바가 제대로 전달되었다고 할 수 있다.

04040404. . . . NAND Flash Memory InterfaceNAND Flash Memory InterfaceNAND Flash Memory InterfaceNAND Flash Memory Interface

OS 의 구조에서 설명했듯이, OS 에서 FAT 을 쓰기위해서는 약간의

준비과정이 필요하다.

각각의 Device 와 인터페이스 하는 부분이 있어야 하는데, 이번

절에서 다루고자 하는 내용은 바로 그 인터페이스 하는 부분을 이야기

하고자 한다.

이 부분을 이렇게 떼어서 설명하게 된 이유는 이 부분이 대부분의

embeded 프로그래머가 겪는 힘든 일이기 때문이다.

‘ 얼마나 메모리(RAM)를 적게 사용하면서 얼마나 수행능력을 높일

수 있을까? ’ 하는 물음에 대한 대답이 어쩌면 이곳에 있을 수 있기

때문이다.

특히, NAND Flash 메모리는 다른 flash 메모리에 비해 가격이 싸지만

몇몇 제한 사항이 있기 때문에 그것을 잘 극복(?)해야만 제대로 된

속도를 낼 수 있다.

하지만, 이곳에서는 그러한 특별한 방법을 알려 줄 수는 없다.

그것은 그 회사들의 Knowhow 이기 때문이고, 또 각각의 시스템 마다

다를 수 있기 때문이다.

정말 세세한 것까지 알고자 한다면, 칩메이커의 white paper 를 읽어

보기 바란다.

그림 27) memory addressing ( 자료 출처 : www.sec.co.kr )

메모리는 간단히 위의 그림과 같이 설명될 수 있는데, 1 섹터는

512Byte 이고, 그러한 섹터들이 모여서 Page 를 만들고, 또

Page 들이 모여서 Block 을, 그리고 Block 들이 모여서 하나의

Device 가 되는 것이다.

Column 과 Row 어드레스가 존재해서 읽을 때 이 두 어드레스를

통해서 읽어야 한다.

메모리를 액세스 하기 위해선 각각에 명령을 보내고 Adress 를 보내야

하는 데, 그 부분은 data sheet 에 더 잘 나와 있기 때문에 자세히는

설명하지 않겠다.

대략적으로 큰 그림을 설명하면, 어드레스 용 레지스터가 있는데,

그곳에다 A0~A23 까지 값을 넣어 주고 읽기 명령 주고 Data

레지스터에서 그 값을 Buffer 에다 담으면 되는 것이다. ( 각각 메모리

회사의 data sheet 를 참조 )

정확한 데이터를 읽고 쓰기 위해서 addressing 을 잘 해야 한다.

그림 26 의 A0 ~ A7 은 512byte 의 첫 번째 반쪽인 256byte 를

뜻한다.

A0 ~ A7 까지 모두 1 이 되면 ( 1111 1111 (2 진수) = 255 ) 이므로

0 부터 255 까지 addressing 이 가능해서 256byte 가 구별이 가능한

것이다.

A9 ~ A13 는 0 ~ 31 까지의 한 block 에 존재하는 page

addressing 을 나타낸다. ( 한 Block 당 32page 라는 얘기다. )

A14 ~ A23 은 11 1111 1111 (2 진수) 1023 이고, 0 부터 1023 까지

addressing 이 가능한 Block 수를 나타낸다.

따라서, 위의 메모리 용량을 계산하면,

1024 block * 32 page * 1page 당 byte 수 ( 512 byte ) =

16,777,216 으로 16MB 용량의 flash 메모리 인것을 알 수 있다.

질문이 생길 것이다.

1page 당 byte 수가 어떻게 나왔는지 궁금할 것이다.

A0 ~ A7 까지는 첫 번째 반쪽을 나타냈다. A8 은 command 명령으로

00h 이면 첫 번째 반쪽을 의미하고, 01 이면 두 번째 반쪽을

의미하게 되는 것이다.

따라서, 1page 는 256+256 = 512byte 임을 알 수 있다.

또 질문이 있을 것이다.

바로 spare 영역이 궁금할 것이다. spare 영역은 실제로 data 로

읽혀지지는 않고 data 로 쓰인 부분의 error 체크할 목적으로 만들어

졌다.

ECC 체크라든지 그 외의 체크 값이 들어갈 수도 있고, 목적에 따라

안 쓰일 수도 있다.

그리고 ECC 체크를 안 하는 Firmware 소프트웨어도 많이 봤다.

아마 속도나 여러 이유 때문에 안 쓰이는 경우가 많으나, 되도록 이면

data sheet 의 목적대로 맞추어 주자,

그러한 행동이 버그를 줄이는 방법이 될 수도 있다.

그림 28) Small Block 방식의 메모리 구조

현재 생산되고 있는 NAND flash 메모리들은 크게 2 가지 분류로 나눌

수 있다.

Large Block 로 구현된 flash 메모리와 Small Block 로 구현된 flash

메모리로 나눌 수 있다.

왜 이렇게 나누었는지 정확히는 알 수 없지만, 아마도 많은 용량을

작은 크기에 넣기 위해서는 제조공정상 어쩔 수 없는 선택이었을

것이다.

그림 27 은 Addressing 을 하는 방법은 그림 26 과 별반 차이가 없다.

Block Address 가 1024 에서 8192 로 약 8 배 늘어나서 전체 메모리

크기는 128MB 로 늘어난 것을 알 수 있다.

그림 29) Large Block 방식의 메모리 구조

반면, 그림 27 을 보면, 중간쯤에 512Byte 와 2K Byte 이 틀리다는

것을 알 수 있다.

또한, A0 ~ A27 의 배치도 틀리다는 것을 알 수 있다.

A0 ~ A10 까지는 Page 당 크기를 나타낸다.

11 개의 bit 이므로, 2048Byte 까지 addressing 이 가능하다.

A12 ~ A17 까지는 Block 당 Page address 를 나타낸다.

6bit 이므로 11 1111 = 63 즉, 0 부터 63 까지 addressing 이

가능하다.

A18 ~ A27 는 10 개의 bit 로 총 1024 개의 block addressing 이

가능하다.

그래서, 이 device 의 총 용량은,

1024 block * 64 page * 1page 당 섹터수 ( 2048 byte ) =

134,217,728 byte = 128MB 가 되는 것이다.

2222 부부부부 FAT FAT FAT FAT 파일파일파일파일 시스템을시스템을시스템을시스템을 분석하기분석하기분석하기분석하기 위한위한위한위한 기본기본기본기본 툴들툴들툴들툴들

1111 장장장장 Disk Editor ( Disk Editor ( Disk Editor ( Disk Editor (시만텍시만텍시만텍시만텍 사사사사) ) ) )

Disk Editor 는 디스크의 내용을 편집하기 위한 툴이다.

Disk 는 HDD 가 될 수도 있고, FDD 가 될 수도 있고, flash memory

가 될 수도 있다.

디스크의 내용을 직관적으로 들여다 볼 수 있는 중요한 툴이고, 이

문서에서는 Disk Editor 만큼은 아니지만, 비슷한 기능을 하는

프로그램을 만들어 놓았다.

Disk Editor 가 힘들다면, 문서에 첨부되어 있는 Disk View 를

사용해도 된다.

20 여개의 그림과 함께 설명을 하기 때문에 지루함 감도 있을 테지만,

그림 30) DE.EXE 실행화면

그림 3 은 Disk Editor 가 실행된 화면이다.

앞으로 나오는 경고문들을 전부다 해석하면 좋겠지만, 대충

해석하자면, Disk 를 읽고 쓰게 되니까 조심하라고 생각하면 된다.

물론, Disk Editor 2000 부터는 윈도우즈에서는 물리적으로 쓰지

못하게 되어있다.

그림 4 에서도 간략한 설명이 나오지만, 윈도우즈가 멀티태스킹을 하기

때문에 어떤 결과를 초래할지 모르기에 읽기 전용으로만 나온 것이다.

그림 31) 멀티태스킹 경고문

그림 32) 하드의 디렉토리 검색

그림 4 에서 또다시 enter key 를 누르면 그림 5 에서 처럼 디렉토리를

검색한다.

그림 33) scan 시에 정지한 화면

하드를 scan 하면 용량에 따라 차이는 나겠지만, 오래 걸리기 때문에

ESC key 를 누르면 그림 6 과 같은 화면이 나오면서 멈출 것인지가

나온다.

보통 한 번 정도는 스캔해 두고 다음부터는 안 해도 그렇게 차이는

없다.

그림 34) 디렉토리의 내용을 보여주는 화면

주메뉴는 Object, Edit, Link , View , Info, Tools, Help 가 있다.

01010101. . . . Object Object Object Object

- 물리 드라이브 , 논리 드라이브로 변환 , 디렉토리 보기, File 보기,

Cluster 보기 등등 주로 굵직한 주제들이 들어 있다. ( 그림 8 번

참조 )

그림 35) Object 를 선택시

그림 36) Object -> Drive 선택시

02020202. . . . Object Object Object Object ----> Drive > Drive > Drive > Drive

그림 9 와 같은 화면이 나온다.

그림의 내용은 드라이브 선택이다.

Type 이 Logical Disk 로 선택되어 있으면, 왼편에는 현재 논리적으로

보이는 드라이브를 보여준다.

Logical 로 본다는 사실은 현재 OS 가 설치된 파일 시스템을

따라가면서 디렉토리나 cluster , 파일을 보여준다는 의미가 된다.

Disk Editor 는 현재 FAT,FAT16,FAT32 의 논리적 디스크 만을

보여준다. NTFS 파일시스템 및 그외의 시스템은 Physical 밖에 볼수

없다.

마찬가지로 Type 에서 Physical Disk 로 선택되어 있으면, OS 는

상관없이 현재 디스크를 물리적으로 0 부터 시작해서 마지막 섹터까지

볼수 있다는 의미가 된다.

또한, ‘Read Only' 옵션을 없애면, 섹터를 바로 쓸수도 있다.

그림 37) Object -> Directory 선택시

03030303. . . . Object Object Object Object ----> directory> directory> directory> directory

그림 10 과 같은 화면이 나오는데, 현재보고 싶은 디렉토리를

선택하도록 하고 선택이 끝나면, 디렉토리 내에 있는 파일 및 sub

디렉토리를 그림 7 과 같은 형식으로 보여준다.

3) Object -> Directory 선택하면, 그림 11 과 같은 화면이 나온다.

파일을 선택해 실제 데이터를 볼수 있도록 하기 위함이다.

그림 38) Object -> File 선택시

그림 12 는 실제 파일을 선택했을 때 그 파일의 데이터가 있는 내용을

보여주는 화면이다.

그림 39) 실제 섹터의 데이터를 보여주는 화면

그림 40) Object -> Sector 선택 시

그림 12 에서는 주로 Cluster 정보, 논리/물리 섹터 정보, 파일명 Full

Path 등을 알 수 있다.

그림 41) Object -> cluster 선택시

04040404. . . . Object Object Object Object ----> Cluster > Cluster > Cluster > Cluster

그림 13 과 같은 화면이 나온다.

Cluster 단위로 섹터의 내용을 보고자 할 때 쓰면 된다.

05050505. . . . Object Object Object Object ----> Sector > Sector > Sector > Sector

그림 14 와 같은 화면이 나온다. 현재 보고 있는 논리적 섹터에서

다른 논리적 섹터로 jump 하기 위한 것이라 생각하면 된다.

6 번 섹터를 보고 있다가 10000 번 섹터를 보고자 방향키를 10000 번

가까이 누를 필요는 없기 때문이다.

06060606. . . . Object Object Object Object ----> Boot Record > Boot Record > Boot Record > Boot Record

그림 15 가 나온다.

갑짜기 이것이 뭐냐는 분들이 계실지 모르겠지만, 나중에 Boot

Record 에 대해서 설명을 하겠으니, 우선은 이런 내용이 있구나 하고

넘어 가시면 되겠습니다.

그림 42) Object -> Boot Record 선택 시

07070707. . . . Object Object Object Object ----> > > > 1111st FAT st FAT st FAT st FAT

그림 16 이 나오게 된다.

win9x 계열에서 FAT 라는 파일 시스템을 쓴다는 것은 일반인들도

많이 들어 봤을 것이다.

그림 16 이 바로 그 FAT 의 실체입니다.

실제로 DATA 가 있는 섹터들을 cluster 단위로 만들어서 번호를 메겨

놓았는데, 그것을 찾아가는 지도(map)이라고 생각하시면 됩니다.

이 부분도 나중에 설명드리도록 하겠습니다.

그림 43) Object -> 1st FAT 선택 시

08080808. . . . Object Object Object Object ----> Memorey > Memorey > Memorey > Memorey

그림 44) Object -> Memory Dump 선택 시

그림 17 과 같은 화면이 나온다.

이것은 디스크와는 상관없이 현재 기본 메모리에 대한 메모리

dump 를 하기위한 기능이다.

09090909. . . . ViewViewViewView

- 선택하면, 그림 18 과 같은 화면이 나온다.

그림 45) View 선택 시

as Hex

as Text

as Directory

as FAT(12)

as FAT(16)

as FAT(32)

as Patition Table

as Boot Record(16)

as Boot Record(32)

방식으로 보여주는데, Object 에서 대부분 보았던 그림들이다.

Hex 는 섹터 내용을 볼 때, Text 는 파일내용을 볼 때, Directory 는

Object -> directory 를 선택할 때 나오는 화면들이다.

FAT12 /16 /32 는 그림 16 과 같은 형식으로 나오게 보여주는 것이다.

즉, Object 에 있는 내용만을 알면, View 는 단지 현재 섹터를 어떤

방법으로 보여줄 것인가 라는 기능으로 쓰이는 것이다.

예를 들면, Boot Record 방식으로 보고 있다가 Hex 값으로 볼 때

위의 기능을 쓰면 된다.

여기서, 지금까지 언급 안 한 것이 있는데, 바로 단축키이다.

as Hex -> F2 , as Patition -> F6 과 같이 단축키를 누르면 보려고

하는 내용을 빠르게 볼수 있다.

모든 단축키를 다 외워도 좋겠지만, 필자처럼 외우는 머리가 좋지

않은 사람들은 우선 필요한 단축키들을 사용하다가 점점더 익숙해지

것이 필요하다.

참고로, 필자도 F2 -> as Hex, F6 -> as Patition , Alt+D -> drive ,

Alt+S -> Sector , Alt+P -> Physical Sector , Alt+B -> Boot

Record , Alt+F1 -> 1st FAT 정도만 외우고 있다.

10101010. . . . View View View View ----> as Partition Table> as Partition Table> as Partition Table> as Partition Table

그림 46) View ->as Partition Table 선택시

그림 19 와 같은 화면이 나오는데,

하드 드라이브의 드라이브 분할에 관해 보여주는 화면이다.

이 부분도 뒤에서 자세히 설명하도록 하겠다.

11111111. . . . Tools Tools Tools Tools

- 그림 20 을 보면 알겠지만, 찾기, 계산기, 복구 등등의 기타 기능이

들어가 있다.

그림 47) Tools 선택

필자는 ' Find '와' Write Object To ... ' 와 같은 기능들을 사용했다.

파일시스템을 분석하는데 필요하면 뒤에 좀 더 자세히 설명을 할

것이다.

2222 장장장장 첨부된첨부된첨부된첨부된 Utility Utility Utility Utility 프로그램들프로그램들프로그램들프로그램들

첨부된 Disk 관련 Utility 들은 필자가 손수 짠 프로그램이므로,

freeware 라고 생각해도 된다.

그리고, 뒤에서 첨부된 Utility 들을 소스 분석할 것이다.

앞서도 말했지만, 노턴의 Disk Editor 만큼 잘 만들어 진 프로그램은

아니다.

하지만, 기본에는 충실했으므로, 다른 응용프로그램으로 발전 가능할

것이다.

01010101. . . . Diskview Diskview Diskview Diskview

DiskView 는 우리가 다루려는 것이 하드디스크, 플래쉬 메모리, SCSI

디스크 등등 이므로, 디스크를 볼수 있는 툴리 필요했다.

Disk Editor 로 보는 것이 더 좋겠지만, 빠르게 보고 빠르게

대처하려고 만든 만큼 Disk Editor 보다 나은 점도 있다.

그림 48) DiskView 화면

예를 들면,2 Disk Editor 로 다수의 섹터를 삭제하려면, 번잡하고

시간이 오래 걸린다.

그림 21 에 보듯이 Dos Command 에서 그냥 ‘ c:\ DiskView /s

보고싶은 섹터 ' 라고 치면 된다.

Diskview /s Sector : 보고 싶은 물리섹터를 DiskView /s 다음에

치면된다.

그러면, 바로 HEX 값들이 TEXT 화면으로 올라 온다.

DiskView /z Sector : /z 옵션으로 원래 zero 의 약자로 clear 시킬 때

쓰면 된다.

예) a:\disview /z 0 : A 드라이브의 0 번섹터를 Zero 로 만들어라.

a:\diskview /z 0 100 : A 드라이브의 0 번섹터부터 100 번

섹터까지 Zero 로 만들어라.

DiskView /c 소스섹터 타겟섹터 : 원본 섹터를 목표 섹터에 copy

하라는 명령이다.

예) a:\diskview /c 6 0 : A 드라이브의 6 번 세거를 0 번 섹터로

copy 하라.

DiskView /p 시작섹터 끝섹터 : 1st 드라이브와 2nd 드라이브의

시작섹터와 끝섹터를 비료하라.

예) c:\diskview /p 0 1000 : 1st 물리 디스크와 2nd 물리

디스크의 0 번섹터부터 1000 섹터까지 비교하라.

보면 아시겠지만, 하드를 clear 시키고, 특정섹터를 copy 해서 넣어

두고, 두 하드 디스크를 비교하고, 하드디스크에 있는 섹터를 바로

바로 보기 위해서 만든 util 이다.

02020202. . . . InFatInFatInFatInFat

그림 49) InFAT 화면

그림 22 에 보이듯이 앞서 보았던, 파일시스템에 대한 정보들을

보여주는 util 이다.

Disk Editor 는 편집기 이지만, InFat 는 파일시스템처럼 따라가면서

정보를 보여준다.

만일 디스크, 파일시스템 관련 프로그램을 하시려면, FAT 나 NTFS 의

문서를 다시 공부하셔야 하는데, 그러한 수고를 덜어 주는

프로그램이라고 생각하면 된다.

03030303. . . . hexcopyhexcopyhexcopyhexcopy

hexcopy 는 물리적인 섹터의 일부분을 읽어서 파일로 만들거나,

파일로 만든 binary 값을 물리섹터 일부분에 copy 할 때 쓰는

프로그램이다.

MBR 또는 BR 를 분석할 때 쓰기 위한 툴이다.

그림 50) Hexcopy 실행화면

04040404. . . . WINDEWINDEWINDEWINDE

3333 부부부부 파일파일파일파일 시스템시스템시스템시스템 분석하기분석하기분석하기분석하기

1111 장장장장 파일파일파일파일 시스템시스템시스템시스템 이해하기이해하기이해하기이해하기

지금까지 디스크의 구조도 보고, 디스크를 분석해볼 툴도 보았다.

이제는 본격적으로 파일 시스템의 이론을 공부해 보도록 하겠다.

01010101. FAT. FAT. FAT. FAT 의의의의 역사역사역사역사 ( http://helloec.net/network/FAT.htm ( http://helloec.net/network/FAT.htm ( http://helloec.net/network/FAT.htm ( http://helloec.net/network/FAT.htm 참고참고참고참고 ) ) ) )

FAT 에 의한 관리방식은 1977 년에 등장한 마이크로소프트 Disk

Basic 시대부터이다.

그 당시 랜덤 액세스 미디어로는 160KB 의 5 인치 플로피디스크밖에

없었다.

'MS-DOS 1.25'가 등장했을 때는 디스크 베이직과의 파일호환성을

유지하기 위해 파일시스템으로 FAT 가 사용되었다.

이 MS-DOS 에서는 FAT 엔트리가 12 비트로 확장되어, 최대

128KB 까지의 파일시스템을 구축할 수 있게 되었다.

'MS-DOS 2.11'이 등장할 때까지 10MB 정도의 하드디스크밖에 없고,

또 매우 고가의 디스크였기 때문에 FAT12 로도 충분히 여유가 있었다.

그러나 'MS-DOS 3.1'이 등장할 때에는 100MB 정도의 하드디스크가

등장하게 되었고, FAT12 에 추가된 형태로 FAT16 지원이 추가되었다.

그 후 'MS-DOS 4.x'에서는 엔트리를 16 비트로 확대하고 최대

2GB 까지의 하드디스크를 지원했습니다. 이것이 그대로 윈도 95 로

이어진 것이다.

마지막으로 32 비트로 확대하여 최대 2TB 까지 지원 가능하게 된

것이다.

02020202. . . . FATFATFATFAT12121212

플로피디스크에서 사용되고있는 파일시스템이며 디스켓공간에

2^12(2 의 12 승)=4096 개의 섹터(파일저장의 최소공간)를 가질 수

있으며 최대용량은 4096×512 byte(1 개섹터의 용량)=약 2MB 이며

섹터 8 개(4096byte)를 하나의 최소저장공간으로 묶을 경우

4096×4096= 16,777,216 byte 약 16MB 까지 최대 저장용량으로

지정할 수 있다.

FAT12 방식을 사용하는 플로피디스켓은 저장용량이 작기 때문에

하드디스크와는 달리 공간을 나눌 필요가 없으므로 MBR(Master Boot

Record)영역이 필요하지 않다.

부트레코드

FAT1

FAT2

Root Directory

데이터 저장영역

표 6) FAT12 구조

03030303. . . . FATFATFATFAT16161616

MS-DOS 에서 사용하는 파일시스템으로 윈도우 95 ORIGINAL

버전까지 사용된 파일시스템이다.

FAT16 방식은 2^16(2 의 16 승)=65536 개의 섹터를 가질 수

있으므로 65536×512 byte = 33,554,432byte, 약 30MB 를 하나의

방(파티션)으로 만들 수 있다. 여기에서 섹터를 최대한 64 개를 하나로

묶어서(=클러스터) 사용하면 65536×64×512=약 2GB 의 공간을

하나의 파티션으로 사용 할 수 있다.

만일 10GB 용량의 하드디스크를 가지고 있다면 파티션을 5 개로

분할해야만 전체공간을 모두 사용 할 수 있고

클러스터는 64×512 byte=32KB 가 되고 파일 한 개는 무조건

클러스터 하나 이상의 공간을 하기 때문에 1KB 크기를 가진 파일도

32KB 공간 한 개를 차지하며 나머지 31KB 는 낭비되는 공간으로

남게되며 남은 공간에는 다른 파일을 함께 넣을 수 없게 약속되어

있어서 FAT16 방식의 최대 단점은 2GB 마다 파티션을 나누어야

한다는 점과 공간의 낭비가 매우 심하다는 것이다.

04040404. . . . 16161616 비트비트비트비트 FAT FAT FAT FAT 의의의의 한계한계한계한계

윈도 95 의 등장 이래, 응용프로그램이 사용하는 파일수의 증가와

데이터의 거대화가 급속히 진행되고, 하드디스크의 용량도 점점

증가했다 결국 새로 2GB 이하의 하드디스크를 찾는 것 자체가

어려워지게 된다. FAT16 을 2 이용해 대용량 하드디스크를 이용하려면

2GB 마다 파티션을 분할해, 최대 4 개까지 동시에 액세스할 수 있는

파티션을 만들 수 있다. 결국 최대 8GB 가 사실상의 한계 용량이 된다.

이처럼 하드디스크의 용량이 OS 의 관리 가능 범위를 초월하는

비정상적인 상태를 맞게 되자, 사태는 긴급한 해결을 요구하게 된다.

05050505. . . . FATFATFATFAT16161616 에서에서에서에서 FAT FAT FAT FAT32323232 로로로로

FAT 를 32 비트화 하려면 단순히 FAT 엔트리를 32 비트화하는

것만으로는 안된다. FAT 파일 시스템에 관한 데이터 구조의 변경,

API 의 추가와 확장 및 유틸리티 등의 FAT32 지원이 필요한다.. 또

FAT 의 크기가 커지는 데 따라 발생하는 문제도 처리해야 한다..

오래된 디스크 유틸리티를 사용할 경우, FAT32 에서 포맷된

하드디스크를 이용할 수 없게 되므로 주의해야 한다..

FAT16 의 디스크 크기는 512KB 에서 8KB, 2GB 의 디스크에서

32KB 가 되고 있다. FAT16 에서 2GB 의 하드를 이용하는 경우,

1KB 의 파일을 만들 때 32KB 의 용량을 사용하게 된다.

한편, FAT32 에서는 8GB 의 드라이브에서도 4KB 클러스터가

이용되고, 마찬가지로 1B 의 파일을 만들 때 4KB 클러스터가

이용된다. 이러한 이유로 FAT32 를 사용하게 되면 FAT16 을 사용할

때보다 일반적인 디스크 용량의 이용효율이 10~20 퍼센트 정보

향상된다고 알려지고 있다.

FAT16 의 확장, VFAT VFAT 파일 시스템은 FAT 파일 시스템이

확장된 것으로 Windows 95 와 함께 도입되어 많이 알려진 파일

시스템이다. 이 파일 시스템은 FAT 와 호환되며 FAT 보다 제한이

적어 파일 이름도 최고 255 자까지 만들 수 있고 공백이나 여러 개의

구두점도 포함할 수 있다. 대소문자는 지정한 대로 보존되기는 하나

구별하지는 않는다.

VFAT 로 긴 파일 이름을 만들 때 파일 시스템은 사실 두 가지 파일

이름을 만든다. 하나는 실제 파일 이름이고, Windows 95, Windows 98,

Windows NT 4.0 이상 버전에서 나타난다. 다른 파일 이름은 MS-

DOS 용 파일 이름으로 긴 파일 이름의 단축형이다. MS-DOS 용 파일

이름은 실제 긴 파일 이름의 공백 문자를 제외한 처음 6 글자와

틸드(~) 그리고 숫자로 이루어져 있다. 예를 들면

Onlinewithyounet.txt 의 MS-DOS 용 파일 이름은

ONLINE~1.txt 이다. 이러한 파일 이름을 만드는 방식은 뜻하지 않은

결과를 가져올 수 있다. VFAT 로 긴 파일 이름을 만들 때 MS-

DOS 용 이름으로 디렉터리 항목을 하나 사용하고 파일 이름

13 자마다 항목을 하나씩 사용한다.

이론상으로 보면 긴 파일 이름 하나가 최고 21 개의 디렉터리 항목을

차지할 수 있다. 루트 디렉터리는 512 개의 파일을 포함할 수 있지만,

루트 디렉터리에 255 자의 가장 긴 파일 이름을 만들면 포함할 수

있는 파일 수가 24 개로 줄어든다. 따라서 루트 디렉터리에는

가능하면 긴 파일 이름을 사용하지 않는 것이 좋다 다른 디렉터리는

이러한 제한 사항의 영향을 받지 않는다. 이 글에서 VFAT 를

언급하는 것에 대해 의아할 수도 있지만 현재 FAT 보다 VFAT 가 더

일반적으로 사용되고 있다. 그러나 위에 언급한 차이점 외에 VFAT

사용에도 제한 사항이 있다. Windows NT 에서 분할 영역을 FAT 로

포맷하면 VFAT 로 포맷된다. Windows NT 4.0 에서 FAT 분할 영역을

사용하려면 MS-DOS 같은 다른 운영 체제로 분할 영역을 포맷해야

한다..

06060606. . . . FATFATFATFAT32323232

윈도우 95 OSR2 버전부터 채택된 FAT32 는 FAT16 방식의 한계를

극복하기 위해 2^32= 약 4GB (2 의 32 승)개의 섹터나 클러스터 수를

지정 할 수 있다. 한섹터(512byte)를 한 클러스터로 지정해서

사용하더라도 한 파티션의 최대양을 4,294,967,296×512byte=

2,199,023,255,552byte , 2TB(2000GB)까지 지정 할 수 있으며

클러스터 공간의 낭비도 최소한으로 줄일 수 있다.

FAT32 방식의 주소지정방식은 2^28(2 의 28 승)(실제

주소지정가능량)×2^4(2 의 4 승)(예비)으로 이루어진다.

단점으로는 클러스터를 이용하는 방식은 읽거나 기록할 때 FAT 에

가서 위치정보를 확인해서 실제 위치로 이동하는 방식이므로 ACCESS

시간이 많이 걸리며 FAT 영역이 손상되면 실제의 정상적인 파일도

사용을 못하고 여러 개의 클러스터로 구성된 용량이 큰 파일은 각

클러스터 간의 링크가 손상되어도 해당파일을 사용 할 수 없게 되는

단점이 있다. 또한 각 디렉토리나 파일에 사용권한을 줄 수가

없으므로 여럿이 함께 사용하는 운영체제에는 부적 절한

파일시스템이다.

장점은 호환성과 간단한 파일 시스템 구조로 파악이 쉽다는 것이다.

07070707. . . . 빈공간빈공간빈공간빈공간 재계산재계산재계산재계산 억제억제억제억제

지금까지의 FAT 시스템에서는 디스크의 빈 공간을 계산하려면

FAT 를 모두 읽어 미사용 부분의 계산을 처리했다 그러나

FAT32 에서 2GB 의 드라이브를 취급하는 경우, 이 데이터를 읽어내게

되면, 약 2MB 정도의 분량을 읽게 된다. 이 문제를 해결하기 위해 빈

공간을 보존하기 위한 'FSINFO'라고 불리는 영역이 새로 추가되었다

파일을 읽고 쓸 때마다 이 수치를 갱신해 빈 공간의 용량을 계산할

때에도 고속으로 처리할 수 있게 되었다 그러나 FSINFO 와 실제의 빈

공간의 용량의 차이가 없도록 해야 한다.. 특히 윈도 95 나 98 의

셧다운이 제대로 이루어지지 않으면 FAT 와 FSINFO 에 장애가

발생한다.. 이를 해결하기 위해 윈도의 비정상 종료시 다음 시작에

스캔디스크가 실행되는 것이다.

08080808. . . . 파일파일파일파일 저장의저장의저장의저장의 고속화고속화고속화고속화

FSINFO 에는 파일의 최종저장 섹터번호까지 저장되도록 되어 있어,

추가로 저장할 경우에도 FAT 의 처음부터 최종 저장번호까지 읽지

않고 그대로 추가 저장할 수 있다. 이것으로 디스크 액세스의

최소화를 실현하고, 디스크 캐시 메모리를 유효하게 이용할 수 있게

된다.

09090909. . . . 신뢰성과신뢰성과신뢰성과신뢰성과 효율성효율성효율성효율성 향상향상향상향상

FAT32 에서는 FAT16 에 비해 신뢰성 향상도 꾀하고 있다. FAT16

시스템에서는 FAT 영역을 2 개 만들어두고, 보통의 경우에는 제 1

FAT 를 참조한다.. 만약 제 1 FAT 가 손상되어 읽을 수 없게 될 때는

몇 번 정도 재시도를 반복하고 그대로 안되면 예비로 있는 제 2

FAT 에 액세스한다.. FAT32 에서는 FAT 영역이 늘어나기 때문에

FAT 에 불량이 발생할 확률이 FAT16 에 비해 크게 높아졌다 이

문제에 대해 2 서는 장애가 발생한 FAT 부분만을 예비 FAT 에서

적극적으로 이용하는 것으로 FAT 에 불량이 발생한 경우에도 처리를

계속할 수 있게 되었다 같은 2GB 의 하드디스크를 사용하는 경우,

FAT16 의 경우는 하나의 클러스터가 32KB, FAT32 의 경우 하나의

클러스터가 4KB 가 된다. 만약 1KB 의 파일이 있을 때 1 클러스터가

소비되므로 28KB 의 사용 용량의 차이가 발생한다.. 만약 1KB 의

파일이 100 개 있을 때, FAT16 은 3.2M 를 FAT32 는 400KB 의

용량을 소비하게 되므로 FAT32 는 FAT16 보다 하드디스크의 사용

효율이 8 배나 높아지게 된다

2222 장장장장 FAT FAT FAT FAT 분석하기분석하기분석하기분석하기

00000000. . . . 용어용어용어용어 정의정의정의정의

FAT 가 공개 안 되어 있는 반면, 많은 사람들이 비교 분석하고

응용프로그램까지 내놓는 것은 사실이다.

그러다 보니, 저마다 용어 해석이 틀린 부분이 있다.

물론, MS 사에서 만들어서 그것의 용어를 따라 가는 것이

정석이겠지만, 참조 문헌이나 참조 웹사이트에서 쓰이는 용어로

정의하고자 한다.

실제로도 실무에서 쓰는 용어는 간략화 된 용어를 주로 쓴다.

MBR : Master Boot Record , Master Sector , Master Boot Sector

BR : Boot Record , BPB , Boot Sector

RDE : Root Directory Entry , Root Directory , Root Sector , Root

BPB : BIOS Parameter Block

FAT : File Allocation Table

01010101. . . . FAT FAT FAT FAT 구조구조구조구조 ( File A ( File A ( File A ( File Allocation Table ) llocation Table ) llocation Table ) llocation Table )

하드디스크가 맨 처음 공장에서 출하된 다음 맨 처음 format 을

한다는 사실은 일반 PC user 들이 아는 사실일 것이다.

왜 맨 처음에는 format 을 할까요?

그것은 하드디스크가 0xFF 의 값으로 처음부터 끝 섹터까지 쓰여져

있기 때문입니다.

데이터가 들어갈 장소는 있지만, 체계적으로 OS 와 유기적으로 동작될

어떠한 연관이 없기 때문에 초기화 작업을 해 주는 것입니다.

그림 24 를 보면 우리가 format 을 하게 되면, 사용자 데이터에는

아무것도 없지만, MBR,BOOT,FAT1,FAT2,ROOT 까지를 정해주게

됩니다.

즉, 사용자 데이터까지 들어갈 장소 및 틀을 만들어 주는 것입니다.

도서관이 하드디스크라면, 문서가 들어갈 문서장을 만들어 주는 것이

바로 format 입니다.

MBR(Master Boot Record) : 물리적 부트 섹터로 하드의 물리적인

0 번섹터입니다.

물리적물리적물리적물리적 부트섹터부트섹터부트섹터부트섹터 : 디스크의 전체 용량과 파티션 정보 등을 저장

논리적논리적논리적논리적 부트섹터부트섹터부트섹터부트섹터 : 파티션 정보와 FAT 용량 정보를 저장

FATFATFATFAT1111 : 사용자 데이터의 저장위치 정보를 저장

FATFATFATFAT2222 : FAT1 백업

Root Root Root Root 디렉토리디렉토리디렉토리디렉토리 : Root 디렉토리 파일 번지를 저장

사용자사용자사용자사용자 데이터데이터데이터데이터 : 사용자가 만드는 모든 파일

FATFATFATFAT: File Allocation Table

파티션을 사용하는 경우는 논리적 부트섹터부터 사용자 데이터까지

반복하여 구성됨

그림 51) FAT 구조 ( 자료 출처 www.finaldata.co.kr )

명칭 설명 및 의미

MBR ( Master Boot

Record )

물리섹터 0 번에 위치,주로 파티션테이블과 확장 read 가능한지,

부트가능한지를 판단함.

Partition Entry ( Partition

Table )

IDE 형식의 windows 계열의 하드에는 네 개의 파티션을 나눌수

있다.

BR ( Boot Record )

물리섹터 63 번에 위치, IO.sys 를 찾아 load 하고, 각각의

부트정보가 있다.

FAT1( File Allocation

Table )

파일의 링크된 정보 테이블이 있다.

FAT2(File Allocation

Table mirror )

FAT1 의 backup.

RDE( Root Directory

Entry )

Root Directory

Data 실제 Data

표 7) FAT 의 구조

02020202. . . . MBRMBRMBRMBR 의의의의 구조구조구조구조

Offset 크기(byte) 설명

00h 다양하다. Executable code

1BEh 16 첫 번째 파티션 테이블 entry

1CEh 16 두 번째 파티션 테이블 entry

1DEh 16 세 번째 파티션 테이블 entry

1EEh 16 네 번째 파티션 테이블 entry

1FEh 2 executable marker(AA55h)

표 8) MBR 구조

MBR 은 하드디스크의 첫 번째 물리적 섹터에 있고, 두 가지 파트로

나눠진다.

* some executable code

* the partition table

executable code 는 실행 시간에 RAM 에 load 되고, 실행된다.

executable code 의 하는 기능은 어떤 파티션이 자신의 boot

sector 를 load 하고 실행하기 위해 부팅할 수 있는 파티션인지를

결정한다. boot sector 는 파티션의 첫 번째 섹트에 있다. 파티션은

boot sector 에서 시작하고, 다른 boot sector 앞에서

끝난다.(실제적으로 boot sector 또는 다른 partition table) MBR 의

code 부분은 fdisk /mbr 이 사용되었을 때, 다시 새롭게 되어진다.

FDISK /MBR 을 사용하는 것은 장점보다는 더 많은 단점을 가질 수

있다. 예를 들어서, 어떤 하드 드라이버는 커다란 드라이버를 다루기

위해서 drive overlay software 를 사용할 필요가 있다. 그런

드라이버에서, MBR 에 loader code 는 FDISK /MBR 이 거기에 넣는

표준 코드가 아니다. 그와 같은 경우에, drive overlay software 의

loader code 부분을 깨뜨릴지도 모르고, 드라이버가 이후에 접근할 수

없게 될 수도 있다. 즉, 파티션 테이블의 정보가 disk overlay

software 를 가지는 것과 같지 않다. 파티션 테이블 자체는 하드

디스크의 첫 번째 섹터의 offset 1BEh 에 있다. 각 entry 는

16 바이트로 되어 있다.

00003333. . . . Partition TablePartition TablePartition TablePartition Table

파티션 table entry 는 16 바이트 길이다.

Offset 크기 설명

00h 1byte

Partition State

00h = 비 활성 파티션

80h = Boot 파티션

01h 1byte Begin of partition: Head

02h 1word Begin of partition: Cylinder - Sector

04h 1byte 파티션 종류 ( 표 10 참조 )

05h 1byte End of partition: Head

06h 1word End of partition: Cylinder -Sector

08h 4bytes Number of sectors between the MBR and the 1st sector of the partition

0Ch 4bytes Number of sectors in the partition

표 9) Partition Table Entry 구조

Cylinder - Sector encoding

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Cylinder bits 7 to 0 9&8 Sector bit 5 to 0

957Fh 표현

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

95h 7Fh

1 0 0 1 0 1 0 1 0 1 1 1 1 1 1 1

Cylinder bits 7 to 0 9&8 Sector bits 5 to 0

0110010101 = Cylinder 405 111111 = Sector 63

표 10) CHS 값 format

값 설명

00H 사용안함

01H 12bit FAT

04H 16bit FAT, 32MB 보다 작은 파티션에서 쓰임.

05H 확장 MS-DOS 파티션

06H 16bit FAT, 32MB 보다 크거나 같은 파티션에서 쓰임.

0BH 32bit FAT, 2047GB 까지의 파티션.

0CH 0BH 와 같은 파티션, 그러나, 확장 INT13 LBA 를 사용한다.

0EH 06H 와 같은 파티션, 그러나, 확장 INT13 LBA 를 사용한다.

0FH 05H 와 같은 파티션, 그러나, 확장 INT13 LBA 를 사용한다.

83H Linux

82H Linux swap

표 11) 파티션의 종류

첫 번째 파티션은 Primary partition 이고, 다른 파티션들은 Extended

partition 에 저장되어져 있다. 파티션 테이블의 첫 번째 레코드는

Primary 파티션을 보여준다. partition table 의 두 번째 레코드는 전체

Extended partition 이 있는 곳을 보여준다. 더 많은 파티션을 읽기

위해서, Extended partition 이 시작하는 위치로 가서, MBR 처럼 첫

번째 섹터를 읽는다. 그리고 파티션 테이블에 첫 번째 엔트리는 다음

파티션을 나타낸다. 만약 더 많은 파티션이 있다면, 또 다른 Extended

partition 이 있을 것이고, 이전처럼 똑같은 과정을 수행하면서, 전체

파티션을 읽을 수 있다.

MBR 은 Master Boot Record 의 약자로, x86 계열의 컴퓨터가 부트

되는 하드디스크의 첫 번째 1 sector(512Byte)를 뜻한다.

그림 24 와 같이 존재하며, 첫 446byte 는 각각의 부트를 위한

코드를 메모리에 Load 시킨다.

그리고, 파티션 1,2,3,4 는 기본적인 Primary 파티션으로서 파티션

entry 를 나타낸다.

즉, 파티션이 1 개 이면, 파티션 1 에만 값이 존재합니다.

마지막으로 0xAA55 는 (혹자는 매직넘버라고도 함.) Bios 에서

MBR 임을 확인하는 sign code 이다.

각각의 파티션 entry 는 그림 25 의 구조 처럼 되어 있다.

16byte 로 되어 있고, 각각의 의미는 그림과 같다.

Boot 는 부트할 파티션인지를 나타낸다.

‘ 80 ’ 이면 Boot 파티션이고, ‘ 00 ’ 이면 부트 파티션이 아니다.

HD 는 시작 Head 번호를 나타낸다. 뒤의 HD 는 끝 Head 번호를

나타낸다.

SEC CYL 은 부트섹터의 섹터와 실린더 수를 나타내고, 뒤의 SEC

CYL 은 끝을 나타낸다.

SYS 는 파티션의 종류를 나타낸다.

안에 써있는 값에 따라, 그 파티션이 어떤 식으로 이루어 질지가

결정된다.

그림 2 에서 08H offset 되어 있는 4byte 는 그 파티션의 상대

섹터수를 나타낸다. 만일 하나의 파티션이고(MS-

DOS 에서) , BR(Boot Record)가 63 번 섹터에 있다면, 이 값은 3F

00 00 00 이 될 것이다. ( 00 00 00 3F = 63 ) 또, 그 다음 4byte 는

파티션의 총 섹터수를 나타낸다.

즉, 파티션의 시작섹터와 총 크기를 나타내서, 각각의 파티션 범위가

어디까지 인지를 알수가 있다.

실례를 들어 보자,

지금 512byte 를 읽어 왔는데, 446byte 는 떼고, 첫 번째 파티션

테이블의 값을 가져왔다고 가정하자.

1B0H : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 01

1C0H : 01 00 0B FE 3F FF 3F 00 00 00 C1 C0 3E 00 00 00

80 은 부트 가능한 파티션이고, 01 01 00 은 첫 번째 01( 0000 0001

(2) )은 파티션 시작 헤드 번호 이므로, 1 번 헤드, 두 번째 01 에서

( 00 0001(2) ) 앞의 두 bit 를 뺀 값이 시작 섹터 번호 이므로, 1 번

섹터 , 세 번째 00 는 실린더의 번호이므로, 0 실린더이다.

그림 52) 파티션 엔트리구조

다음 ' 0B ' 는 파티션 종류로 , 32Bit FAT 이고, 2047GB 까지의

범위를 나타낸다.

다음 ‘ FE 3F FF ' 는 헤드 FE , 섹터 3F , 실린더 FF 를 나타낸다.

즉, 실린더 헤드 섹터를 곱하면, 4096512 섹터가 되고, 1 섹터당

512byte 라고 한다면, 2,089,221,020 byte 가 된다. 즉, 2GB 의

하드용량이 되는 것이다.

다음의 4byte 인 ‘ 3f 00 00 00 ' 은 파티션의 시작 섹터를

나타내고, ’ c1 c0 3e 00 ' 은 총 섹터수를 나타낸다.

‘ 00 3e c0 c1 = 4112577 sector ' 1sector 를 512byte 라고 한다면,

2,105,639,424 byte 가 된다. 실제적으로 CHS ( cylinder head

sector ) 모드로 계산한 값과 LBA 모드로 계산한 값은 차이가 있다.

Physical Sector: Absolute Sector 0

00000000: 33 C0 8E D0 BC 00 7C FB - 50 07 50 1F FC BE 1B 7C 3 핉劇.|? P

00000010: BF 1B 06 50 57 B9 E5 01 - F3 A4 CB BE BE 07 B1 04 ¿ PW 밧 懲鱇

00000020: 38 2C 7C 09 75 15 83 C6 - 10 E2 F5 CD 18 8B 14 8B 8,| u 꺠 醇 Í

00000030: EE 83 C6 10 49 74 16 38 - 2C 74 F6 BE 10 07 4E AC ?Æ It 8,t淄

00000040: 3C 00 74 FA BB 07 00 B4 - 0E CD 10 EB F2 89 46 25 <.t荇 .´ Í

00000050: 96 8A 46 04 B4 06 3C 0E - 74 11 B4 0B 3C 0C 74 05 뻿 F ´ < t

00000060: 3A C4 75 2B 40 C6 46 25 - 06 75 24 BB AA 55 50 B4 :훧+@힓% u$빽 UP

00000070: 41 CD 13 58 72 16 81 FB - 55 AA 75 10 F6 C1 01 74 AÍ Xr 괎 U 챬

00000080: 0B 8A E0 88 56 24 C7 06 - A1 06 EB 1E 88 66 04 BF 듺늊$Ç ¡

00000090: 0A 00 B8 01 02 8B DC 33 - C9 83 FF 05 7F 03 8B 4E .¸ 뗜 3?ÿ

000000A0: 25 03 4E 02 CD 13 72 29 - BE 46 07 81 3E FE 7D 55 % N Í r)퐽

000000B0: AA 74 5A 83 EF 05 7F DA - 85 F6 75 83 BE 27 07 EB 챫 Z 껓 ??꺘'

000000C0: 8A 98 91 52 99 03 46 08 - 13 56 0A E8 12 00 5A EB 뒛멢 Fè .Z

000000D0: D5 4F 74 E4 33 C0 CD 13 - EB B8 00 00 80 19 25 14 ?t?익 釉..€

000000E0: 56 33 F6 56 56 52 50 06 - 53 51 BE 10 00 56 8B F4 V3?VRP SQ¾ .

000000F0: 50 52 B8 00 42 8A 56 24 - CD 13 5A 58 8D 64 10 72 PR?B 둞$Í ZX 뛡

00000100: 0A 40 75 01 42 80 C7 02 - E2 F7 F8 5E C3 EB 74 49 @u B 順?취

00000110: 6E 76 61 6C 69 64 20 70 - 61 72 74 69 74 69 6F 6E nvalid partition

00000120: 20 74 61 62 6C 65 00 45 - 72 72 6F 72 20 6C 6F 61 table.Error loa

00000130: 64 69 6E 67 20 6F 70 65 - 72 61 74 69 6E 67 20 73 ding operating s

00000140: 79 73 74 65 6D 00 4D 69 - 73 73 69 6E 67 20 6F 70 ystem.Missing op

00000150: 65 72 61 74 69 6E 67 20 - 73 79 73 74 65 6D 00 00 erating system..

00000160: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................

00000170: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................

00000180: 00 00 00 8B FC 1E 57 8B - F5 CB 00 00 00 00 00 00 ...뗽 W 뗶?....

00000190: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................

000001A0: 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 01 ..............€

000001C0: 01 00 0C FE FF FF 3F 00 - 00 00 FC 8A 38 01 00 00 . ? ...?8

000001D0: C1 FF 0F FE FF FF 3B 8B - 38 01 AD E5 69 03 00 00 ? ? ? i

000001E0: 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ª

표 12) MBR 을 읽어 온 값

위의 hex 값으로 된 값들을 deassemble 해 보면

아래와 같은 코드가 나온다.

MBR71.ASM

;-------------------------------------------------------------------

-----------

; DOS 7.1 MastBootSector(파티션섹터) 소스(영어)

; EXE 모델로 컴파일하여 Offset 200h 부터 떼어 내면 512Byte 의 코드가 나옴

;-------------------------------------------------------------------

-----------

locals @@

.model small,pascal

;MS-DOS 에서 사용하는 파티션의 종류

PART_UNKNOWN equ 00h ;Unknown

PART_DOS2_FAT equ 01h ;12-bit FAT

PART_DOS3_FAT equ 04h ;16-bit FAT. Partition smaller than 32MB

PART_EXTENDED equ 05h ;Extended MS-DOS Partition

PART_DOS4_FAT equ 06h ;16-bit FAT. Partition larger than or equal to

32MB

PART_DOS32 equ 0Bh ;32-bit FAT. Partition up to 2047GB

PART_DOS32X equ 0Ch ;Same as PART_DOS32(0Bh), but uses Logical Block

Address Int 13h extensions

PART_DOSX13 equ 0Eh ;Same as PART_DOS4_FAT(06h), but uses Logical

Block Address Int 13h extensions

PART_DOSX13X equ 0Fh ;Same as PART_EXTENDED(05h), but uses

Logical Block Address Int 13h extensions

s_partition struc

Part_BootInd db ?

Part_FirstHead db ?

Part_FirstSector db ?

Part_FirstTrack db ?

Part_FileSystem db ? ;위의 그 종류를 정의함

Part_LastHead db ?

Part_LastSector db ?

Part_LastTrack db ?

Part_StartSector dd ?

Part_NumSectors dd ?

s_partition ends

SegA segment byte public

assume cs:SegA , ds:SegA

;-------------------------------------------------------------------

-----------

; 하드디스크 마스터 부트섹터의 내용

; 처음 Boot 때 0000:7C00 에 읽혀저 실행함

;-------------------------------------------------------------------

-----------

MastBootProc proc far

xor ax,ax

mov ss,ax

mov sp,7C00h

sti

push ax

pop es ;es<-0

push ax

pop ds ;ds<-0

cld

mov si,(@@061B-MastBootProc)+7C00h

mov di,(@@061B-MastBootProc)+0600h

push ax

push di

mov cx,MastBootEnd-@@061B

rep movsb

retf ;cx<-0

@@061B: mov si,(PartitionTable-MastBootProc)+600h

mov cl,4

@@0620: cmp [si],ch ;ch=0

jl @@062D

jnz @@063B

add si,10h

loop @@0620

int 18h

@@062D: mov dx,[si] ;dl<-80h, dh<-파티션시작 면번호

mov bp,si ;bp<-Boot 파티션 Tab 의 Pointer

@@0631: add si,10h

dec cx

jz @@064D ;Ok 계속

cmp [si],ch

je @@0631

;Boot Partition 이 여러개이거나, 또는 파티션 첫 Byte 가 00h 도 아니고

80h 도 아닌경우

@@063B: mov si,(InvalidPartiTab-MastBootProc)+0600h+1

@@063E: dec si

@@063F: lodsb

cmp al,0

je @@063E

mov bx,7

mov ah,0Eh ;Disp char al, teletype mode

int 10h

@@064B: jmp short @@063F

;---------------유효한 Boot 파티션을 찾음--------------------------------

-------

;si<-4 개의 파티션 다음위치

;ax<-0

;bp<-Boot 파티션 Tab 의 Pointer

;dl<-Boot Drive No (80h-)

;dh<-파티션시작 면번호

@@064D: mov [bp+25h],ax ;=0

xchg ax,si ;si<-0

mov al,[bp+4] ;파티션종류

mov ah,PART_DOS4_FAT ;LBA Mode 를 지원않는데 Large 모드

Int13 함수가 없는경우 대치할 파티션번호

cmp al,PART_DOSX13 ;Same PART_DOS4_FAT, Not LBA

je @@066B

mov ah,PART_DOS32 ;32-bit FAT

cmp al,PART_DOS32X

je @@0665

cmp al,ah

jne @@068F ;PART_DOS32 이 아닌경우

inc ax ;zf<-0

;종류가 PART_DOS32, PART_DOS32X 이면 백업본이 있음

@@0665: mov byte ptr [bp+25h],6 ;Boot Record 백업본이 있는 위치

jnz @@068F ;PART_DOS32 인 경우

;LBA 를 지원하지 않는 경우(PART_DOSX13, PART_DOS32X)

;ah<-Int13 확장이 안된 경우 대치할 파티션 Type

;al<-원래 파티션 Type

@@066B: mov bx,55AAh

push ax

mov ah,41h ;dl(80h-FFh)의 드라이버가 설치 되었는가 체크

int 13h

pop ax

jc @@068C

cmp bx,0AA55h

jne @@068C

test cl,1 ;Extended disk access functions (AH=42h-

44h,47h,48h) supported

jz @@068C

mov ah,al

mov [bp+24h],dl ;ReadLongSector()에서 쓸려고

mov word ptr ds:(@@06A1-MastBootProc)+600h,1EEBh

jmp short @@06C1 ;jmp short @@06C1 명령을 넣음

@@068C: mov [bp+4],ah

@@068F: mov di,10 ;오류발생시 반복 Counter

@@0692: mov ax,201h ;Read sectors to memory es:bx

mov bx,sp ;bx<-7C00h

xor cx,cx

cmp di,5

jg @@06A1

mov cx,[bp+25h]

@@06A1: add cx,[bp+2] ;ch<-Cyl Low 8Bit, cl 의 Bit 0-5:Sct, cl 의

Bit 6-7:Cyl High 2Bit

int 13h

@@06A6: jc @@06D1

mov si,(MissingOSMsg-MastBootProc)+600h

cmp word ptr ds:(ValidCheckID-MastBootProc)+7C00h,0AA55h

je jGoBootRcd

sub di,5

jg @@0692

@@06B8: test si,si

jnz @@063F

mov si,(OSLoadErrMsg-MastBootProc)+600h

jmp short @@064B

;LBA 를 지원하지 않고(PART_DOSX13, PART_DOS32X), 확장

Int13 함수가 있으면

;@@06A1 에서 여기로 날라옴

;cx<-Boot 섹터의 Offset, 0 이나면 백업본위치인 6

@@06C1: cbw

xchg ax,cx ;cx->현재 파티션 종류

push dx

cwd ;eax->백업 부트섹터

add ax,[bp+8] ;이파티션의 시작위치, 0 으로 시작하는 HDD

섹터번호

adc dx,[bp+0Ah]

call ReadLongSector

pop dx

jmp short @@06A6

@@06D1: dec di

jz @@06B8

xor ax,ax ;Reset disk, al=return status

int 13h

jmp short @@0692

MastBootProc endp

db 0,0, 81h, 54h, 44h, 14h ;06DA

;-------------------------------------------------------------------

-----------

;07E0 cx<-읽을 섹터수

; dx:ax<-읽을 섹터번호(하드의 모든섹터에 0 부터 번호를 매긴)

; es:bx<-전송할 버퍼

;-------------------------------------------------------------------

-----------

ReadLongSector proc near

uses si

;Disk Address Packet 의 구조

;Offset Size Description

; 00h BYTE 10h (size of packet)

; 01h BYTE reserved (0)

; 02h WORD 전송할 block 수 (max 007Fh for Phoenix EDD)

; 04h DWORD 전송할 버퍼

; 08h QWORD starting absolute block number

; Non-LBA device 를 위해 아래의 방식으로 계산한 값

;(Cylinder*NumHeads*SectorPerTrack +

SelectedHead*SectorPerTrack + SelectedSector -1

xor si,si ;si=0

push si si dx ax ;읽을 섹터번호

push es bx ;전송할 버퍼

push cx

mov si,10h

push si

mov si,sp

push ax dx

mov ax,4200h

mov dl,[bp+24h]

int 13h ;ds:si<- disk address packet

pop dx ax

lea sp,[si+10h]

jc @@Exit

;다음 읽을 위치 계산

@@100: inc ax

jnz @@200

inc dx

@@200: add bh,2

loop @@100

clc

@@Exit: ret

ReadLongSector endp

jGoBootRcd: jmp short GoBootRcd

InvalidPartiTab db 'Invalid partition table',0 ;010F

;파티션 타입이 모르는 종류일 경우

OSLoadErrMsg db 'Error loading operating system',0

;열 번째 읽었을 때 Read Error 가 난 경우

MissingOSMsg db 'Missing operating system',0

;마지막이 AA55h 인 부트 레코드를 10 번 시도해서도 못 읽었을 경우

db 36 dup(0)

GoBootRcd: mov di,sp ;di<-7C00h

push ds

push di

mov si,bp ;si<-지금 Booting 하는 파티션 Table 의 번지

retf

;db 52 dup(0) ;빈공간

org MastBootProc+01BEh

;드라이브, 면, 섹터(2), 실린터(3), 파일시스템, 면, 섹터, 실린터,

절대섹터번호, 총섹터수

;(2) Bit5-0:섹터, Bit7-6:실린더의 상위 2bit(하드일경우)

;(3) 실린더의 하위 8bit

PartitionTable s_partition <80h, 1, 1, 0, PART_DOS32X,7Fh,0FFh,1Fh,

63, 6451137>

s_partition <0,0,0C1h,20h, PART_DOS32X,7Fh,0FFh,35h,

6451200, 177408>

s_partition <>

s_partition <>

ValidCheckID dw 0AA55h

MastBootEnd:

SegA ends

end MastBootProc

위의 소스를 보면 ‘ 갑짜기 웬 assemble 이냐 ’ 라는 분들이 계실

것입니다.

맞습니다.

assemble 입니다. MBR 부분은 512byte 의 작은 부분에 들어가

있어서, 제가 아는 한 asm 으로 작성되어 있는 것으로 알고 있습니다.

물론, C 언어로도 만들 수 있겠지만, 제가 보기엔 asm 이 최적인 것

같습니다.

위의 소스는 필자가 직접 sourcer 나 w32dasm87 , Dasmx 같은

tool 로 deassemble 해서 재구성한 소스입니다.

위의 소스를 정확히 분석해 보려면 몇 가지 준비 과정이 필요하다.

- TASM 컴파일러가 있어야 한다.

- ASM 을 이해해야 한다.

- Disk access 관련 툴이 필요하다. ( DE.exe , Hexcopy )

- deasm 툴이 필요하다. ( Sourcer , w32dasm , dasmx )

- hexedit 와 같은 파일내용을 Hex 값으로 보고 지우는 프로그램이

필요하다.

주석을 적어 놓았기 때문에 한 줄 한 줄에 대한 설명은 하지

않겠습니다.

교학사의 황희융저 MS-DOS assemble 이란 문서와 Micro

XXXXX 란 문서를 보시고, 그외에 assemble 관련 문서를 보시면

위의 소스를 이해하시리라 생각합니다.

위의 소스가 하는 일은 BIOS 가 MBR 을 읽어서 메모리에 올린 다음에

컨트롤이 MBR 로 넘어온 상황에서 부트 파티션을 검색해서 있나

없나를 살피고, 없으면 플로피를 읽는 명령을 내려서 없으면, error

처리를 합니다.

파티션을 검색해서 있으면, 0x80 이라고 지정된 부트 파티션의 첫

섹터(BR)을 읽어서 그쪽으로 컨트롤을 넘깁니다.

대부분 63 번 섹터에 BR 가 존재하는데, 파티션 설정에 따라서 BR 는

바뀔 수 있다.

BR 으로 컨트롤이 넘어가면, BR 은 표 8 과 같은 정보들을 가지고

있습니다.

IO.SYS , MSDOS.SYS 와 같은 시스템 파일을 메모리에 올립니다.

( FAT 일 경우 , NTFS 일 경우에는 다른 파일을 올림 )

또한, BR 에는 파일시스템으로 넘어가기 위한 정보들이 많이 존재

한다.

Bytes per sector : 1 Sector 당 크기를 나타내는 것으로 대부분의

하드는 512 가 된다. MMC 카드나 SMC 그리고, 각종 flash 메모리

카드들은 이부분의 크기가 다를 가능성이 있다.

Reserved sectors at beginning : 이것은 첫 FAT 의 섹터를 가르쳐

준다. 현재 BR 이 63 섹터 이고 begining sector 가 32 라면,

63+32 = 95

95 섹터에 1st FAT 가 존재하게 된다.

그림 25 에서도 봤듯이 MBR+BR+1stFAT+2ndFAT+RDE+DATA

이런 순으로 되어 있기 때문에 각각의 offset 을 알아야 우리가 알려는

DATA 의 내용을 찾을 수 있는 것이다.

1stFAT 를 찾았으면, 2nd FAT 를 찾는 것은 쉽다.

FAT Copies : FAT 개수

Big Sectors Per Fat : FAT 당 섹터수

바로 FAT 수와 FAT 당 섹터수를 알면 표 8 의 예를 들면 2 개의

FAT 가 존재하고, FAT 당 섹터수의 크기가 9992 이므로,

MBR : 0

BR : 63

1st FAT : BR + begining sector = 95

2nd FAT : 1st FAT + FAT 당 섹터수 = 95 + 9992 = 10087

그림 25 와 비교해 보면 RDE 도 금방 유추할 수 있을 것이다.

RDE : 1st FAT + ( FAT 당 섹터수 * FAT 수 ) = 95 + ( 9992*2 ) =

20079

가 될 것이라고 생각할 수 있다.

하지만, 여기서 주의해야 할 점이 있다.

바로 First Cluster of Root 의 값이다.

만일 이것이 표 8 처럼 2 이면, 위의 공식이 맞다.

하지만, 이것이 300 이나 444 같은 값으로 틀리다면 다른 공식이

들어 가야 한다.

First Cluster of Root 은 RDE 가 되는 첫 클러스터라는 뜻이다.

만일 첫 Cluster 가 300 이라고 가정하면,

1st FAT + (FAT 당 섹터수 * FAT 수) + (첫 Root Cluster-2) *

Cluster 당 섹터수

= 95 + ( 9992 *2 ) + ( 300 - 2 )*16 = 24847

이 된다.

위의 공식에서 First Cluster of Root 가 2 면,

95 + (9992 * 2) + ( 2-2 ) * 16 = 20079 가 된다.

즉, 위의 공식이 더 정확한 공식이 되는 것이다.

여기서, 왜 2 를 뺐냐면, 뒤에 FAT 를 분석하면서 얘기하겠지만, 첫

2 개의 Cluster 는 FAT 의 시작을 나타내기 때문이다.

OEM ID: MSWIN4.1

Bytes per sector: 512 512

Sectors per cluster: 16 16

Reserved sectors at beginning: 32 32

FAT Copies: 2 2

Reserved: 0

Reserved: (Unused)

Media descriptor byte: F8 Hex

Sectors per FAT: 0 9992

Sectors per track: 63

Sides: 255

Special hidden sectors: 63

Big total number of sectors: 20482812 20482800

Big Sectors Per Fat: 9992 9992

Number of active Fats: 0

Reserved: (Unused)

Mirrored: Yes

Reserved: (Unused)

File System Ver (major): 0

File System Ver (minor): 0

First Cluster of Root: 2

FS Sector number: 1

(hotlink) Backup Boot Sector: 6

Reserved: (Unused)

Physical drive number: 128

Reserved: (Unused)

Extended Boot Record Signature: 29 Hex

Volume Serial Number: 056A1AF7 Hex

Volume Label: WIN98000

File System ID: FAT32

Signature: AA550000 Hex

표 13) BR ( Boot Record )

Media descriptor byte : F8 은 하드 디스크를 나타내고, F0 는

FDD 를 나타낸다.

Big total number of sectors : 현재 파티션의 총 섹터수를 나타낸다.

Physical drive number : 128 (0x80) 은 드라이브 0 , 0x81 은

드라이브 1 , 0x82 는 드라이브 2 이런식으로 표시가 된다. FDD 는

0x0 이다.

Volume Serial Number : 이것은 하드드라이브( Volume 이라고도

불림 )의 Serial 번호 이다.

이것은 포맷하거나 할때마다 변경될 수도 있고, 또 직접 손으로

작성해 볼수도 있다.

원래는 이것으로 하드디스크 마다 어떤 변별력을 가지려고 했던 것

같으나, 누구든지 쓰고 바꿀수 있기 때문에 변별력을 가지지는 못한다.

Volume Label : 드라이브의 이름이다. 예를 들면, C 드라이브의

이름을 ‘ OSDRV ' 라고 썼다면, 이곳에 그 이름이 나오게 된다.

반대로 이곳에 그 이름을 쓰면, 윈도우즈에서도 이름이 나와야겠지만,

이곳과 함께 RDE 에서도 이름을 바꾸어 주어야 윈도우즈에서도

제대로 된 이름이 나오게 된다.

File System ID : 파일시스템을 나타내는 ID 이다. FAT12 , FAT16 ,

FAT32 , NTFS 와 같은 ID 가 들어 가게된다.

Signature : 0xAA55 가 들어 가는 것은 이 섹터가 BR 임을 나타내

주는 표시이다.

이외에도 BR 섹터 다음 섹터에는 FSINFO 관련 섹터가 들어 간다.

0x1e8 에 4byte 로 남은 Cluster 수가 존재한다.

FAT 가 2 개 존재하는 이유는 실제 DATA 를 맵핑해 놓은 것이

FAT 이기에 만일 FAT 가 망가지거나 뒤엉켜 버리면, 실제

DATA 들의 값들이 무용지물이 되어 버리기 때문에, FAT 는 DATA 를

찾아가는 중요한 지도 이므로, 복사본을 만들어 놓는 것입니다.

만일 첫 번째 지도를 사용하다가 이상하거나, 지워지거나 , 망가져

버리면, 두 번째 지도를 첫 번째 지도에 copy 해서 다시 첫 번째

지도를 가지고 사용합니다.

즉, 두 번째 지도는 backup 을 해 놓은 것이라 할 수 있습니다.

그만큼 FAT 가 깨지거나, 손실될 위험이 많다는 뜻입니다. 요즘에는

안 그렇지만, 예전에는 bad 섹터도 많이 나서, 갑자기 ‘ cluster 손실

error ’ , ‘ link 오류 ’ 등의 메시지가 나오면서 blue 스크린이 나왔던

것이 기억납니다.

FAT 는 Cluster 들이 어떻게 연결되어 있는지를 나타내는 것이기에 이

부분이 끊어지면 그러한 오류들이 나는 것입니다.

이것을 고치는 방법은 MS 의 ‘ Scandisk.exe ' , ' chkdsk.exe '

나 노턴의 ’ NDD ' 등과 같은 프로그램들이 존재합니다.

우리가 손수 만들수도 있습니다.

아마 이 문서의 내용을 다 이해하시고, 이곳에 첨부되어 있는

코드들을 이해하시면 충분히 만들 수 있다고 생각합니다.

FAT 의 첫 번째 바이트를 보면 그 디스크에 있는 타입을 결정할 수

있다. (FAT[0]의 하위 8 비트) 부트 섹터에 BPB 를 넣음으로써 MS-

DOS 에서 미디어의 타입 결정을 대신하게 되었다. (FAT 의 첫 번째

바이트를 보면서 확인했던 것을) 모든 FAT 은 부트 섹터에 BPB 를

가지고 있어야 한다.

BPB_RootEntCnt : FAT12/16 에 대해서, 이 필드는 루트 디렉토리에

32 바이트 디렉토리 엔트리들의 개수를 포함한다. FAT32 에 대해서는

이 필드는 0 으로 설정되고, FAT12/16 에 대해서는 이 값은 항상

32 에 의해서 곱해졌을 때 BPB_BytsPerSec 의 짝수 값으로 된

개수를 나타낸다.

BPB_FATSz16 : 이 값은 one FAT 에 의해서 차지하는 섹터들의

16 비트 개수이다. FAT32 에서 이 값은 0 이다. 그리고

Sector_Per_FAT32 는 FAT 크기의 개수를 포함한다.

Name Offse

t

Siz

e 설명

Jump_Boot 0 3

boot code 로 점프 명령, 두가지 형태를 따른다.

* jmpBoot[0]=0xEB, jmpBoot[1]=0x??,

jmpBoot[2]=0x90

*

jmpBoot[0]=0xE9,jmpBoot[1]=0x??,jmpBoot[2]=0x?

?

0x?? 는 명령에 맞는 8bit 값을 집어 넣어진다.

위의 세 byte 는 Intel x86 절대 점프 번지이다.

Oem_Name 3 8 "MSWIN4.1" 단지 파일 시스템 만든 회사 이름.

Bytes_Per_Sector 11 2 Sector 당 Byte 개수.

512, 1024, 2048, 4096 이 들어 갈 수 있다.

Sector_Per_Clustor 13 1

Cluster 당 Sector 개수.

1, 2, 4, 8, 16, 32, 64, 128 이 들어 갈 수 있다.

Bytes_Per_Sector * Sector_Per_Clustor <

32K(32*1024)

왜냐면, 한 Cluster 의 size 는 32K bytes 보다 작아야

하기 때문이다.

Reserved_Sector_Coun

t 14 2

절대 ‘ 0 ’ 이 되면 안된다.

FAT12, FAT16 에서는 ‘ 1’ , FAT32 에서는 ‘ 32 ’

Number_Of_FATs 16 1

FAT 개수.

기본적으로 ‘ 2 ’

2 개가 있는 이유는 하나가 에러났을 때, 복구하기 위한

수단이다.

Root_Entry_Count 17 2 FAT32 에서는 ‘ 0 ’ 이어야 한다.

FAT16 의 경우는 보통 ‘ 512 ’를 사용한다.

Total_Sector_Fat16 19 2

예전 16bit 전체 sectors 개수.

이곳이 ‘ 0 ’ 이면, Total_Sector_Fat32 는 ‘ 0 ’ 이

아니어야 한다.

Media 21 1

MEDIA 구별.

0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE,

oxFF 가 들어 갈수 있다.

0xF0 : 플로피 디스크

0xF8 : 하드 디스크 ( fixed disk )

Sector_Per_FAT16 22 2 한 FAT 당 sector 개수.

FAT32 에서는 ‘ 0 ’ 이어야 한다.

Sector_Per_Track 24 2 Track 당 sector 개수. ( interrupt 13 이용 )

Number_Of_Heads 26 2 Head 의 개수. ( interrupt 13 이용 )

Hidden_Sector 28 4

FAT 볼륨을 포함하는 파티션의 앞에 있는 숨겨진

섹터들의 수이다. 이 필드는 파티션 되지 않은

media 에 대해서는 항상 0 이다. Hidden sector 개수.

( interrupt 13 이용 )

Total_Sector_Fat32

32 4

전체 sector 개수.

이곳이 ‘ 0 ’ 이면, Total_Sector_Fat16 은 ‘ 0 ’ 이

아니어야 한다.

이 필드는 볼륨에 대해서 새로운 전체 32 비트

섹터들의 수이다. 이 개수는 볼륨의 4 영역에서 모든

섹터들의 수를 포함한다.

표 9 Boot Sector 구조

Name

Offset

(byte)

Size

(byte)

설명

Number_Of_Drive 36 1

드라이브 번호

0x80 : (fixed drive, 하드 디스크 )

0x00 : ( floppy disk )

Reserved1 37 1 Windows NT 에서 예약됨. FAT 에서는 ‘ 0 ’

Boot_Sign 38 1

확장 Boot 사인. ( 0x29 )

이 값은 boot sector 내에 뒤의 3 필드가 있다는 것을

가리킨다.

Volume_ID 39 4

Volume serial number

제거 가능한 media 를 따라가는 볼륨을 지원한다. FAT

파일 시스템 드라이버들이 제거 가능한 드라이버에서

잘못된 디스크가 입력된 것을 찾는 것을 허용한다. 이

ID 는 현재 날짜, 시간과 32 비트 값을 결합시키는

것에 의해서 생성된다.

Volume_Label 43 11

Volume Label

루트 디렉토리에 기록된 11 바이트의 볼륨 레이블과

일치한다.

Type_Of_FileSystem 54 8 FAT12, FAT16, FAT 를 나타냄.

offset 36 번에서 시작하는 FAT12 와 FAT16 구조

offset 36 번에서 시작하는 FAT12 와 FAT16 구조

Name

Offset

(byte)

Size

(byte)

설명

Sector_Per_FAT32 36 4

이 필드는 FAT32 media 대해 정의되어 있고, FAT12 와

FAT16 에는 존재하지 않는다. 이 필드는 one FAT 에

의해서 차지하는 섹터들의 32 비트 개수이다.

Ext_Flags 40 2

Bits 0-3 active FAT 의 Zero-based 수. 만약

mirroring 을 할 수 없으면 유효하다. Bits 4-6 예약되어

있다. Bits 7 : 0 은 모든 FAT 에서 실행시간에 FAT 이

mirror 되어졌다는 것을 의미한다. 1 은 FAT 이

active 하는 것을 의미한다. Bits 8-15 예약되어져있다.

Filesystem_Version 42 2

상위 바이트는 중요한 개정 번호이다. 하위 바이트는

하위의 개정 번호이다. 이것은 FAT32 의 버전 넘버이다.

Root_Cluster 44 4

루트 디렉토리의 첫 번째 클러스터의 클러스터 번호로

설정된다. 대개 2 로 설정된다.

Filesystem_Info 48 2

Backup_Boot_Sector 50 2

Reserved 52 12

Number_Of_Drive 64 1

Reserved1 65 1

Boot_Sign 66 1

Volume_ID 67 4

Volume_Label 71 11

Type_Of_FileSystem 82 8

표 14) Offset 36 에서 시작하는 FAT32 구조

04040404. . . . RDERDERDERDE( ( ( ( Root Directory EntryRoot Directory EntryRoot Directory EntryRoot Directory Entry))))및및및및 실제실제실제실제 DATA DATA DATA DATA 를를를를 찾기찾기찾기찾기 위한위한위한위한 과정과정과정과정

MBR 파티션 관련 부분.

~

BR 논리 디스크에 대한 모든 정보를 가짐.

~

FAT1 cluster 들

FAT2 FAT1 의 mirror 부분

RDE root dir 부분

DATA data 부분

표 15) 간략한 FAT 분류

표 1 과 같이 간략히 나타 낼 수 있는데, 우리는 현재 RDE 까지 찾을

수 있다.

RDE 를 읽어서 파일( 또는 디렉토리 ) 이름을 찾고, 그 파일이

존재하는 첫 클러스터를 찾아서 다음 클러스터까지 연결되는 부분을

공부하고, 디렉토리 안의 또 다른 디렉토리들 ( sub directory )이

어떻게 연결되어 있는지를 분석하게 될 것이다.

1111) ) ) ) RDE RDE RDE RDE ( ( ( ( Root Directory Entry Root Directory Entry Root Directory Entry Root Directory Entry ))))

디렉토리는 크게 Root Directory Entry 와 Directory Entry 로 나타낼

수 있다.

그림 53) 탐색기에서 본 directory 관계

그림 1 에서 Root Directory Entry 는 ' C:\ ' , ' D:\ ' , ' E:\ ' 과

같은 논리 드라이브의 첫 라인선상을 뜻한다.

E:\ 밑에서는 ‘ 사진 ’ , ‘ 요즘 ’ , ‘ TC ' ,... 이라는 디렉토리와

파일이 존재할 것이다.

반면에, ' E:\test 10_50_100 ' 은 Directory Entry 가 된다.

즉, sub directory 가 되는 것이다.

그림 54) RDE, DE 와 디렉토리와의 관계

그림 2 에서 보듯이, E:는 RDE 가 되고 그 밑에 연결되어있는 sub

directory 들은 전부 DE 가 되는 것이다.

여기서 보면, RDE 와 DE 를 찾아가는 방법이 약간은 차이가 있음을

알수 있지만, 결국 Directory Entry 라는 것에는 변함이 없다.

다시 한번 RDE 를 찾는 법을 간단하게 정리하면,

* MBR 에서 BR 의 위치를 찾는다.

* BR 에서 reserved sector (offset 0x0e 에서 2byte)를 찾고, 또한 cluster 당 섹터수

( offset 0x0d 에서 1byte )를 찾고, 또 FAT 당 섹터수 ( offset 0x016 에서 2byte )를 찾아

둔다.

* BR 의 위치에서 reserved sector 를 더한 곳에 FAT 이 존재한다.

* FAT 의 위치에서 FAT 당 섹터수 X2 의 값을 더한 곳에 RDE 가 존재하게 되는 것이다.

표 16) RDE 구하는 방법

그래서 볼수 있게 되는 부분이 바로 그림 3 이다.

각 Entry 는 32byte 로 구성되어 있다.

하나의 파일 또는 디렉토리를 나타내는 기본 단위가 32byte 인

셈이다.

물론, Long File Name 을 적용하기 위해서 64byte 를 차지하는

경우도 있지만, 기본 Entry 의 단위는 32byte 이다.

그림 55) RDE

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

이름 ( 디스크 이름, 파일 이름, 디렉토리 이름 ) 속성

First Cluster

High 번호

First Cluster Low 번호 크기

표 17) DE 포멧

Directory Entry 포맷은 표 2 와 같다.

나머지 부분도 의미가 있으나, 파일의 시간 관련 부분이므로 나중에

설명하기 위해서 생략했다.

0 ~ 10 byte 까지는 이름이 된다.

디스크의 이름이 될 수도 있고, 파일 이름이 될 수도 있고, 디렉토리

이름이 될 수도 있다.

그것을 결정하는 것은 바로, offset 0x0b 속성에서 결정한다.

값 설명

0x01 읽기 전용

0x02 숨김

0x04 시스템

0x08 볼륨 ID

0x10 디렉토리

0x20 실행

0x0F long file name

표 18) 디렉토리 엔트리 속성

특히, 0x10 은 디렉토리를 나타내고, 0x20 은 파일을 나타낸다.

만일 디렉토리를 나타내고, 숨김으로 하고 싶다면, 0x10+0x02 =

0x12 로 하면 원하는 결과를 얻을수 있을 것이다.

그림 3 에서 하늘색과 초록색을 볼 수 있다.

초록색은 그 파일의 크기를 나타낸다.

우리가 파일의 크기를 알 수 있는 것은 이 값을 가지고 확인하는

것이다.

대신, 디렉토리나 볼륨 ID 에서는 이 값이 0 이다.

미리 만들어 놨으면 좋았겠지만, MS 사에서 그렇게 정의해 놓았기

때문에 우리도 그렇게 생각하면 되겠다.

그리고, 하늘색은 바로 우리가 중요하게 생각하는 First Cluster 를

나타낸다.

First Cluster 는 그 파일 (또는 디렉토리) 가 FAT 에서 존재하는 첫

Cluster 를 나타내는 것으로 실제 DATA 를 찾아 갈때에 없어서는

안되는 중요한 부분이다.

그래서, MS 의 chkdsk.exe 나 Norton 의 NDD.exe 를 실행시키면

Lost cluster 라고 나오는 부분이 있는데, 바로 이러한 부분이

없어졌거나 FAT 에서 link 가 되는 부분이 적합하지 않으면 나오게

되어 있는 것이다.

2222) ) ) ) DATADATADATADATA 와와와와 RDE, FAT RDE, FAT RDE, FAT RDE, FAT 의의의의 관계관계관계관계

FAT 의 존재 이유는 실제 DATA 를 찾기 위해서 존재한다.

DATA 가 100 섹터에서 133 섹터, 그리고, 400 섹터 ... 과 같이

여러군데 떨어져 있는 경우가 대부분이기 때문에 우리는 FAT 을

참조해서 다음 클러스터를 찾아가는 것이다.

따라서, DATA 를 읽는 동작을 간략히 정리하면,

* test.txt 라는 파일을 읽어라.

* RDE 를 찾아서 test.txt 라는 파일을 검색한다.

* RDE ( 또는 DE )에서 test.txt 를 찾았다면, first cluster 를 찾아서 첫 cluster 의

데이터를 cluster 당 섹터수 만큼 읽는다.

* 다시 FAT 에서 first cluster 가 있는 FAT 범위안에 있는 실제 섹터와 offset 을 읽는다.

* 그 다음 클러스터가 있으면, 계산에 의해서 클러스터가 존재하는 실제 DATA 섹터를

cluster 당 섹터수 만큼 읽고 없으면, 파일 읽는 동작을 그만둔다.

표 19) DATA 읽는 동작

test.txt 라는 파일을 찾은 후에 우리는 약간의 계산이 필요하게 된다.

FAT32 와 FAT16 은 다르겠지만, 우선 FAT16 의 예를 들고, 그림

3 을 1.jpg 를 가지고 테스트해 보자.

바로 위의 Entry 는 Volume ID 즉, 드라이브 명을 뜻하므로, 파일이나

디렉토리는 아니다.

다음 Entry 인 ‘ 1.jpg ' 는 속성이 ’ 0x20 ' 이므로 파일을

뜻하고 First Cluster 의 High 는

0x00, Low 는 0x02 를 나타내므로, 첫 클러스터는 2 임을 알 수 있다.

그리고, 만약 cluster 당 섹터수가 4 이고, 첫 데이터 섹터가 520

섹터라면,

0x02 cluster 는 520 , 521, 522, 523 섹터를 나타낸다.

읽고 나서 FAT 을 찾아가 보면, 다음 cluster 가 자리에 있을 것이다.

이것을 조금 공식화 시켜 보자.

필요한 것은 FAT 이 존재하는 범위에서 cluster 가 존재하는 FAT 내

섹터를 지목하는 일일 것이다.

FAT16 의 경우, N cluster 가 존재하는 FAT 에서의 섹터 번호는

FAT 내의 Sector Number = Reserved Sector + ( N Cluster * 2 / 512 )

표 20) FAT 내에서 N Cluster 에 대한 Sector Number 계산

이렇게 나타낼 수 있다.

FAT16 의 경우, 1cluster 가 0x0000 이렇게 2byte 를 차지하게 된다.

따라서, 1 섹터에서 512/2 = 256 개의 클러스터가 존재하게 되는

것이다.

즉, N Cluster / 256 을 하면 N 클러스터가 존재하는 섹터를 찾을 수

있다.

여기에, Reserved Sector 의 값, 즉 FAT 이 offset 되어 있는 위치를

더하면 우리가 원하는 FAT 내의 Sector Number 를 구할수 있는

것이다.

만약 MBR 이 존재한다면, 당연히 BR 의 offset 주소도 더해 주어야

한다.

그리고, N Cluster 가 존재하는 FAT 의 Sector 를 찾았다면, 이제는 그

섹터에서 어디에 위치해 있는지를 알아내야 한다.

N Cluster % 256 을 하면, 바로 offset 값을 구할 수 있다.

FAT 내의 클러스터 offset = ( N Cluster * 2 % 512 ) 로 구할 수 있는

것이다.

같은 계산으로 FAT32 는 0x00 00 00 00 이렇게 4byte 를 차지하므로,

FAT32 내의 Sector Number = Reserved Sector + ( N Cluster * 4 / 512 )

FAT32 내의 클러스터 offset = ( N Cluster * 4 % 512 )

표 21) FAT32 에서 N Cluster 의 Secter Number 구하는 방법

로 구할 수 있다.

FAT 에서 찾는 방법을 알았으니, 이제는 실제 데이터를 찾는 법도

알아야 한다.

실제 DATA 도 N Cluster 가지고 찾을 수 있다.

시작은 위에서도 언급했듯이, RDE 에서 First Cluster Number 를 가져

오는 것이다.

만약 520 이 DATA 의 시작 섹터라면, 520 섹터부터 cluster 당 섹터수

크기만큼 DATA 가 연속으로 되어 있을 것이다.

그런데, 여기서 주의할 점이 하나 있다.

모든 Cluster 가 2 부터 시작이라는 것이다.

위에서 ‘ 1.jpg ' 의 N Cluster 가 2 이므로, 2 - 2 -> 0 + 520 ->

520 부터 시작한다는 것이다.

만약 N Cluster 가 0x 1795 라면?

0x1795 ( 6037 ) - 2 = 6035 -> 6035* Cluster 당 섹터수 + 520

= 6035*4 +520 = 24660 섹터가 실제로 N Cluster 가 있는 내용의

실제 DATA 인 셈이다.

공식으로 적어 놓는다면,

실제 DATA 섹터 = ( N Cluster - 2 )* Cluster 당 섹터수 + First DATA Sector

표 22) 실제 DATA 섹터 찾는 방법

가 된다.

05050505. . . . FATFATFATFAT16161616 과과과과 FAT FAT FAT FAT32323232 를를를를 구현하기구현하기구현하기구현하기 위한위한위한위한 메모리크기메모리크기메모리크기메모리크기

1111) ) ) ) FATFATFATFAT16161616 , , , , FATFATFATFAT32323232 가가가가 차지하는차지하는차지하는차지하는 메모리메모리메모리메모리 크기크기크기크기

총 크기의 섹터수 / 클러스터당 섹터수 = 클러스터수

FAT32 인 경우

1 섹터당 FAT 개수 = 512/4 = 128 개

클러스터수 / 128 = FAT 크기 ( 섹터 )

FAT16 인 경우

1 섹터당 FAT 개수 = 512/2 = 256 개

클러스터수 / 256 = FAT 크기 ( 섹터 )

총 크기 (Byte) 총 섹터(sector) 총 cluster 수 1cluster 당 섹터수 FAT 가 차지하는 크기

0.5G

0.5G / 512 =

1048576

131072 8 1024 섹터 = 0.5M

1G

1G / 512 =

2097152

262144 8 2048 섹터 = 1M

2G

2G / 512 =

4194304

524288 8 4096 섹터 = 2M

4G 8388608 1048576 8 8192 섹터 = 4M

8G 16777216 2097152 8 16384 섹터 = 8M

표 23) FAT32 에서 FAT 가 차지하는 크기 1cluster 당 8 섹터 일때 ( 256M ~ 8G )

총 크기 (Byte) 총 섹터(sector) 총 cluster 수 1cluster 당 섹터수 FAT 가 차지하는 크기

16G 33554432 2097152 16 16384 섹터 = 8M

32G 67108864 2097152 32 18384 섹터 = 8M

표 24) FAT32 에서 FAT 가 차지하는 크기 ( 8G ~ 32G )

총 크기 (Byte) 총 섹터(sector) 총 cluster 수 1cluster 당 섹터수 FAT 가 차지하는 크기

16M 131072 65536 2 256 = 128k

128M 262144 65536 4 256 = 128k

256M 524288 65536 8 256 = 128k

512M 1048576 65536 16 256 = 128k

1G 2097152 65536 32 256 = 128k

2G 4194304 65536 64 256 = 128k

표 25) FAT16 에서 FAT 가 차지하는 크기 ( 16M ~ 2G )

2222))))FatFatFatFat 에서에서에서에서 RDE( Root Directory Entry ) RDE( Root Directory Entry ) RDE( Root Directory Entry ) RDE( Root Directory Entry )가가가가 차지하는차지하는차지하는차지하는 메모메모메모메모리리리리 크기크기크기크기

FAT16 의 경우에는 RDE 의 개수가 512 개로 정해져 있다.

MS 에서는 다른 경우에는 호환성에 문제가 있을 것이라고 경고하고

있고, 경험한 바에 의하면, 512 개 외의 다른 것을 본적은 없다.

1 개의 Entry 는 32 바이트다.

512 / 32 = 16 , 1 섹터당 16 개의 Entry 를 기록할 수 있다.

512 개의 Entry / 16 = 32 섹터가 나온다.

즉, FAT16 에서는 32 개의 섹터 크기의 RDE 영역이 존재하고, 32*512

= 16384byte = 16kB 의 메모리가 필요 하게 된다.

FAT32 의 경우에는 RDE 가 FAT 로 링크되어 있기 때문에,

계속해서 생겨 날 수가 있다.

FAT 영역에서 cluster 끼리 연결되듯, 0x0fffffff ( EOF )가 나올때까지

연결된다.

각각은 1 클러스터로 되어 있으며, ( 1 클러스터 이상을 해도 문제는

없을듯 싶으나, 실제로는 1 클러스터로 되어 있는 경우밖에 본 적이

없음. )

예를 들어, 1 클러스터당 섹터수가 8 이라면,

1 섹터당 16 개의 Entry 수가 나오고, 8*16 = 128 개의 파일 및

디렉토리를 생성할 수가 있다.

128 개의 생성 개수들이 연결되어서 생길수 있으므로,

가능한 클러스터수 / 16 개 = 최대 생길수 있는 경우의 RDE 영역의

크기라고 생각할 수 있겠다.

만일 1G 의 SDCARD 의 경우, FAT32 로 format 을 했을 때,

262144 개의 총 클러스터수가 나올수 있고, 262144/16 = 16384 섹터

= Maximun 약 8M 까지 생성 될 수 있다.

물론, 이러한 값들은 계산에 의한 것이고, MS 문서에 따르면, 각각의

예약된 영역이 있어서 그러한 값들을 생각해서 계산한다면, 더 적어질

수 있다.

4444 부부부부 실전실전실전실전 프로그래밍프로그래밍프로그래밍프로그래밍

실습을 하기 위해서는 실습할 수 있는 환경이 필요하다.

windows 에서 읽고 쓰는 방법을 설명하면 좋겠지만, 그 부분은 vxd 나

WDM 같은 디바이스 드라이버 프로그램을 할 줄 알아야 하기 때문에

누구나 쉽게 쓸수 있는 win98 의 OS 에서 Turbo C 3.0 에서 테스트를

하였다.

원리만 이해한다면, 프로그램 툴( visual c++, gcc, visual basic ... )은

어떠한 것이든 상관없기 때문이다.

하드웨어 액세스하는 부분이 들어가기 때문에 우리는 조금의

assemble 을 이해해야 한다.

필자가 아주 자세히 설명을 붙여 놨음에도 불구하고 배경지식을 얻고

싶으면, Assemble 관련 서적을 찾아보기 바란다.

어떠한 서적이든 ‘ mov ' 는 설명이 되어 있기 때문이다.

1111 장장장장 하드하드하드하드 디스크디스크디스크디스크 물리적으로물리적으로물리적으로물리적으로 읽고읽고읽고읽고 쓰기쓰기쓰기쓰기

앞서도 말했듯, 우리는 Media 즉, 하드디스크를 읽고 쓰는 프로그램을

하려고 한다.

Flash 메모리 같은 경우는 각각의 매체를 읽고 쓰는 부분이 다르기

때문에 우선 하드 디스크에서 읽고 쓰는 함수를 만들어 놓으면,

마찬가지로 Flash 에서도 그 함수들을 쓸 수 있다.

하드디스크는 Int 13h(인터럽트 13h)를 사용해서 장치를 읽고 쓸 수

있다.

윈도우즈에서는 하드웨어를 직접 제어하기 위해선, VxD 와 같은

드라이버가 필요하지만, DOS 에서는 Int 13h 를 통해서 직접적으로

하드 디스크를 읽고 쓸 수 있다.

int 13h 를 이용하기 위해서 x86 계열의 컴퓨터가 어떻게 움직이는지

이해해야 한다.

01010101. . . . int int int int 13131313h h h h 이해하기이해하기이해하기이해하기

Int 13h 의 AH = 02h 이면, 하드디스크를 읽으라는 명령이다.

예) mov ah , 2

Int 13h

라고 하면 읽는 동작이 일어나게 된다.

‘ 읽었으면, 그 읽은 데이터는 어디에 존재하는 것일까? ’하는 의문을

갖게 된다.

ES:BX 에 데이터가 들어가게 된다.

‘ 데이터가 들어가는 것은 아는데, 몇 개의 섹터를 읽을 수 있을까? ’

‘ 읽다가 문제가 생기면 어떤 표시를 할까? ’

‘ 어떤 Media 를 읽을까? ’

등등의 의문을 가지게 될 것이다.

이러한 궁금증은 아래의 표들을 보면 알 수 있다.

Interrupt Interrupt Interrupt Interrupt 13131313hhhh, , , , Section AHSection AHSection AHSection AH====02020202hhhh

INT13 - DISK - Read Sectors into Memory

AH = 02h

AL = 읽을 섹터의 수

CH = cylinder number 의 하위 8 비트

CL = 섹터 번호 1-63 (0-5 비트), cylinder 의 상위 2 비트(6-7 비트)

DH = 헤드 번호

DL = 드라이브 번호(bit 7 을 1 로 설정하는 것은 하드디스크)

ES:BX = 데이터 버퍼

Return CF 에러에 대해서 설정된다.

표 26) Int 13h 2h 하드읽기

예를 하나 들어보자,

우리가 읽으려는 섹터는 물리 섹터 0 번, 바로 MBR 이다.

mov ah , 2 ; 읽기

mov al , 1 ; 1 개의 섹터만

mov ch , 0 ; Cylinder 는 0

mov cl , 1 ; 섹터 1

mov dh , 0 ; head 0

mov dl , 80h ; 하드디스크

mov bx , 500 ; es:bx 에 데이터가 들어감.

int 13h ; 인터럽트

코드와 같이 만들면, MBR 의 내용이 ES:BX 에 들어가 있을 것이다.

그림 56) Debug 실행 화면

현재 자신의 OS 가 win9x 나 Dos 라면 바로 debug.exe 를 실행해

보자.

그림 30 과 같이 검은 바탕에 ‘ - ’ 만 나와서 껌벅 거리고 있을

것이다.

자세한 내용을 알고 싶으면, ‘ - ’ 뒤에 ‘ ? ’를 치면 ,

그림 57) -? 실행한 화면

그림 31 과 같은 화면이 나온다.

‘ 어셈블 A [주소] ’ 라는 것이 나온다.

즉, 어셈블을 하고 싶으면, ‘ - ’ 다음에 ‘ A '를 치라는 뜻이다.

특별히 주소를 지정하지 않으면, 현재 CS:IP 의 주소에서 어셈블을

시작한다.

현재의 CS 와 IP 를 알고 싶으면,

-R 을 치면 레지스터의 내용이 나온다.

-R 을 치고, 레지스터명을 치면, 그 레지스터의 내용을 수정할 수 있다.

-r

AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000

DS=162C ES=162C SS=162C CS=162C IP=0100 NV UP EI PL NZ NA PO NC

162C:0100 FEFF ??? BH

-r ax

AX 0000

:

-r cx

CX 0000

:3333

-r

AX=0000 BX=0000 CX=3333 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000

DS=162C ES=162C SS=162C CS=162C IP=0100 NV UP EI PL NZ NA PO NC

162C:0100 FEFF ??? BH

표 27) -r 에서 내용 변경한 예

그림 58) -a 를 실행한 화면

그림 32 는 실제로 프로그램화 한 화면이다.

‘ -t ’는 ‘trace'의 약자로 코드의 한 라인씩 실행해 준다.

int 13 의 코드라인 까지 실행하면, 하드의 MBR 을 읽어서 ES:BX 에

데이터를 넣어 준다.

그림 59) MBR 을 읽어온 화면

그림 33 에 보면 ' - d ' , 'dump' 명령으로 es:500 의 메모리 내용을

dump 한 것을 알수 있다.

BX 가 500 이기에 ES:BX 즉, ES:500 에 MBR 에서 읽어온 데이터가

들어가 있는 것이다.

참고로, MS 에서 기본적으로 되어 있는 debug.exe 로는 위의 내용을 볼수 없었다. 그래서,

ndebug.exe 라는 툴을 이용해서 윈도우에서 확인했다.

ch , cl , dh 에 원하는 섹터의 값을 넣어 주고 읽겠다고 하면 al 의

개수 만큼 es:bx 에 들어 가는 것이다.

반대로 ah 에 2 대신 3 을 집어넣으면 쓰는 동작을 한다.

ES:BX 가 가리키는 메모리 값을 쓰려는 섹터에 넣는 것이다.

ES:BX 는 자기가 원하는 데이터를 넣어 놓아야 할 것이다.

Interrupt Interrupt Interrupt Interrupt 13131313hhhh, , , , Section AH Section AH Section AH Section AH = = = = 03030303hhhh

INT13 - DISK -Write Disk Sectors

AH = 03h

AL = 쓰려고 하는 섹터의 수

CH = cylinder number 의 하위 8 비트

CL = 섹터 번호 1-63(비트 0-5), cylinder 의 상위 2 비트(6-7 비트)

DH = 헤드 번호

DL = 드라이브 번호(bit 7 을 1 로 설정하는 것은 하드디스크)

ES:BX 데이터 버퍼

표 28) Int 13h 3h 하드 쓰기

확인을 해보자.

우선, 우리는 HDD 로부터 데이터를 읽어서 메모리에 저장 할 수 있게

되었다.

읽어낸 데이터를 다시 HDD 에 쓰는 동작을 해보고, 또 다시 쓰여진

섹터의 내용을 읽어 내면 쓰기가 제대로 되었는지를 확인할 수 있다.

- 물리 섹터 0 번을 읽어서 5 번섹터에 저장한다.

- 물리 섹터 5 번을 읽어내서 0 번 섹터와 같은지를 확인한다.

주의! MBR 은 OS 동작에 중요한 부분이므로, 혹시 OS 가 없는 하드를 가지고 테스트하든지,

FDD 를 액세스 하든지, 중요한 데이터를 백업해 두든지 하는 작업을 해 두어야 한다.

잘못 해서 MBR 을 ‘0’으로 밀어 버린다면 최악의 상황으로 Fdisk 작업부터 새로 해야

할지도 모르기 때문이다.

위의 코드들은 아래와 같이 축약될 수 있다.

mov ax,201 ; mov ah , 2 mov al , 1 과 같다.

mov cx,1 ; mov ch , 0 mov cl , 1

mov dx,80 ; mov dh , 0 mov dl , 80

mov bx,500

int 13

코드를 실행해 보면, 같다는 것을 알 수 있다.

mov ax,301

mov cx,5

mov dx,80

mov bx,500

int 13

을 하면, 현재 ES:BX 에 있는 데이터를 5 번 섹터에 저장시킬 것이다.

이제 또 다시

mov ax,201

mov cx,5

mov dx,80

mov dx,800

int 13

을 하고 ES:800 을 보면 0 번 섹터의 내용을 읽어 옴을 알 수 있다.

02020202. . . . HDD Access HDD Access HDD Access HDD Access 함수함수함수함수 만들기만들기만들기만들기

지금까지 하드디스크를 직접적으로 액세스하는 방법을 어셈블러로

보았다.

C 언어로 설명할 것을 왜 어셈블러로 설명을 하는가 하는 사람들도

있을지 모르지만, x86 계열에서 하드웨어 제어하기 위해서 안으로 더

파고들면, 결국 어셈블에 다다르게 된다.

아래의 소스를 보면, 하드를 액세스하기 위해서 C 언어로 만들어 놓은

것이다.

보면 어셈블로 작성한 것과 별 다르지 않다는 것을 알게 될 것이다.

union REGS reg;

struct SREGS sreg;

char string[512];

unsigned segment;

reg.h.ah = 0x2;

reg.h.al = 0x1;

reg.h.ch = 0x0;

reg.h.cl = 0x1;

reg.h.dh = 0x0;

reg.h.dl = 0x80;

reg.x.bx = 500;

int86x(0x13, &reg, &reg, &sreg);

segment = sreg.es; // 세그먼트 주소를 가져온다.

for(int k=0;k<512;k++)

{

string[k] = peekb(segment, 500+k); // 메모리를 읽어서, string 버퍼에 옮긴다.

}

표 29) assemble 코드를 c 언어로 바꾼 예

c 언어에서 assemble 처럼 쓸수 있는 방법은 inline assemble 로

사용하는 방법과 표 42 처럼 컴파일러가 제공해 주는 형식으로

assemble 처럼 쓸 수도 있다.

inline assemble 을 사용하는 방법은 각각의 시스템마다 틀릴테지만,

void main(void)

{

asm

{

mov ah , 42h

mov al, 4h

int 13h

}

}

식으로 쓰인다.

embeded 시스템에서 이러한 방법으로 구현을 하는 소스들이 많이

있지만, assemble 을 모르는 사람에게는 좀 어려울 수가 있다.

다행히 Turbo C 컴파일러에서는 int86x( )라는 함수를 지원해서

필자가 생각하기에는 좀 더 쓰기 편한 것 같아 int86x( ) 함수를

이용해서 만들었다.

약간의 형식이 틀릴 뿐, 내용은 같다는 것을 알 수 있다.

union REGS {

struct WORDREGS x; // 16byte 형

struct BYTEREGS h; // 8byte 형

};

struct BYTEREGS {

unsigned char al, ah, bl, bh;

unsigned char cl, ch, dl, dh;

};

struct WORDREGS {

unsigned int ax, bx, cx, dx;

unsigned int si, di, cflag, flags;

};

struct SREGS {

unsigned int es;

unsigned int cs;

unsigned int ss;

unsigned int ds;

};

표 30) DOS.H 에 정의된 원형

표 169 를 보면 각각의 구조체들이 정의되어 있다.

peekb( segment , offset ) 은 segment:offset 의 메모리 내용을

데이터로 옮겨준다.

위에서 보여준 구조체 원형이라든지, 함수에 대한 설명은 TC3.0

이상의 boland 컴파일러나 MS c++ 에 대한 컴파일러의 도움말에 잘

나와 있다.

TC 같은 경우는 ' REGS ' 라고 빈 페이지에 쓴다음, 마우스

오른쪽을 클릭하면 도움말이 나온다.

그림 60) 확장 Int 13 으로 하드디스크 액세스하는 함수

표 170 을 보면, 앞에서 말한 방법과 약간 틀린 것을 알수 있다.

구조체를 하나 정의한 다음에 명령도 0x42 나 0x43 을 사용했다.

앞서 말한 방법으로 하드를 액세스 하면, ch, cl , dh 에 실린더 ,

섹터 , 헤더가 들어 가는 것을 알 수 있다.

그런데, ch 는 8bit + cl( 6~7 bit ) 의 2bit 총 10bit 가 실린더 ,

cl 의 0~5bit 가 6bit 가 섹터, dh 의 8bit 가 헤더가 된다.

2^10 = 1024

2^6 = 64

2^8 = 256

으로 1024*64*256 = 16777216 sector 이다.

섹터는 1 부터 시작하므로 63 이 되고, 헤드도 0 ~ 254 이므로 255 가

된다.

정확히 계산하면, 1024*63*255 = 16450560 이 된다.

1sector 가 512byte 이므로,

16450560 * 512 = 8,422,686,720 = 약 8G 의 용량까지 액세스 할

수 있다.

현재 우리가 쓰는 하드는 2004 년 현재 80G ~ 200G 까지 쓰고 있다.

또한, 앞으로는 T(terra) 까지도 액세스 할지도 모른다고 한다.

이렇게 따지면, Int 13 으로는 8G 이상을 액세스 할 수가 없는 것이다.

이것 때문에, 확장 Int 13 이 나왔다.

Int 13h 에 ah = 0x42 는 읽기 , 0x43 은 쓰기 동작을 하는 것이다.

00h successful completion

01h invalid function in AH or invalid parameter

02h address mark not found

03h disk write-protected

04h sector not found/read error

05h reset failed (hard disk)

06h data did not verify correctly (TI Professional PC)

ĥ㌘Р잌 ĥXЇ-廰Т-

쓰거나 읽는 것이다.

Offset 크기 설명

00h BYTE packet 의 크기

01h BYTE 예약(0)

02h WORD 옮길 섹터수 (Phoenix EDD 에서는 최대 127 섹터이다.)

04h DWORD 옮길 buffer

08h QWORD absolute block number

10h QWORD

(EDD-3.0, optional) 64-bit flat address of transfer buffer; used if

DWORD at 04h is FFFFh:FFFFh

표 31) disk address packet 의 format

앞서의 방법과 마찬가지로 구조체를 정의해준 뒤 , 그곳에 맞는

값들을 집어 넣어준후 int 13 을 걸어주면 된다.

그러면, ds:si 에 값이 저장되는 것이다.

int 13 을 걸었을 때, CF 는 clear 되어야지만 제대로 읽기 쓰기가 된

것이다.

또한, AH = 00h 가 되어야 제대로 읽기 쓰기가 된 것이다.

만일 CF set 되었거나, error 가 on 이거나, AH 가 00h 이외의 값이면

읽기 쓰기가 실패한 것으로 보고 원인을 파악해야 한다. ( 표

48 참조 )

offset 설명

00h 성공함

01h ah 에 유효하지 않은 함수나 변수가 들어가 있다.

02h address mark 찾을수 없다.

03h disk 쓰기 보호되어 있다.

04h 섹터를 찾을수 없다 또는 읽기 오류.

05h 하드디스크 초기화 실패.

05h data 가 정확하지 않다.

06h floppy 에서 disk 가 바뀌어짐.

07h hard disk 에서 drive parameter 가 활성화되지 않았다.

08h DMA overrun

09h data boundary error (attempted DMA across 64K boundary or >80h sectors)

0Ah hard disk 에서 bad sector 찾아짐.

0Bh hard disk 에서 bad track 찾아짐.

0Ch 지원되지 않는 트랙 또는 유효하지 않은 media

0Dh PS/2 hard disk 에서 포맷된 섹터가 유효하지 않다.

0Eh hard disk 에서 control data address mark 검출됨.

0Fh hard disk 에서 DMA arbitration level 벗어났다.

10h CRC 불일치 또는 읽는 도중 ECC 에러남.

11h data ECC corrected (hard disk)

20h controller 실패

31h no media in drive (IBM/MS INT 13 extensions)

32h incorrect drive type stored in CMOS (Compaq)

40h seek failed

80h timeout (not ready)

AAh drive not ready (hard disk)

B0h volume not locked in drive (INT 13 extensions)

B1h volume locked in drive (INT 13 extensions)

B2h volume not removable (INT 13 extensions)

B3h volume in use (INT 13 extensions)

B4h lock count exceeded (INT 13 extensions)

B5h valid eject request failed (INT 13 extensions)

B6h volume present but read protected (INT 13 extensions)

BBh undefined error (hard disk)

CCh write fault (hard disk)

E0h status register error (hard disk)

FFh sense operation failed (hard disk)

표 32) Values for disk operation status ( Ralf Brown's Interrupt List 로부터 참조)

LbaReadWriteSector() 함수를 사용하면, 물리적인 섹터를 읽고 쓸수

있다는 것을 알게 되었다.

‘ hddacc.cpp ’ 는 위에서 다루었던 내용을 실제로 코드로 구현한

것이다.

LbaReadWriteSector() 함수를 만들기 위해 우리는 그동안 Int 13h 와

어셈블을 공부한 것이다.

hddacc.cpp

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

// Disk Read Write Test

// 2004.3.26

//

// 이 프로그램은 disk access 상태를 볼 수 있습니다.

//

// e-mail : [email protected]

// Last modify date : 2004.9.7

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

#include <stdio.h>

#include <stdlib.h>

#include <dos.h>

#include <conio.h>

#include <io.h>

#include <fcntl.h>

#include <sys/stat.h>

#include <iostream.h>

#include <mem.h>

#include <string.h>

#include <process.h>

#include <errno.h>

#define LBA_READ 0x42

#define LBA_WRITE 0x43

#define TRUE 1

#define FALSE 0

typedef unsigned long DWORD;

typedef DWORD* LPDWORD;

typedef long LONG;

typedef unsigned int WORD;

typedef unsigned int UINT;

typedef int BOOL;

typedef unsigned char BYTE;

typedef char * LPTSTR;

typedef const char* LPCTSTR;

typedef void VOID;

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

// 하드디스크 섹터를 읽고 쓰기 선언.

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

BOOL LbaReadWriteSector(WORD disk, WORD wCmd, BYTE *buf, DWORD ssect,

WORD nSect);

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

// DiskAddress Packet 구조체

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

typedef struct tagDiskAddrPacket // for LBA read, write

{

BYTE bySize; // size of struct

BYTE byReserved; // reserved 0

WORD wNumSct; // number of sector for read, write

WORD wBufOffset; // offset of buffer

WORD wBufSeg; // segment of buffer

DWORD dwLogicalSct; // lower of logical sector

DWORD dwLogicalSctUp; // upper of logical sector

} DISKADDRPACKET;

DISKADDRPACKET dap; // disk address packet 16byte

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

// 하드디스크 섹터를 읽고 쓰기 정의.

// disk : 0x80 , 0x81 과 같은 미디어 타입을 나타낸다.

// wCmd : Read ( 0x42h ) , Write ( 0x43h ) 할지를 나타낸다.

// buf : 데이터를 담을 buffer.

// ssect : 읽을 물리적인 시작 섹터.

// nSect : 읽을 개수.

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

BOOL LbaReadWriteSector(WORD disk, WORD wCmd, BYTE *buf, DWORD ssect,

WORD nSect)

{

union REGS reg;

struct SREGS sreg;

dap.bySize = sizeof(DISKADDRPACKET);

dap.byReserved = 0;

dap.wNumSct = nSect;

dap.wBufOffset = FP_OFF(buf);

dap.wBufSeg = FP_SEG(buf);

dap.dwLogicalSct = ssect; // start logical sector for read &

write

reg.h.dl = disk; // disk is 0x80, 0x81...

reg.h.ah = wCmd; // LBA_READ or LBA_WRITE

reg.h.al = 0;

reg.x.si = FP_OFF(&dap);

sreg.ds = FP_SEG(&dap);

int86x(0x13, &reg, &reg, &sreg);

if (reg.x.cflag)

return FALSE;

else

return TRUE;

}

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

// main 함수

//++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++

void main(void)

{

DWORD ssector = 5; // access 하려는 섹터

int scount = 0; // 섹터 count

char disk_buffer[512]; // 읽어 들일 버퍼

LbaReadWriteSector(0x80,LBA_READ,disk_buffer,ssector,1); // 섹터

읽음.

printf("\n dump = %ld\n",ssector);

for(scount=0;scount<128;scount++) // 버퍼에 있는 내용을

보여줌.

{

if((scount%16)==0)

{

printf("\n");

}

printf(" %2x",(disk_buffer[scount]&0xff));

}

}

2222 장장장장 정보정보정보정보 가져오는가져오는가져오는가져오는 프로그램프로그램프로그램프로그램 만들기만들기만들기만들기

01010101....간단한간단한간단한간단한 disk viewer disk viewer disk viewer disk viewer 만들기만들기만들기만들기

Disk Viewer 를 만들게 된 이유는 Norton 의 Disk Editor 를

사용하다가가 불러 오는 속도가 느려서 였다. 또, 관련 프로그램을

연구하고 있던 터라 만들게 되었던 프로그램입니다.

처음부터 완벽하게 좋은 프로그램을 만들 수 없듯이, 모방이 창조의

어머니라는 말처럼, 우리도 Norton 의 Disk Editor 를 모방해 보는

것도 좋은 공부가 될 것입니다.

그림 61) Norton Disk Editor 의 모양

그림 59 처럼 만들려면, 많은 시간이 필요한 것은 물론이거니와

DOS(windows 98se 이하 os)에서만 동작하기 때문에 요즘 같이

windows xp 를 사용하는 환경에서는 그 실효성이 떨어진다.

따라서, 똑같이 만들 필요도 없을뿐더러, 단지 그 만들어진 배경

지식만 이해하면 충분할 것이다.

같이 제공되는 CD 에서 2 장에 보면, DiskView.cpp 라는 파일을 볼 수

있다.

문서에다 source code 들을 적는 것은 필자나 독자나 시간만 버리는

것 같아서, 중요한 부분만을 설명할 것이다.

DiskView.cpp 라는 파일을 열어 보면 알겠지만, define 된 곳이나

구조체화 된 곳은 앞서 공부한 ‘ hddacc.cpp ’ 와 같다.

즉, LbaReadWriteSector 함수는 같다.

LbaReadWriteSector 함수는 우리가 하드디스크를 액세스 하는 통로

이기 때문에, 기본적으로 포함 되어야 한다.

만일 어떤 독자가 다른곳에서 활용하기 원한다면,

LbaReadWriteSector 함수안의 내용을 바꾸면 될 것이다.

예를 들어, Nand Flash memory 에 이 함수들을 적용하고 싶다면,

LbaReadWriteSector 부분만을 적용하면 바로 확인할 수 있을 것이다.

그림 62) io 관계

이것은 윈도우용 Disk Editor 를 만들 때 똑같이 적용된다.

LbaReadWirteSector 함수 대신에 하드웨어를 액세스 할 수 있는

드라이버가 대신하게 되는 것이다.

아래의 HexDump 는 Buf 에 들어간 내용을 Dos 화면에 뿌려주는

역할을 한다.

printf 문을 이용했고, Text 모드의 화면에서는 80x25 개의 문자를

뿌려 줄수 있다.

이것을 잘 인지해서 모양 좋게 뿌려 주면 되는 것이다.

void HexDump(char * Buf, int size)

{

int i ;

char HDibble; // 0x12 라고 나올때 ‘1’ 이 있는 자리를 나타냄.

char LDibble; // 0x12 라고 나올때 ‘2’ 있는 자리를 나타냄.

int Flag =0;

for(i =0; i< size/2; i++)

{

HDibble = Buf[i];

HDibble = (HDibble & 0xF0) >> 4; // 0x12 일때 ‘1’을 빼내어 0x01 로

LDibble = Buf[i];

LDibble = LDibble & 0x0F; //0x12 중 ‘2’의 자리에 있는 값만 빼냄.

if(!Flag)

{

if((i%8) ==0 && (i%16)!=0)

{ printf("- "); Flag = 1; }

}

else

{

Flag = 0;

}

if((i%16) ==0) { printf("\n"); }

if((i%16) ==0) { printf("%4X :",i); } // 0x010, 0x020 이런 값.

printf("%X%X ",HDibble, LDibble);

}

printf("\nPlease any key to continue ... "); // 반을 나누어서, 좀

쉬어야함.

getch();

for(i =size/2; i< size; i++)

{

HDibble = Buf[i];

HDibble = (HDibble & 0xF0) >> 4;

HDibble = HDibble;

LDibble = Buf[i];

LDibble = LDibble & 0x0F;

LDibble = LDibble;

if(!Flag)

{

if((i%8) ==0 && (i%16)!=0) { printf("- "); Flag = 1; }

}else Flag = 0;

if((i%16) ==0) { printf("\n"); }

if((i%16) ==0) { printf("%4X :",i); }

printf("%X%X ",HDibble, LDibble);

}

}

ShowSector 함수는 특정 섹터를 읽어서 화면에 보여 주는 함수이다.

LbaReadWriteSector 함수 호출후, HexDump 함수 호출하는 식의

프로그램 구조로 되어 있다.

BOOL ShowSector(DWORD ssector)

{

unsigned char *disk_buffer = 0;

unsigned sector_size=512;

disk_buffer = (unsigned char *) malloc((unsigned)sector_size);

memset(disk_buffer,NULL,512);

LbaReadWriteSector(0x80,LBA_READ, disk_buffer, ssector,

1);

HexDump(disk_buffer,512);

free(disk_buffer);

return TRUE;

}

DeletSector 함수는 특정섹터에 쓸 buffer 의 내용을 전부 0 으로

만들어 놓고, wirte 섹터를 하면, 그 섹터의 내용이 0 이되는 것을 알

수 있다.

BOOL DeleteSector(DWORD ssector) // 0 으로 만듦.

{

unsigned char *disk_buffer = 0;

unsigned sector_size=512;

disk_buffer = (unsigned char *) malloc((unsigned)sector_size);

memset(disk_buffer,NULL,512);

LbaReadWriteSector(0x80,LBA_WRITE, disk_buffer, ssector,

1);

HexDump(disk_buffer,512);

free(disk_buffer);

return TRUE;

}

DeleteSeclectSector 함수는 특정 시작 섹터와 끝 섹터를 정해서

0 으로 만드는 함수이다.

BOOL DeleteSelectSector(DWORD ssector, DWORD Endsector) // 0 으로 만듦.

{

unsigned char *disk_buffer = 0;

DWORD k=0;

unsigned sector_size=512;

disk_buffer = (unsigned char *) malloc((unsigned)sector_size);

memset(disk_buffer,NULL,512);

for(k=ssector;k<Endsector+1;k++) // 시작 섹터부터 끝섹터까지.

{

LbaReadWriteSector(0x80,LBA_WRITE, disk_buffer, k,

1); }

free(disk_buffer);

printf( "\nDeleted!");

return TRUE;

}

CopySector 함수는 특정 섹터를 읽어서 다른 섹터에 복사해 주는

함수이다.

BOOL CopySector(DWORD ssector, DWORD Tatsector)

{

unsigned char *disk_buffer = 0;

unsigned sector_size=512;

disk_buffer = (unsigned char *) malloc((unsigned)sector_size);

memset(disk_buffer,NULL,512);

LbaReadWriteSector(0x80,LBA_READ, disk_buffer, ssector,

1); //읽어오기

LbaReadWriteSector(0x80,LBA_WRITE, disk_buffer, Tatsector, 1); //

쓰기

HexDump(disk_buffer,512);

free(disk_buffer);

return TRUE;

}

위 함수들을 이용해서, DiskView.cpp 의 main 에서는 하드디스크에

있는 섹터들을 읽고 쓰고 copy 하고, delete 하는 동작을 하게 되는

것이다.

그림 63) DiskView 실행화면

02020202. . . . MBR MBR MBR MBR 정보정보정보정보 가져가져가져가져 오기오기오기오기

앞서서 MBR 에 대한 소스를 공개 했으므로, 이번 장에서는 파티션

테이블에 대해서 좀 더 알아보고 프로그램을 해 보기로 한다.

그림 64) MBR 에 대한 그림

그림 62 에서도 볼 수 있듯이, 0x0 부터 1cd 까지는 부트 code

들이다. 앞서도 보았듯이, 부트를 하기 위한 code 이다.

이 코드들을 다시 공부한다는 것은 시간 낭비인 것 같고, 실제적으로

저 값들이 어떤 동작을 한다는 것인지만 이해한 후에 파티션 테이블을

보여 주면 될 것 같다.

이 번 장의 목적은 파티션 테이블을 제대로 표현하도록 프로그램해 볼

것이다.

실제적으로 파티션을 나눌 때는 이 테이블을 기초로 나누어지니까

정보를 확실하게 이해하는 것이 좋다.

WINDE 처럼 각각에 화려한 선을 그려서 나누어 보고 싶지만, 그렇게

까지 하는 것은 각자의 몫으로 맡기고,

우리는 우선 buffer 에다가 MBR 섹터를 읽어서, 필요한 정보가 어디

있는지 보여주는 것을 목표로 하고자 한다.

그림 65) Patinfo 실행 결과

그림 63 을 보면, 우리가 원하는 부분을 볼 수가 있다.

굉장히 간단하지만, 이러한 하나 하나가 모여서 커다란 프로그램을

이룬다는 것을 생각하자.

Patinfo.cpp 파일의 내용을 보면, 아래와 같은 구조체가 하나더

포함되어 있다.

하나 하나씩 변수를 정할 수도 있지만, 재활용의 측면에서 이렇게

변수의 포맷을 맞추었다.

typedef struct tagPrimePation // 파티션 정보 entry 들.

{

BYTE Part_At[1];

BYTE Part_SHead[1];

BYTE Part_SSect[1];

BYTE Part_SCylin[1];

BYTE Part_FileSys[1];

BYTE Part_EHead[1];

BYTE Part_ESect[1];

BYTE Part_ECylin[1];

DWORD Part_SSectNum[1];

DWORD Part_TotalSectNum[1];

} PRIMEPAT;

PRIMEPAT PrimePat;

다음의 GetPartition 함수는 원하는 섹터를 입력 했을때 섹터내에서

파티션 entry 부분의 정보를 가져와서 보여주게 된다.

BOOL GetPartition(DWORD ssector) // 4 개의 파티션 정보를 읽어서

표시한다. ( FAT/NTFS 든 상관 없음. )

{

BYTE DriveNum=0;

unsigned char *disk_buffer = 0;

disk_buffer = (unsigned char *) malloc(512);

memset(disk_buffer,NULL,512);

LbaReadWriteSector(0x80,LBA_READ, disk_buffer, ssector, 1);

g_Part_EXT[0]=0;

for(DriveNum=0;DriveNum<4;DriveNum++) // 드라이브 수.

{

memcpy(PrimePat.Part_FileSys,disk_buffer+0x1c2+DriveNum*16,1);

memcpy(PrimePat.Part_At,disk_buffer+0x1be+DriveNum*16,1);

memcpy(PrimePat.Part_SSectNum,disk_buffer+0x1c6+DriveNum*16,4)

;

memcpy(PrimePat.Part_TotalSectNum,disk_buffer+0x1ca+DriveNum*1

6,4);

if(DriveNum==2)

{

g_Part_SSectNum[0]=PrimePat.Part_SSectNum[0];

g_Part_TotalSectNum[0]=PrimePat.Part_TotalSectNum[0];

}

if(DriveNum==3)

{

g_Part_SSectNum1[0]=PrimePat.Part_SSectNum[0];

g_Part_TotalSectNum1[0]=PrimePat.Part_TotalSectNum[0];

}

switch(PrimePat.Part_FileSys[0])

{

case 0x0:

printf("\n %d System = unused",DriveNum);

break;

case 0x1:

printf("\n %d System = FAT12

",DriveNum); break;

case 0x4:

printf("\n %d System = FAT16

",DriveNum); break;

case 0x5:

printf("\n %d System =

EXTEND",DriveNum); g_Part_EXT[0]=PrimePa

t.Part_SSectNum[0];

break;

case 0x6:

printf("\n %d System =

BIGDOS",DriveNum); break;

case 0x7:

printf("\n %d System =

NPFS ",DriveNum); break;

case 0x0b:

printf("\n %d System = FAT32

",DriveNum); break;

case 0x0c:

printf("\n %d System =

FAT32x",DriveNum); break;

case 0x0f:

printf("\n %d System = EXTNDx",DriveNum);

g_Part_EXT[0]=PrimePat.Part_SSectNum[0];

break;

default:

printf("\n%dSystem=0x%1x

",DriveNum,PrimePat.Part_FileSys[0]);

}

printf(" Act = 0x%2x",PrimePat.Part_At[0]);

printf(" Start Sect = %10ld",PrimePat.Part_SSectNum[0]);

printf(" Size

= %10ld",PrimePat.Part_TotalSectNum[0]);

}

free(disk_buffer);

return TRUE;

}

03030303. . . . BR BR BR BR 정보정보정보정보 가져오기가져오기가져오기가져오기

임베디드 시스템에서 BootRecord 에서 가져온 값을 이용해서 많은

값들을 이용한다.

따라서, 이번장에서도 BR 의 정보를 보여주는 프로그램을 만들어

보고자 한다.

DispBR.cpp 에는 새로이 tagBR 과 tagBR32 구조체가 포함되었다.

데이터를 읽어서 메모리에 저장된 내용을 하나씩 가져오려고 했을때,

이왕이면, 구조체에 넣으면 편리하게 이용할 수 있기 때문에

FAT16 용과 FAT32 용으로 따로 만들었다.

BOOL GetBR(DWORD ssector)

{

char tmpFAT[4];

DWORD coutk;

memset(BootRecord32,NULL,512);

LbaReadWriteSector(0x80,LBA_READ, (BYTE*)BootRecord32, ssector,

2);

memcpy(tmpFAT,BootRecord32+3,4);

if(memcmp(g_stFAT,tmpFAT,4)==0) // FAT 가 아닌 경우는 배제 시킴.

{

printf("\n NTFS not suported!");

exit(0);

return FALSE;

}

printf("\n----BOOT-----------------------------------------

Absolute sector %ld",ssector);

printf("\n(0x03) OEM ID = ");

for(coutk=0;coutk<8;coutk++)

{

printf("%c",BootRecord32->OemID[coutk]);

}

printf("\n(0x0b) Bytes per Sector = %d",BootRecord32->BytePSect[0]);

g_SectPClus = BootRecord32->SectPClus[0];

printf("\n(0x0d) Sector per cluster = %d",g_SectPClus);

printf("\n(0x0e) Offset first FAT = %d",BootRecord32->OffFat[0]);

printf("\t(Physical) %d",ssector+BootRecord32->OffFat[0]);

printf("\n(0x10) FAT Copy = %d",BootRecord32->FATcopy[0]);

printf("\n(0x15) Media descriptor = %x",(BootRecord32-

>Media[0])&0xff);

printf("\n(0x20) Big Total Sector = %ld",BootRecord32-

>TotalSect[0]);

printf("\n(0x24) Sector Size Per Fat = %ld",BootRecord32->SectPFat[0]);

g_SectPFat = BootRecord32->SectPFat[0];

printf("\n(0x2c) Root Clust = %ld",BootRecord32->RootClust[0]);

g_RootClust = BootRecord32->RootClust[0];

printf("\n(0x43) Volume serial number = ");

for(coutk=2;coutk>0;coutk--)

{

printf("%x",BootRecord32->VolSerial[coutk-1]);

}

printf("\n(0x47) Volume Label = ");

for(coutk=0;coutk<11;coutk++)

{

printf("%c",BootRecord32->VolLabel[coutk]);

}

printf("\n(0x52) System ID = ");

for(coutk=0;coutk<8;coutk++)

{

printf("%c",BootRecord32->SysID[coutk]);

}

printf("\n ");

printf("\n----BOOT---------------------------------------------

--------------");

printf("\n1st FAT (Physical) = %d",ssector+BootRecord32-

>OffFat[0]);

g_FATsect = ssector+BootRecord32->OffFat[0];

printf("\n2nd FAT (Physical) = %d",ssector+BootRecord32-

>OffFat[0]+BootRecord32->SectPFat[0]);

g_RDE = ssector+BootRecord32->OffFat[0]+(BootRecord32-

>SectPFat[0]*BootRecord32->FATcopy[0]+(g_RootClust-2)*g_SectPClus);

printf("\nRoot Directory Entry (Physical) = %ld",g_RDE);

getch();

clrscr();

return TRUE;

}

그림 66) DispBR 실행 결과

04040404. . . . 하드디스크하드디스크하드디스크하드디스크 정보정보정보정보 가져오기가져오기가져오기가져오기

하드디스크도 마이컴을 가지고 있기 때문에 적절한 명령을 주면,

하드디스크에 대한 정보를 가져올 수 있다.

물론, 애플리케이션 레벨에서 프로그램을 하는 경우에는 장치와

붙어서 access 를 해 주는 드라이버 레벨하고의 통신이 중요하다.

보통의 경우는 드라이버들이 기본적인 api 를 제공해 주기 때문에 그

api 를 통해서 애플리케이션에서 필요한 정보들을 얻어 오면 된다.

그림 67) device control 관계

os 가 있는 경우에는 os 가 커널이라는 것을 만들어 놓아서 커널에서

device 들을 총괄적으로 관리하게 된다.

windows NT 계열에서는 드라이버와 통하는 명령을 통해서

하드디스크의 정보를 알아 올수가 있다.

하지만, 이곳은 드라이버에 대한 설명 문서가 아니므로, DOS 계열 즉,

windows 98 정도에서 int13 을 이용해서 하드디스크의 정보를

가져오는 정도로만 마치고자 한다.

만일 windows NT 계열에서도 하드디스크를 컨트롤 하고 싶다면,

WDM( Windows Driver Model ) 을 공부하셔서 관련된 드라이버를

따로 개발 하면 된다.

또는 잘 찾아 보시면, 웹 상에서 관련 소스들을 받아 공부할 수 있을

것이다.

dispinfo.cpp 의 파일의 내용을 보면, 크게 2 가지 눈여겨 볼 것이

있다.

tagDiskParm 구조체와 GetDiskInfo 함수이다.

그림 68) tagDiskParm 구조체 ( 자료 출처 Ralf 의 interrupt )

그림 69) GetDiskInfo 함수

int86 함수에 대해선 앞서도 설명했지만, int13 을 쓸수 있도록 도와

주는 함수이다.

ah 에 0x48 을 집어 넣고, dl 에 가져오려는 disk 의 media type 을

가져오고, ds:si 에 우리가 만들어 놓은 구조체의 주소를 넣은 다음에

bySize 에 buffer 의 크기를 적어 주고, int13h 를 걸어 주면,

ds:si 주소에 원하는 정보가 들어 가게 되어 있다.

그 정보를 printf 문으로 모니터에 보여 주면 되는 것이다.

그림 70) DISKINFO 실행 결과

그림 68 은 512MB 의 USB 메모리를 읽어온 결과이다.

1 sector 는 512byte 이기 때문에, 1013760 x 512 = 519,045,120

byte 가 된다.

C 드라이브는 하드 디스크이고, D 드라이브는 이동형 디스크일때

reg.h.dl 에 0x81 을 집어 넣으면 1 번 드라이브에 대한 정보를 가져올

수 있다.

만일 좀 더 많은 드라이브를 연결한다면?

0x80, 0x81, 0x82, 0x83 ... 이런 순으로 값을 집어 넣고 정보를 읽어

보면된다.

05050505. . . . 유효유효유효유효 클러스터클러스터클러스터클러스터 및및및및 사용량사용량사용량사용량

FAT 은 DATA 가 어디에 있는지 알려주는 map 이고 DATA 들을

연결시켜 주는 연결자 이다.

우리는 FAT 을 통해서 DATA 가 디스크에서 어느 위치에 있는지 얼마

만큼 있는 지 알게 된다.

그림 71) 디스크 전체 공간

그림 72) 프로그램 결과

그림 70 은 전체 디스크 공간을 보여 주는 그림이다.

calcsize.cpp 의 실행 결과를 보면 전체 디스크 공간을 나타내어

주는데, 그림 70 과 같다는 것을 확인할 수 있다.

그림 73) BR16 과 BR32 의 구조체

그림 74) Get Total Size 함수

그림 75) main 함수

3333 장장장장 간단한간단한간단한간단한 응용응용응용응용 프로그램프로그램프로그램프로그램 만들기만들기만들기만들기

01010101. . . . 포맷포맷포맷포맷 프로그램프로그램프로그램프로그램 만들기만들기만들기만들기 ( FAT ) ( FAT ) ( FAT ) ( FAT )

1 장 07 포멧에서 포맷에 대한 개념을 이미 파악했다.

우리도 그곳에 나와 있는 것을 다 테스트해 보면 좋겠지만, 커다란

부분만을 테스트하는 프로그램을 만들고 나머지는 독자의 몫으로

맡기려고 한다.

이번 part 에서 테스트 환경은

cpu : p3 700Mhz

os : win98se

파일 시스템 : FAT32 , FAT16

Media : 후지스 13G HDD , Sandisk mmc 32MB

다행히, mmc card reader 에서 win98 용 드라이버를 제공해 주었기

때문에 win98 에서도 이동형 장치로 인식할 수 있었다.

format 을 하고서 제대로 인식되는지를 테스트 하기 위해선 또 하나의

하드 디스크를 장착해서 테스트 해 보는 것이 정석이나, 떼었다

붙였다 하기에는 하드 디스크는 불편했기에 이동형 장치로 인식할 수

있는 방법을 택했다.

마찬가지로 usb 저장장치도 마찬가지로 포맷을 행할 수 있기 때문에

usb 저장장치가 되는 지원되는 사람들은 usb 저장장치를 이용하는

것이 좋다.

여러 가지 포맷 중에 우리는 qformat 을 할 것이다.

또한 원래의 포맷은 아마도 섹터가 불량 섹터가 있는지도 확인하는

알고리즘도 첨가되어 있을 것이다.

우리는 그 부분까지는 할 필요가 없다고 생각된다.

각각의 Media 마다 불량 섹터를 체크하는 방법이 다르고, 어떠한

Media 는 체크하는 부분이 많은 시간을 차지하기 때문에 실효성이

없다는 사람도 있어서, 많은 펌웨어 개발자들은 각각의 아이디어를

내어서 나름데로 체크하기 때문이다.

따라서, 이곳에서는 모든 섹터가 불량 섹터가 없다는 전제하에

프로그램을 한다는 것을 이해하기 바란다.

그림 76) 포맷의 분류

그림을 다시 보면, Quick format 은 FAT 과 RDE 를 새로 update 해야

한다는 것을 알수 있다.

하지만, 실제로는 MBR 과 BR 도 다 새로 만들어 주고 FAT 과 RDE 는

거의 0 으로 채우면 끝이 난다.

format 이라면, DATA 의 부분을 0 으로 채우고서 다시 읽어서 0 으로

써져 있는지 ( 이 부분이 bad 섹터 검사하는 부분이다. ) 확인한 후에

bad 섹터가 있다면, FAT 에서 bad 섹터로 체크를 해 두고 그 부분은

cluster 로 쓰이지 않고 pass 된다.

Qformat 은 그러한 부분은 생략하고 MBR, BR 에 원하는 값을 집어

넣은 뒤, FAT 에는 거의 0 을 집어 넣고 RDE 도 0 으로 채워 넣으면

끝나기 때문에 빠르게 포맷이 가능한 것이다.

DATA 에 대한 bad 섹터 검사가 있는 것은 format 이고, DATA 에

대한 bad 섹터 검사가 없는 것은 quick format 으로 생각해도 무방할

것이다.

여기서 잠깐요!

포맷 프로그램을 만들려 할 때 가장 중요하게 알아야 하는 것은 뭔가요?

그것은 바로 Media 의 절대 크기일 것입니다.

물리적인 총 크기를 알아야 그 안에서 유효 클러스터의 값이 나오고, 파티션을 어떻게

정의할까 하는 생각도 나오게 되는 것입니다.

하지만, 실제적으로 물리적인 크기를 얻어오는 것은 윈도우즈로 넘어가면서 알기가 어려워

졌습니다.

win98se 이전의 os 에서는 장치를 직접 액세스 하는 부분이 가능했기 때문에, int13

이라든지 각종 interrupt 핸들러를 이용해서 정보를 알아오는 것이 windows 에서 보다는

상대적으로 쉽습니다.

Media 의 절대 크기를 알게 되면, 그 다음 알아야 되는 것은 유효 클러스터 수 일것입니다.

우리가 윈도우즈에서 용량을 가져올때 유효한 클러스터를 계산해서 그 값을 계산한 값으로

보여주게 되는 것입니다.

그림 77) 유효클러스터

따라서, 절대 크기와 실제적으로 윈도우즈에서 나타내는 크기가 다를 수가 있습니다.

qformat.cpp 의 main() 함수를 보면, 3 개의 함수로 이루어 진것을

알수 있을 것이다.

GetDiskInfo(), MakeBR(), MakeFAT() 함수가 qformat 의 중심

함수들이다.

GetDiskInfo 함수는 물리적인 Media 의 용량을 int13 함수를 통해서

가져오는 함수이다.

Media 의 특성상 물리적으로 가져오는 다른 방법이 존재할 수도 있다.

따라서, GetDiskInfo 함수는 그에 따라서 바뀌어야한다.

그림 78) MakeBR 함수

MakeBR 함수는 앞에서도 설명했듯이 Boot Record 에 맞게 하나 하나

값을 적어 넣으면 된다.

JumpCode 는 0xEB 0x58 0x90 또는 0xEB 0x3C 0x90 의 두 값이

있을 수 있다.

당연히 BootRecord 를 프로그램하는 사람에 따라 다른 값이 존재할

수 있다.

앞에서 설명했듯이,

0xEB 0x58 0x90 은

#0000: jmp short #005A

nop

가 되고,

0xEB 0x3C 0x90

#0000: jmp short #003E

nop

의 의미가 되기 때문에 실제적으로 코드가 있는 부분으로 jump 하게

되는 명령이어서, 실제적으로 코드가 있는 부분을 자신이 직접

프로그램할 수 있다면, 그 부분의 위치(offset)을 적어 주면 되는

것이다.

즉, 우리가 보고 있는 BootRecord 는 데이터 부분과 code 부분이

나누어져 있어서, 데이터 부분에는 BootRecord 에 호환성 있게 만들어

주고 code 부분에서는 우리들 마음데로 프로그램을 해서 좀 더

재미난 프로그램을 만들 수 있다는 얘기가 된다.

어떠한 사람들은 바이러스 프로그램을 만들때 이 부분을 가지고

장난을 칠테고, ( 실제적으로 Boot 관련 바이러스는 대부분 이부분을

가지고 장난 친다는 것을 알수 있다. www.ahnlab.co.kr 에 가서

바이러스 검색에서 " boot " 를 치면 boot 관련 바이러스를 알수

있다. ) 또 바이러스 치료 프로그램을 만드는 사람들은 이 부분을

분석해서 바이러스가 생기는 부분을 막을 것이다.

또한 보안 관련 프로그램들이나 각종 유용한 프로그램들도 이부분을

참조하는 경우가 많다.

여기서 잠깐요!

Boot Record 는 Boot 에 관련된 DATA 와 Boot 하려는 데 필요한 code 들로 이루어 져

있습니다.

자기 자신이 부팅을 하고 싶지 않으면 굳이 Boot code 들은 적지 않아도 상관이 없습니다.

예를 들면, USB 저장매체나 SD card 같은 저장 매체의 경우에는 자신이 부팅을 하지 않는

경우가 대부분이기 때문에 code 부분이 없는 경우도 많습니다.

있어도 Boot 에 관련된 code 보다는 저장매체의 보안에 관련된 일을 하는 경우가

대부분입니다.

OemID 는 format 을 만드는 사람들의 경우 자신이 만들었다는 것을

표시할 때 쓴다.

따라서, 단지 8 자 의 조건만 만족하면 어떠한 글자라도 상관이 없다.

OffFat 는 자신이 FAT 을 놓고 싶은 장소(offset)을 정해서 값을

넣으면 된다.

Total16 은 Media 의 크기가 32MB 이하일 경우에는 이곳을 전체

섹터로 나타낸다.

TotalSect 를 전체 섹터로 나타내도 상관이 없지만, 중요한 것은 둘 중

하나를 전체 섹터로 나타낸다면, 나머지 하나는 반드시 0 이어야 한다.

OS 가 두 값을 다 가지고 혼란스러워 할 필요는 없기 때문이다.

Fatsize 는 유효 클러스터를 계산한 뒤에 필요한 섹터의 크기가 나온다.

그 값을 적어 주면 된다.

VolSerial 은 원래 포맷할 당시의 날짜와 시간을 가지고 만든다.

그래서, 이 값을 이용해서 check sum 을 MBR 의 patition entry 의

바로 앞에다 적어서 windows 가 부팅할 시에 MBR 이나 BR 에 문제가

없는지 check 하도록 만들어져 있다.

하지만, 우리는 단지 포맷을 하고 저장매체로서 호환을 할 것이기

때문에 우리가 원하는 값을 적어놓아도 상관없다.

VolLabel 은 우리가 윈도우즈에서 ‘ 드라이브명 ’ 이라고 보게 되는

값이다.

이 값을 변경하고 재부팅을 하게 되면 자신이 바꾼 값이 동작하는

것을 알수 있다.

여기서 잠깐요!

‘ 드라이브 명 ’ 은 윈도우즈에서 바꾸면 바로 바뀌잖아요.

왜 재부팅을 해야 하나요?

윈도우즈는 현재 RAM 에 올라가 동작하고 있게 됩니다.

물론 어떤 부분은 하드디스크에 저장하는 부분도 있겠지만,

기본적으로 윈도우즈가 동작하게 되는 모든 행위는 RAM 에 올라가게

되는 것입니다.

즉, 윈도우즈는 자기가 RAM 에 있는 일부 메모리를 고치는 것을 OS

자신만이 알게 됩니다.

또한 하드디스크의 BR 을 매 시간 체크해서 RAM 에 올리는 것이

아니기 때문에 처음 부팅할 때에만 BR 의 값을 RAM 에 올리게 되는

것입니다.

따라서, 우리는 RAM 이 아닌 HDD 의 값을 고쳤기 때문에 재부팅을

해 주어야 바뀐 값을 확인 할 수 있습니다.

또 다른 확인하는 방법은 바로 저장매체를 확인하는 것입니다.

저장매체를 인식한 후 프로그램하거나 Disk Editor 를 사용하여 값을

바꾼 후 다시 저장매체를 제거한 후 재인식하면 우리가 바꾼 값을

확인할 수 있습니다.

혹시, Disk Editor 로 저장매체의 MBR 및 BR 등등을 지웠는데도

저장매체가 정상동작하는 것처럼 보인다면 바로 RAM 에서도 동작하기

때문이라고 생각하시면 됩니다.

하지만, 만일 어떠한 프로그램이 BR 을 재인식하려 하는 동작을

한번만이라도 한다면 그때서 부터는 ‘ Media 에서 값을 읽을 수

없습니다. ’ 라는 말과 함께 이상 동작을 하게 될 것입니다.

SysID 는 FAT16 및 FAT32 를 구별해 주는 부분이 아니다.

즉, 어떠한 사람들은 이 부분이 파일 시스템을 구별해 준다고

생각한다.

하지만, 이 부분은 단지 정보 제공이 목적이지 이 값을 가지고

파일시스템을 구별하는 목적이 아니다.

그러나, 이 값은 묵시적으로 FAT16 , FAT32 같이 묵시적으로 많은

사람들이 공통적으로 쓰고 있고 현재에는 그 저장매체의 파일시스템이

무엇인가를 확인하는 중요한 정보가 되고 있는 것이 사실이다.

만일, 이 글을 읽고 있는 개발자가 있다면 이 사실을 염두해 두고

개발을 하기 바란다.

나중에 이 부분으로 인해서 bug 가 발생할 수 있다는 생각을 열어두고

개발하는 것이 bug 를 줄이는 길이다.

그림 79) MakeFAT

MakeFat 은 크게 세 부분으로 나눈다.

0 으로 지우는 부분과 0xF8 과 값이 일 부 값을 써 주는 부분,

그리고, 그러한 부분이 다 메모리에 채워 졌으면 FAT 의 자리에

써주는 부분이렇게 나누어 진다.

OffFat 의 값을 BR 에서 정했기 때문에 우리는 그 값이 정한 자리에

FAT 의 초기화된 값을 써 주어야 한다.

그리고, FAT 은 클러스터들의 연결이기 때문에 0x00 외에 다른

값들을 써 주면 안된다. ( bad 섹터 표시는 예외 )

또한 Directory Entry 도 0x0 으로 만들어주어야 하기 때문에

fatsize 의 3 배를 지우도록 했다.

FAT 만 지우려면 2 배만 하면 된다.

그림 80) MakeFAT 실행 결과

그림 79 는 MakeFAT 을 실행한 결과이다.

보시는 바와 같이 단순히 F8 FF FF FF 를 적어준 부분만 있다.

눈여겨 본 분은 아시겠지만, 이것은 FAT16 에 대한 포맷이다.

FAT32 라면 FAT 이 이러한 값이 아니라 그림 80 과 같은 값이

나오게 된다.

FAT 은 각각에 섹터에 대한 의미만 안다면 프로그램하는 것은 그렇게

어렵지 않기 때문에 의미 파악하는 것이 중요하다.

그림 81) FAT32 에서 FAT 의 값

qformat.cpp 의 일부 프로그램을 고쳐서 정확히 포맷이 되는지

확인하려면, diskeditor 를 이용해서 저장매체를 0 으로 만든 다음에

다시 저장매체를 꽂으면, 포맷이 안 되어 있다는 메시지가 뜨면서

포맷을 하시겠습니까? 라고 물을것이다. 이때 포맷을 하지 말고

우리가 만든 qformat.exe 를 실행하고 다시 저장매체를 재인식

시키면 바로 저장매체를 읽고 쓸수 있는 상태가 되는 것을 확인할 수

있다.

그림 82) 파일 시스템을 인식 못함.

02020202. . . . 간단한간단한간단한간단한 파티션파티션파티션파티션 분할기분할기분할기분할기 만들기만들기만들기만들기

우리는 종종 파티션 관리 유틸리티를 쓰곤 한다.

대표 적인 파티션 관리 프로그램은 아마 파티션 매직일 것이다.

그림 83) 파티션 매직

파티션 분할하는 프로그램이 생각 보다 쉬워 보여도 내부에서는

실제적으로는 많은 작업을 한다.

앞서 MBR 섹터에서 파티션 테이블이 있었다.

솔직히 그 부분을 나누면 우리는 논리적인 파티션을 나눌 수 가 있게

된다.

하지만, 그 부분만을 나누면 뒤에 따라 오는 BR 이나 RDE 나 FAT

그리고 실제 DATA 영역이 전부 영향을 받기 때문에 파티션 entry 를

건드리게 되면, 뒤에 오는 DATA 영역까지도 전부 손을 봐야 된다.

우리도 그러한 프로그램을 만들게 된다면, 필자 이 문서를 쓰는 것

보단 프로그램을 관리해 주는데 더 많은 시간을 들여야 할 것이다.

실제적으로 그 비슷한 프로그램 때문에 많은 고생을 했던 경험이 있기

때문에 우리는 그러한 수준의 프로그램까지 만들지는 않겠다.

대신 간단히 만들어 볼 수 있는 프로그램을 만들어 테스트 하고자

한다.

보통 우리가 파티션을 나눌때 쓰는 프로그램은 fdisk 이다.

이것은 MS 사의 기본 프로그램이고 TEXT 모드에서 동작하는 그나마

간단한 프로그램 이다.

그림 84) Fdisk 프로그램

이 프로그램은 OS 가 설치되기 전에 동작시켜야 하고, Fdisk 만 하면,

그림 77 처럼 디스크가 인식되지 않을 것이다.

Fdisk 후에는 꼭 format 동작을 시켜야 비로소 드라이브에 데이터를

쓰거나 읽을수 있게 된다.

일부러 우리가 어떤 HDD 를 임의로 물리 0 번 섹터부터 63 번

섹터까지 지웠다고 한다면,

그림 85) 디스크 인식 오류

그림 77 처럼 디스크 인식 오류를 일으킬 것이다.

DE 나 windisk , winde 같은 Disk Editor 프로그램으로 확인해 보면,

MBR 영역과 BR 영역이 올바르지 않기 때문이란 것을 이제는 알수

있다.

또는 앞서 만들었던 DiskView 라는 프로그램으로도 확인 할 수 있다.

따라서 우리는 MBR 과 BR 또는 FAT 에 어떤 값을 집어 넣어서

우리가 원하는 파티션을 나누는 작업을 하고자 한다.

Test 환경

사용 언어 : Turbo-C

OS: win98se

HDD : 13G HDD 2 개

파일 시스템 : FAT, FAT32

테스트 방법 : 일부러 목표 하드 디스크의 MBR 과 BR 을 0 으로

만들어 디스크 인식 오류( 그림 77 ) 상태로 만들고, 우리가

만든 myFdisk.exe 로 디스크의 파티션을 나누고 포맷을 해서 우리가

원하는 크기 만큼 파티션이 만들어 졌는지를 확인한다.

하드디스크를 2 개를 달았다.

첫 번째 하드디스크에는 TC 같은 컴파일러와 실행 파일을 집어 넣기

위해서 이고, 두 번째 하드디스크는 포맷하고 파티션을 만들기 위한

장소이다.

13GB 의 하드디스크를 1GB 의 파티션을 나누어서 포맷을 할 것이다.

fdisk 는 단순히 파티션을 만드는 작업만 하지만, 우리가 만들려는

프로그램은 파티션도 만들고 또한 포맷까지도 할 것이다.

여기서 잠깐요!

포맷에 대해서는 앞 절에서 배웠다 또한 좀 더 앞에서도 언급했다.

그런데도 불구하고 파티션과 포맷에 대한 인과관계가 모호할지도 모른다고 생각되어서

그림과 함께 설명하고자 한다.

그림 86) 파티션과 논리드라이브

파티션은 드라이브를 나누기 위한 정보가 있는 것이고, 각각의 파티션들이 나누어지면,

그것은 논리드라이브나 기본 드라이브 또는 숨김 드라이브가 된다.

각각의 논리 드라이브들은 자신의 드라이브가 논리적으로 0 인 부분이 바로 Boot

Record 가 된다.

각각의 논리 드라이브들은 Boot Record 를 가지고 있게 되는 것이다.

예를 들어, C 드라이브는 63 에 Boot Record 를 가지고 있고, D 드라이브는 34567 에 Boot

Record 를 물리섹터 9876543 에 E 드라이브의 Boot Record 를 가질수 있다.

그러나, 각각의 드라이브는 각각의 Boot Record 를 0 번 섹터로 알게 된다.

따라서, 각 드라이브들은 포맷을 하거나 용량을 계산할 때 각 드라이브 단위로 계산하기

때문에 우리는 드라이브에 대한 용량 및 사용 현황을 알게 되는 것이다.

만일, 하나의 드라이브만 사용하는 경우는 어떻게 될까?

그림 87) MBR+BR 또는 BR

그림 86 처럼 두가지가 다 가능하다.

원래 파티션은 BR 이 생겨난 뒤에 따로 더 집어 넣은 것이다.

용량이 이렇게 크게 될 것이라고 MS 사에서도 짐작을 못했었는데, MBR 이라는 부분을

추가함으로서 좀 더 자유롭게 파티션을 나누거나 multi OS 가 가능하게 된 것이다.

BR 만 있는 대표적인 예는 바로 플로피 디스크를 예로 들수 있다.

플로피 디스크는 자신의 드라이브 외에 여러 드라이브를 만들 수 없게 끔 되어 있어서

( 사실 1.44MB 되는 곳에서 파티션을 나누어서 쓸 필요가 없기 때문에 ) MBR 은 존재하지

않는다.

하지만, 만일 플로피 디스크에 MBR 을 만든다고 해도 아마 윈도우즈에서 인식을 하지

못하기 때문에 플로피디스크에서는 MBR 이 없다.

USB 저장매체나 SD Card 와 같은 저장매체는 플로피와는 다르게 MBR 이 있을수도 있고,

BR 만 있을 수도 있다.

MBR 이 있다고 해서 드라이브를 두 개를 가지는 것이 아니라 플로피 디스크와 마찬가지로

하나의 드라이브만 인식하게 된다.

myFdisk.cpp 는 두 부분으로 구분된다.

파티션 정보를 집어 넣는 부분과 앞서 프로그램시 적용했던 포맷 관련

함수들을 적절히 이용하였다.

그림 88) MBR 값

그림 87 을 보면, 보통의 FAT16 에서 쓰이는 MBR 을 배열로 잡아

놓았다.

앞서도 분석해 보았듯이, 이 부분은 우리가 특별히 바꿀만한 부분이

없다.

바뀌어야 되는 부분은 0x1be 부터 나오는 파티션 entry 부분이다.

하지만, 실린더 헤드 섹터도 옛날에 쓰이던 포맷이므로 현재는

OS 에서 참조하지 않게 되었다. ( 실린더 헤드 섹터로 나타낼수 있는

최대의 크기는 2GB 이다. )

따라서 우리가 바꾸는 부분은 파일시스템 종류 부분과 논리 시작섹터

그리고 논리 총섹터 이 세 부분일 것이다.

또 한 부분은 파티션 Active 관련 부분일 테지만, Booting 하고

상관없이 프로그램을 하기로 했기 때문에 그 부분은 생략한다.

그림 89) 파티션 entry 구조체와 MBR 구조체

MBR 의 구조는 BootCode 446byte 와 각각의 파티션 entry 들

그리고 ‘ 0xAA55 ' 로 알려진 MagicCode 가 있다.

PrimePat1 ~ 4 까지 같은 포맷들이므로 따로 PRIMEPAT 이란

구조체를 하나 더 만들어 구조체 안에 또 구조체를 선언했다.

g_MBR 이란 값을 MBRP 라는 구조체에 복사를 해서 각각의 값들을

한번에 복사 되도록 프로그램화 하였다.

그리곤, MakeBR 에서 MBR 에 써졌던 값들을 참조해서 BR 의 위치와

또한 MakeFAT 에서는 FAT 의 위치를 정하도록 만들었다.

그림 90) MBR 구조체 정의

MakeMBR 의 MBRP->PrimePat1.Part_TotalSectNum[0] 의 값과

MakeBR 의 BootRecord->TotalSect[0] 의 값은 같아야 한다.

그래야 windows 에서는 error 가 없다고 생각할 것이다.

그리고, Fatsize 는 앞서 유효 클러스터 계산하는 방법에 의해서

cluster 당 섹터수가 얼마인지에 따라 값이 정의된다.

그림 91) MakeMBR 과 MakeBR 함수

그림 92) MakeFAT 함수와 main 함수

MakeFAT 함수는 특별히 들어갈 값은 F8 FF FF FF 만 들어 가면,

된다.

자, 이제 Main 함수에서 각각의 만든 함수들을 조립해 보자.

GetDiskInfo 함수를 이용해서, 물리적인 총 섹터를 가져와서 이용하려

했으나, 이곳에서는 단지 디스크 정보를 보여 주는 것으로 대신했다.

MakeMBR 에서 MBR 을 써주고, 그 다음 BR 과 FAT 을 써 주면,

13GB 의 하드중 1GB 의 파티션을 나누어서 그 부분만 포맷을 하도록

했다.

그림 93) MyFdisk 실행 결과

그림 94) 13GB 의 하드가 1GB 만 인식

만일 myFdisk.cpp 를 2 장 3 절에서의 Patition Table 에 따라서

나누게 된다면, 여러개의 파티션으로 나누어지며, MS 사의

Fdisk 보다는 좀 더 편리한 프로그램을 만들 수 있을 것이다.

03030303. . . . 디렉터리디렉터리디렉터리디렉터리 List List List List 가져오기가져오기가져오기가져오기( FAT )( FAT )( FAT )( FAT )

지금까지 MBR 과 BR 에서 디스크의 크기 및 포맷에 대한 대략적인

개념은 이해를 했다.

하지만, 우리가 결국 다루고 싶은 것은 파일 및 폴더 과 같은

DATA 를 다루고 싶은 것이다.

즉, 파일을 컨트롤 ( 핸들링 ) 하고 싶은데, 그 첫 번째가 되는 것이

RDE 라고 앞에서 이론을 얘기할 때 말했다.

이 문서에서 DOS 와 똑같이 파일 핸들링 할 수 있는 소스를 만들어

주세요 라고 한다면, 그건 너무 욕심이 과하고 필자가 어떻게

들어가는지 길을 가르쳐 주고 독자들이 좀 더 연구하면 충분히 그러한

것들을 만들 수 있다고 생각한다.

그림 95) 탐색기로 본 폴더와 파일

그림 94 와 같이 Test 라는 D 드라이브 ( 앞절에서 13GB 를 1GB 만

포맷해서 만들어 놓은 드라이브임 )에 ' mine ' 이라는 폴더와 ' 1.bat '

이라는 파일을 만들어 놓았다고 생각해 보자.( 실제로 필자가 테스트한

그림임 )

command 모드에서 ' dir ' 이란 명령을 치면,

그림 96) dir 실행 화면

그림 95 처럼 파일 또는 폴더 이름이 나오고 파일이라면 파일크기

그리고, 마지막 생성 날짜 와 마지막 액세스한 시간이 나오게 된다.

mylist.cpp 위의 그림과 비슷하게 정보를 보낼 것이다.

물론, dir 실행 화면과 똑같이 만들수도 있다.

하지만, 굳이 그러고 싶은 생각은 없고, 필요한 정보를 내보내는

방법을 code 를 통해서 알아보자.

그림 97) main 함수

프로그램의 구성은 그림 96 과 같다.

MBR 이 있는 경우도 있고, 없는 경우도 있으므로 있으면, MBR 의

Entry 의 값을 참조해서 BR 의 위치를 return 값으로 내 보낸다.

그림 98) MBRCheck 함수

BR 인지 MBR 인지를 확인하는 방법은 정형화된 방법은 보지 못했다.

그래서, 필자 나름대로 FAT16 과 FAT32 가 있는 경우에는 BR 이고

아니면, MBR 이고 혹시 싶어서, MBR 조차도 아닌 경우의 수까지

분류해 놓았다.

그림 99) CalcOffsetRDE 함수

다음에는 FAT 의 위치와 RDE 의 위치를 찾아서 각각 모니터에

표시하도록 했다.

우리가 궁극적으로 찾으려는 것은 RDE 의 위치이고 그것을 찾으면,

우리는 앞서 보았던 그림처럼 파일의 정보를 보여줄 것이다.

그림 100) ShowList 함수

우리가 RDE 를 찾았으면, DE 의 포맷에 따라 각각의 파일 및 폴더를

분류를 해서 보기 좋게 뿌려 주면 된다.

그림 101) MyList 실행결과

그래서, 그림 100 과 같은 결과가 나왔다.

파일이름과 확장자 이름 액세스 DATE , 지워진 파일인지 아님

Directory 인지 아님 LongFileName 의 부분인지 아님 파일의 총 크기

인지를 나누게끔 만들었다.

Dir 과 나온 값과는 약간의 차이가 있다.

Dir 에서는 Deleted 된 File 과 LongFileName 인지 그리고 숨김 파일

또는 Directory 인지를 생략해 버린 것이다.

굳이 End User 가 골치 아프게 볼 필요가 없는 파일 또는 속성이기

때문이다.

만일 우리도 code 를 그렇게 고친다면, ' 1.BAT ' , ' MINE ' 의 값만

보여질 것이다.

그것은 프로그램의 만드는 프로그래머의 취향일 것이다.

그림 102) Dos 용 Mdir

혹시 누군가 Mdir 처럼 만들지도 모르겠다.

사실 DOS 에서 필자가 제안한 code 들로 이렇게 까지 만들 이유가

없다.

DOS 드라이버가 올라가 있기 때문에 ( 정확히 말하자면

command.com 이 동작하기 때문에 ) 이미 만들어져 있는 Dos

명령만으로 파일 컨트롤하기에 적합하기 때문이다.

대신, NTFS 에서 Mdir 처럼 만든다면 굉장히 유용할 것이다.

플로피나 CD-ROM 으로 부팅해서 긴급히 DATA 를 살리거나 할때는

정말 유용한 유틸리티가 될 것이다.

사실 NTFS 를 DOS 처럼 파일 핸들링 하려는 프로그램을 만들려고

생각해 본 적이 있었는데, 세상일이 다 그렇듯, 누군가가 이미 만들어

놓고 있었다.

http://www.sysinternals.com/Utilities/NtfsDos.html

위 사이트에 가면, ‘ NTFSDOS ’ 라는 프로그램이 있는데 말그대로

플로피 디스크로 부팅시켜서 ( DOS ) NTFS 파일시스템을 DOS 처럼

쓰는 프로그램이다.

Dir 명령과 DOS 에서 쓰이는 명령 대부분이 동작하게 되어 있어서,

window xp 나 NT 의 경우에 부팅을 시키지 못해서 DATA 를 가져

오지 못할 때 쓰면 유용한 프로그램이다.

우리나라도 빨리 이러한 분야에 많은 젊은 사람들이 연구를 거듭해

새로운 파일시스템 및 DB 또는 OS 자체를 만들 수 있을 수 있으면

좋겠다는 것이 필자의 작은 바램이다.

4444 장장장장 상용상용상용상용 프로그램들프로그램들프로그램들프로그램들 분석해분석해분석해분석해 보기보기보기보기

이 장은 현재 상용되어 있는 프로그램이 어떠한 것이 있는지 기존의

상용화 프로그램을 벤치마킹 함으로써 좀 더 좋은 프로그램을 만들 수

없는지 한 번 더 생각하게 되는 것이다.

이곳에서 분석하는 프로그램들은 각 분야의 최고라고 생각되는

프로그램들을 필자 나름으로 분석해 본 것이다.

따라서, 분석은 단순히 필자의 생각이므로 정확히 맞지 않음을 미리

얘기하는 바입니다.

01010101. . . . 디스크디스크디스크디스크 조각조각조각조각 모음모음모음모음

그림 103) 디스크 조각 모음

하드 디스크는 물리적으로 헤더라는 한 bit 를 읽는 장치가 존재한다.

그래서, 가까이에 있는 것 보다 멀리 있으면 시간도 많이 걸리는 것은

당연하다.

또한, 연속적으로 붙어 있지 않으면 하드디스크가 물리적인

장치이므로 잘못 읽어서 data 가 손상될 위험도 존재하게 된다.

그렇기 때문에 어느 정도 하드디스크를 사용한 후에는 ‘ 디스크 조각

모음 ’ 이 필요하다.

win98 에서 쓰였던 디스크 조각 모음 방법은 cluster 들이 깨어진

것들을 맨 앞에서부터 순차적으로 조각 맞추었다.

하지만, windows xp 로 올라 오면서 맨 앞에서부터 맞추는 것 보단

가까이에 있는 link 들을 붙이는 작업을 하게 되었다.

따라서, 그림 102 첨 파란색으로 작업이 끝났어도 인접해 있기 때문에

데이터를 읽는 데 문제가 없다고 확인시켜 준 것이다.

맨 앞으로 안 옮기는 것 때문에 windows xp 에서는 훨씬 빨리

조각모음을 끝낼 수 있었다.

windows xp 용 디스크 조각 모음은 사실 diskeeper 라는 프로그램과

같은 프로그램이다.

diskeeper 를 만든 곳에서 MS 사에 팔았는지 자세한 내막은

모르겠지만, 동작 환경이나 디자인은 같다.

동작하는 순서를 자세히 살펴 보면 FAT 을 예로 들어 우선 Directory

Entry 를 읽어서 각 파일에 대한 FAT 에 있는 Cluster 의 조각화를

체크한다.

각각의 조각화 되어 있는 파일 또는 폴더 중에서 우선 순의를 매기고

( 아마 이 부분이 알고리즘이 어떻게 되어 있는지 모르겠지만,

대략적인 생각으로는 link 간 거리가 먼 부분을 우선하지 않았나

생각한다. )

우선 하드디스크의 뒷 부분의 일부 영역의 DATA 를 원래의 조각으로

모음을 한다.

그리고는 우선순의에 따라 데이터를 뒷부분으로 가져온 다음에 놓일

자리를 찾거나 놓일 자리를 확보 하기 위해 조금씩 조각되어 있는

부분을 모은다.

따라서, 분석하는 곳에서는 조각난 부분만을 분석하고 놓일 자리만

확보가 되면, 뒤에 모아둔 조각난 cluster 를 맞추어서 인접하게 갖다

놓는다.

02020202. . . . 파티션파티션파티션파티션 매직매직매직매직

그림 104) 파티션 매직

파티션 매직은 DOS 시절에도 유용한 프로그램이었는데, Windows

에서도 동작하도록 만들어 졌다.

기 DATA 가 있는 상황( OS 가 설치된 상황 ) 에서도 파티션을 조정할

수 있는 것이 큰 특징이며, MBR 의 파티션 entry 를 바꾸어야 하고,

BR 의 총섹터 그리고, 다른 드라이브가 생기면 용량 계산도 해야 한다.

또한, 기존의 드라이브에 있는 데이터가 옮기게 되었을 적에 문제가

없는지도 체크를 해 보아야 한다.

FAT 에서 NTFS 변환 및 NTFS 에서 FAT 으로의 변환이 가능해야

하기 때문에 어쩌면 ‘ 디스크 조각 모음 ’ 보다 더 복잡하게 만들어야

될지도 모른다.

기본적으로 OS 에 의존하지 않고 파일시스템만을 분석해서 파티션

경계면이 생겼을 때 DATA 를 옮겨 주어야 한다.

03030303. . . . 파이널파이널파이널파이널 데이타데이타데이타데이타

그림그림그림그림 105105105105) ) ) ) 파이널파이널파이널파이널 데이타데이타데이타데이타

myList 프로그램을 보면, 윈도우즈나 Dos 에서 명령을 사용하지 않고

물리적인 섹터 데이터를 읽어서 나름데로 분석해서 list 로 만들었다는

것을 알수 있다.

파이널 데이터도 마찬가지로 물리적으로 읽어서 list 로 만들기 때문에

MBR 이나 BR 이 없어져도 ( MBR 이나 BR 이 없어 지면, MS 사의

경우는 디스크 인식 오류가 생김 ) 검색을 통해 RDE 를 찾아서 list 를

다시 살리게 되는 방법을 쓰는 것이다.

또한 그것 이외에도 한 섹터 섹터를 비교해서 그것이 jpg 포맷인지

동영상 포맷인지도 구별해 낼 수 있는 능력을 가졌다.

특히 액셀파일이라든지 문서 파일들을 복원 시킬 수 있는 능력은 타의

제품을 불허한다.

그림그림그림그림 106106106106) ) ) ) jpg jpg jpg jpg 파일파일파일파일

04040404. . . . GhostGhostGhostGhost

처음 고스트라는 제품이 나왔을 때는 왜 필요한지 몰랐다.

하지만, Ghost 와 비슷한 제품을 연구하는 필자로서는 얼마나 잘 만든

프로그램인지 새삼 느끼게 되었다.

Ghost 의 원리는 FAT 이든 NTFS 이든 사용되는 data 영역이 있고

사용되지 않는 data 영역이 있다는 것에 힌트가 있다.

windows 를 설치하게 되면, 예를 들어 13GB 하드에 windows98 을

설치하게 되면, 윈도우즈 98 은 500MB 도 차지하지 않게 된다.

500MB 의 동영상 파일을 한 쪽 하드에서 다른쪽 하드로 옮기게 되면

단순히 data 복사 속도만으로 얼마나 빨리 copy 되는가를 알수 있다.

Ghost 도 마찬가지로 data 있는 부분만을 순서대로 저장을 시키면서

파일로 만들고 또한 압축 알고리즘을 이용해서 파일을 좀 더 작게끔

만들어 버린다.

그림 107) Norton Ghost

따라서, 복원하게 되면 OS 를 설치하는 것 보다 적어도 6 배 이상의

시간이 절약 되며, 설치되어 있는 상황에 따라 더 많은 시간을

절약하게 된다.

필자도 이러한 원리에 따라, ImgCopy 라는 프로그램을 만든적이 있다.

Ghost 와 원개념은 비슷하지만, 구현방식은 조금 틀리게 했다.

FAT 과 NTFS 모두 지원했었는데, 문제는 파티션 나누는 문제라든지

파일화 시키는 문제라든지, 여러 가지 문제 때문에 더 이상 진행은

시키지 않았다.

혹시 확인해 보고 싶으신 분들은 www.winde.co.kr 으로 들어오시면

필자가 만들어 놓은 몇 몇 utility 들이 있음을 알수 있다.

05050505. . . . 기타기타기타기타

위의 프로그램들 이외에도 Windisk , Notorn Disk Editor , Disk

Cleanner , 파이널 eraser 같은 영구 삭제 프로그램들과 Acronis 에서

나온 OS selector 같은 프로그램들이 있다.

맺음말맺음말맺음말맺음말

필자가 파일시스템에 관련해서 문서를 쓰려고 마음 먹게 된 것은

파일시스템에 관련되어서 프로그램을 하고 있을 때였다.

문서를 쓰는 대부분의 사람들이 그렇듯, 인터넷을 뒤지고 많은

사람들과 자료를 공유해 보고 서점을 찾아 다녀도 내가 일하고 있는

분야에 대해서는 별로 문서가 없다는 것을 알게 되었다.

그리고, 필자도 7 년간 파일시스템 관련된 일만 하다 보니, 자연스럽게

다른 사람들 보다 조금 더 알고 있다는 사실을 알게 되었다.

필자는 프로그래머가 꿈이었고, 아직도 진정한 프로그래머가 되는

것이 꿈이다.

프로그램을 만들 때에 참고가 될 만한 서적이 있어야 프로그램을 할

수 있다. 진정한 프로그래머라면 그러한 참고가 될 수 있는 서적을

만들어야 되지 않나 생각해 본다.

혹시, 이 문서가 그러한 역할을 할 수 있지 않을까 내심 기대하면서

이 문서를 마치겠다.

추가추가추가추가 글글글글

사실은 이 문서는 좀 더 많은 내용으로 이루어져 ( 한 500page

정도 ) 있던 필자의 책이었다.

솔직한 심정으로 책으로 출판되었으면 괜찮을 것이라고 생각했었고,

아내와 자식들에게 시간을 양해 받으면서 만든 문서였다.

몇 년간 쓴 문서이지만, 결국은 시장 논리에 의해서 ( 시장성이 없다는

이유로… ) 출판의 꿈은 접었다.

더블어, 비슷한 시기에 비슷한 주제로 나온 책이 몇 달 전에 있었다.

시장이 좁고 찾는 사람이 적은 주제의 문서이지만, 그래도 이러한

문서를 찾고 있을 엔지니어들에게 도움이 되고자 무료로 open 하기로

결정했다.

하지만, 이 문서를 무료로 인용해도 된다는 것은 아니니 오해하지

않기를 바라며,

책으로는 출판되지 못했지만, 이렇게 문서라도 만들 수 있게 도와준

나의 부모님, 나의 아내와 딸 그리고, 몇 달 뒤에 태어날 나의

아들에게 이 글을 바친다.

2222. . . . 용어용어용어용어 해설해설해설해설 , , , , 참고문헌참고문헌참고문헌참고문헌 , , , , 찾아보기찾아보기찾아보기찾아보기

참고 문헌

1) 웹사이트

www.ntfs.com

www.finaldata.com

www.sysinternals.com

www.internals.com

www.sec.co.kr

www.hynix.co.kr

2) 참고서적 및 자료

C 언어로 하드웨어 주무르기 이석주 , 가남사 1994 년

3) 필자의 홈페이지

www.winde.co.kr

용 어 관 련 설 명

반도체 도체와 부도체의 중간적인 성격을 갖는 성질을 이용하여

전기적 신호를 제어, 증폭. 기억등을 할 수 있도록 만든 제품의 총칭

ASIC Application Specific IC

주문형 반도체. 전자 제품의 경박단소 추세에 따라 범용성이 높은

표준 IC 와는 달리 고객이나 사용자가 요구하는 특정한 기능을 갖도록

설계 제작된 IC

CHIP 반도체 조각, 보통 소자 또는 집적회로가 형성되어 있는

웨이퍼의 한 부분을 말하며, Die 라고도 한다.

CSP Chip Scale(Size) Package

Chip Size 대비 PKG 의 Size 가 120%이하일 경우에 한해 CSP

PKG 라 한다. 이 개념으로 회사에서 개발한 PKG 는 μBGA, WBGA,

TBGA, FBGA WLCSP 등이 있다.

DDP Dual Die Package

하나의 Package 내에 두 개의 칩이 들어가는 Package 의 일종이다.

한 장의 Lead Frame 상부와 하부에 각각 칩이 하나씩 붙는 구조가

있고, 두 장의 Lead Frame 이 사용되는 구조가 있다. Memory 용량을

2 배로 증가시킬 수 있는 장점을 갖고 있다.

DDR Double Data Rate

SYNC DRAM 과 달리 1CYCLE 에 DATA 를 2 번 처리할 수 있어

DATA 처리 속도가 빨라 그래픽카드 및 그래픽게임기에 사용됨.

28M/256M SYNC 66 PIN 제품이 있음

DEVICE DEVICE

DRAM Dynamic Random Access Memory

COMPUTER 의 기억장치로 사용되는 DATA 의 저장에 사용.

EEPROM Electrically Programmable Read Only Memory

공급되는 전원이 없어도 DATA 보존이 10 년 이상 가능하며

1 만~10 만회 전기적으로 DATA 를 삭제/기록 가능한 MEMORY

EPROM Erasable Programmable Read Only Memory

사용자가 100 ~ 200 회에 한하여 자외선을 이용 DATA 을 지우고

새로운 DATA 기억 가능한 MEMORY

FLASH MEMORY EEPROM 의 집적도 한계를 극복하기 위해

일괄소거방식의 1TR-1CELL 구조를 채용한 제품으로 전원을 꺼도

기억된 정보가 없어지지 않는 비휘발성 메모리의 일종.

전기적인 방법으로 정보를 자유롭게 입출력할 수 있으며, 전력소모가

적고, 고속 프로그래밍이 가능하다.

MASK ROM Mask Read Only Memory

반도체 생산자가 제품의 제조과정에서 Mask 에 의해 정보를

기억시키고 일단 기억된 정보의 변경은 불가능하다

MEMORY 전기적 또는 자기적 형태로 정보를 가지고 있는

Computer hardware 명칭

MICRO (MicroCircuit) 회로소자의 밀도가 높아 전자회로의 기능을

하고 있는 단일 pkg 내에 있는 상호 연결된 소자들로 이루어진 작은

회로를 말한다.

PACKAGE 반도체 표면을 외부의 습기 및 불순물로부터 보호하고

접합부에서 발생하는 열을 효과적으로 발산시키기 위한 금속, 세라믹

또는 플라스틱등의 용기를 말한다.

RAM Random Access Memory

기억된 정보를 읽어 내기도 하고 다른 정보를 기억시킬수 있는

메모리로 전기가 나가면 기억내용은 지워져 버린다

ROM Read Only Memory

반도체 기억장치의 일종으로 정보를 한번 저장하면 바꿀수 없고, 항상

꺼내어 쓸 수 만 있는 기억 장치

SRAM Static Random Access Memory

DRAM 과 같이 기억소자로 사용되지만, DRAM 은 MEMORY 가 불안정

하여 계속적인 재충전(Refresh)가 필요하나, SRAM 은 전원이

끊어지지 않는 한,MEMORY 가 계속 유지되는 특성이 있으며 속도가

빠르다. (가격이 비싸다)

TFT Thin Film Transistor

절연성 기체에 증착 등으로 반도체 박막을 형성하여 만든 능동 소자.

VRAM(Video RAM) DRAM 의 모든 기능을 수행하면서 특히 고속,

고해상도의 영상신호를 처리할 수 있는 장점이 있어서 앞으로

고해상도의 영상신호 처리에 크게 활용된 전망이다.

CPU PKG 컴퓨터 내에서 논리 또는 산술연산과 명령을 수행하는

중앙처리장치로 IC 로 구성된 Silicon Chip 이다

MODULE 전기적으로 서로 도통되는 PCB 위에 몇 개의 IC 를

장착하여 MEMORY 용량을 확장시키는 방식으로 주로 Computer 및

workstation 에 많이 장착됨.