2011년6월28일_예제 p11-9.c, file descriptor(=파일핸들러), 버퍼사이즈에 대한 고찰, HexaView로 코드영역/파일들 읽어 보기, 매직넘버, ELF/PE구조 (임시제목)

 

● 파일을 읽고 쓰는 read( )와 write( ) 함수의 원형

   1:  // fd = 파일디스크럽터, buffer = 파일의 내용을 담을 메모리주소(배열),  size = 버퍼사이즈(한 번에 읽는 양)
   2:  int read(int fd, char *buffer, int size);
   3:  // fd = 파일디스크럽터, buffer = 파일에 쓸 내용이 담긴 메모리주소(배열), size =버퍼사이즈(上同)
   4:  int write(int fd, char *buffer, int size);

 

● 예제 p11-9.c에서 파일의 내용을 읽어 오는 while문

   1:  // int bytes, infd = open("원본파일", 읽기전용(리눅스는 기본 바이너리));
   2:  while(bytes = read(infd, buffer, BUFFERSIZE)) > 0)
   3:  {
   4:      //buffer의 내용을 bytes수 만큼 반복하여 한 문자씩 출력.
   5:      //write( )로 buffer의 내용을 다른 파일로 복사.
   6:  }

read( )로 파일의 내용을 읽어와 읽어 온 문자수 만큼 buffer에 저장하고 읽어 온 문자수를 반환하여 bytes변수에 저장.
BUFFERSIZE는 512로 정의되어 있어 최대 512Bytes를 읽어 올 수 있다.
버퍼크기는 최대 512Bytes를 읽어 올 수 있다는 의미이지 매번 512Bytes를 읽어 온 다는 뜻은 아니다.
파일의 크기가 10Bytes면 10Bytes를 읽어와 buffer에 저장하고 bytes에 10을 대입한 뒤에 처리를 하고,
다음에 파일을 읽게 되면 파일의 끝이므로 -1을 반환하여 while문의 조건인 0보다 크다를 만족하지 못 하므로 반복문을 탈출하게 됨.

 

● 파일을 열 때 고수준함수 fopen( )은 FILE이라는 구조체를 가리키는 포인터변수타입…즉, 주소를 반환하고,
                    저수준함수 open( )은 3, 4, 5, 6…과 같이 번호를 반환한다.
                    이렇게 운영체제에 파일열기를 요청하여 반환되는 값들을 파일디스크럽터(file descriptor)라고 한다.
                    (windows에선 파일핸들러라고 부름)


● 파일 접근 방식

image

이 때까지 실습했던 방식은 순차적접근방식으로 파일커서가 파일의 시작부분에 위치한 상태로 시작하여,
read( )나 write( )로 읽고 쓸 때에 버퍼사이즈만큼 커서가 파일의 끝으로 이동한다.
파일의 중간부분을 읽으려면 처음 부터 읽어 나가야 하는 불편함이 있다.

임의 접근방식은 파일커서의 위치(orgin)를 임의로 정하거나 정해진 값,
SEEK_SET = 파일의 시작,
SEEK_CUR = 현재 위치,
SEEK_END = 파일의 끝,
또는 바이트수만큼 떨어진 위치를 정하여 이동할 수 있다. (Offset값에 따라 기준위치에서 커서가 이동함)

실험을 해보고 보고서를 써야 하나 그러지 못 한점이 잘 못 되었고 이런 게으른 점을 반성해야겠다.

 

● 예제 p11-9.c 소스코드는 파일을 복사하는 프로그램으로 linux명령 cp와 같은 일을 수행한다.
   cp와 이 코드의 공통된 단점이 파일을 복사하는 동안 진행상황을 알 수 없다는 것이다.
   복사하는 동안 %단위로 진행상황을 모니터에 표시해 준다면 큰 용량의 파일을 복사할 때 컴퓨터가 먹통이 되는 상황이 발생..
   하더라도 사용자는 모니터를 보며 심리적인 안정을 취할 수 있게 된다.

● 버퍼사이즈에 대한 고찰…버퍼의 사이즈의 최적값은?
   크면 낭비고, 작으면 속도가 느려진다.
   linux cp명령의 버퍼사이즈는 아마도 가변적일 것이다. 복사할 파일의 크기에 따라 버퍼의 크기가 달라지지 않을까? 몰라;

image  나의 생각으론 디스크포맷시 할당단위크기가 4096Bytes이니 이 조각단위로 읽으면 되지 않을까?


★ man page를 보고 공부하자! (언제 마음이 바뀔지..초반부터 안 하는데 ㅠㅠ)

 

 

 

HexaView로 코드영역, 실행파일 출력해보기


● 코드영역 main( )의 시작부터 100Bytes만큼 출력

image 

log.txt의 내용…깨져나온다.

┌─────┬────────────────────────┬────────┐
│   BASE   │                   Hexa Code                    │   ASCII Code   │
│  Address │00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F │0123456789ABCDEF│
├─────┼────────────────────────┼────────┤
│0x08048400│55 89 E5 81 EC 18 01 00 00 83 C4 F8 6A 64 68 00 │U...........jdh.│
│0x08048410│84 04 08 E8 18 00 00 00 83 C4 10 31 C0 EB 01 90 │...........1....│
│0x08048420│C9 C3 8D B4 26 00 00 00 00 8D BC 27 00 00 00 00 │....&......'....│
│0x08048430│55 89 E5 83 EC 18 8B 45 08 89 45 FC 83 C4 F4 68 │U......E..E....h│
│0x08048440│20 89 04 08 E8 B7 FE FF FF 83 C4 10 83 C4 F4 68 │ ..............h│
│0x08048450│80 89 04 08 E8 A7 FE FF FF 83 C4 10 83 C4 F4 68 │...............h│
│0x08048460│D4 89 04 08 E8 97 FE FF FF 83 C4 10 C7 45 F4 00 │.............E..│
└─────┴────────────────────────┴────────┘

어제는 이쁘게 나왔는데 오늘은 깨져 나온다. 이상해! 이상해! 이상해!

image

# objdump –d main.o

objdump명령으로 오브젝트파일의 기계어 코드를 쉽게 확인할 수 있다.
HexaView로 읽어 온 값과 일치한다!

 

● 실행파일출력 (linux실행파일)

image 


log.txt의 내용…

┌─────┬────────────────────────┬────────┐
│   BASE   │                   Hexa Code                    │   ASCII Code   │
│  Address │00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F │0123456789ABCDEF│
├─────┼────────────────────────┼────────┤
│0xBFFFF714│7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 │.ELF............│
│0xBFFFF724│02 00 03 00 01 00 00 00 10 83 04 08 34 00 00 00 │............4...│
│0xBFFFF734│C8 28 00 00 00 00 00 00 34 00 20 00 06 00 28 00 │.(......4. ...(.│
│0xBFFFF744│1D 00 1A 00 06 00 00 00 34 00 00 00 34 80 04 08 │........4...4...│
│0xBFFFF754│34 80 04 08 C0 00 00 00 C0 00 00 00 05 00 00 00 │4...............│
│0xBFFFF764│04 00 00 00 03 00 00 00 F4 00 00 00 F4 80 04 08 │................│
│0xBFFFF774│F4 80 04 08 13 00 00 00 13 00 00 00 04 00 00 00 │................│
│0xBFFFF784│01 00 00 00 01 00 00 00 00 00 00 00 00 80 04 08 │................│
│0xBFFFF794│00 80 04 08 BE 04 00 00 BE 04 00 00 05 00 00 00 │................│
│0xBFFFF7A4│00 10 00 00 01 00 00 00 C0 04 00 00 C0 94 04 08 │................│

7F 45 4C 46   (.ELF)로 시작한다.

 


● 실행파일출력 (windows실행파일)

너무 길어서 헤더부분 스크린샷을 캡쳐하지 못 하였음.

┌─────┬────────────────────────┬────────┐
│   BASE   │                   Hexa Code                    │   ASCII Code   │
│  Address │00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F │0123456789ABCDEF│
├─────┼────────────────────────┼────────┤
│0xBFFFF714│4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 │MZ..............│
│0xBFFFF724│B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 │........@.......│
│0xBFFFF734│00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │................│
│0xBFFFF744│00 00 00 00 00 00 00 00 00 00 00 00 D0 00 00 00 │................│
│0xBFFFF754│0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 │........!..L.!Th│
│0xBFFFF764│69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F │is program canno│
│0xBFFFF774│74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 │t be run in DOS │
│0xBFFFF784│6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 │mode....$.......│



4D 5A…(MZ)로 시작한다.

이렇게 리눅스 7F 45 4C 46   (.ELF), 윈도우 4D 5A…(MZ) 이렇게 시작하는 코드를 매직넘버라고 부른다.
ELF구조(리눅스 실행파일)와 PE구조(윈도우 실행파일)를 보면 각 코드의 의미와 구조체가 나와 있다.

◎ 매직넘버 : 읽은 파일이 맞는지 확인용. (아스키값은 중요하지 않고 바이너리값이 중요함.)

윈도우 실행파일을 보면 “This is program cannot be run in DOS mode”라는 문자열이 보인다.
예전 DOS모드와 호환을 위해서 있는 부분으로 옛날 버전의 DOS에서 실행하면 안 될 것이다.
옛날 버전 DOS가 없어서 확인은 못 하였다.
이 부분과 시작부분 사이는 비어있다.

 

● 선생님께서 배포하신 HexaView

image

파일의 시작부터 256Bytes만 읽어 오게 되어 있어 시작부분을 캡쳐할 수 있었다.

log.txt의 내용…

Address   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  0123456789ABCDEF
0x00000000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00  MZ*.*...*...**..
0x00000010 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00  *.......@.......
0x00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x00000030 00 00 00 00 00 00 00 00 00 00 00 00 D0 00 00 00  ............*...
0x00000040 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68  ****.***!**L*!Th
0x00000050 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F  is program canno
0x00000060 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20  t be run in DOS
0x00000070 6D 6F 64 65 2E 0D 0A 24 00 00 00 00 00 00 00 45  mode.**$.......E
0x00000080 0A 8D DA 01 6B E3 89 01 6B E3 89 01 6B E3 89 63  ****k***k***k**c
0x00000090 74 F0 89 02 6B E3 89 01 6B E2 89 2D 6B E3 89 7A  t***k***k**-k**z
0x000000A0 77 EF 89 02 6B E3 89 E9 74 E8 89 00 6B E3 89 82  w***k***t**.k***
0x000000B0 77 ED 89 0A 6B E3 89 E9 74 E9 89 33 6B E3 89 52  w***k***t**3k**R
0x000000C0 69 63 68 01 6B E3 89 00 00 00 00 00 00 00 00 50  ich*k**........P
0x000000D0 45 00 00 4C 01 03 00 83 42 09 4E 00 00 00 00 00  E..L**.*B*N.....
0x000000E0 00 00 00 E0 00 0F 01 0B 01 06 00 00 50 00 00 00  ...*.*****..P...
0x000000F0 30 00 00 00 00 00 00 47 17 00 00 00 10 00 00 00  0......G*...*...


● BMP파일을 읽어 보자.

image 

42 4D  (BM)으로 시작한다.

log.txt의 내용…

Address   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  0123456789ABCDEF
0x00000000 42 4D CA 47 06 00 00 00 00 00 36 00 00 00 28 00  BM*G*.....6...(.
0x00000010 00 00 7B 01 00 00 69 01 00 00 01 00 18 00 00 00  ..{*..i*..*.*...
0x00000020 00 00 94 47 06 00 00 00 00 00 00 00 00 00 00 00  ..*G*...........
0x00000030 00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF  ......**********
0x00000040 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x00000050 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x00000060 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x00000070 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x00000080 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x00000090 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x000000A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x000000B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x000000C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x000000D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x000000E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************
0x000000F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ****************

 

● JPG파일을 읽어 보자.

image

4A 46 49 46 (JFIF)가 매직넘버 아닐지?

log.txt의 내용…

Address   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  0123456789ABCDEF
0x00000000 FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 60  ****.*JFIF.***.`
0x00000010 00 60 00 00 FF DB 00 43 00 08 06 06 07 06 05 08  .`..**.C.*******
0x00000020 07 07 07 09 09 08 0A 0C 14 0D 0C 0B 0B 0C 19 12  ****************
0x00000030 13 0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20  *********** $.'
0x00000040 22 2C 23 1C 1C 28 37 29 2C 30 31 34 34 34 1F 27  ",#**(7),01444*'
0x00000050 39 3D 38 32 3C 2E 33 34 32 FF DB 00 43 01 09 09  9=82<.342**.C***
0x00000060 09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 32 32 32  ********2!*!2222
0x00000070 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32  2222222222222222
0x00000080 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32  2222222222222222
0x00000090 32 32 32 32 32 32 32 32 32 32 32 32 32 32 FF C0  22222222222222**
0x000000A0 00 11 08 01 69 01 7B 03 01 22 00 02 11 01 03 11  .***i*{**".*****
0x000000B0 01 FF C4 00 1F 00 00 01 05 01 01 01 01 01 01 00  ***.*..********.
0x000000C0 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09  .......*********
0x000000D0 0A 0B FF C4 00 B5 10 00 02 01 03 03 02 04 03 05  ****.**.********
0x000000E0 05 04 04 00 00 01 7D 01 02 03 00 04 11 05 12 21  ***..*}***.****!
0x000000F0 31 41 06 13 51 61 07 22 71 14 32 81 91 A1 08 23  1A**Qa*"q*2****#

 

● 잘 모르겠으니 파일 포맷에 대해 찾아보자.

BMP파일포맷 링크: http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html

● 파일포맷종합선물세트가 있는 홈페이지

http://www.wotsit.org

image

여기에 접속한 후에.

image

확장자 시작이 B로 시작하는 것을 찾아보자.

 

image

아래로 쭉 스크롤하면 BMP파일포맷이 보인다.
상기의 BMP파일포맷 링크는 Stefan Hetzl님의 것인가?

찾아 보니 실행파일 포맷도 있다.

image

하지만 두려워서 클릭을 하지 못 하였다. 에휴~
공부를 하면 할 수록 모르는 것이 많아지고 두려움이 커지고 있다.

언제 잇힝하는 날이 올까?