프로그래밍을 공부하기 위해서는 언어도 필수 이지만 시스템에 대한 이해도 필수 입니다.(...라고 본인은 생각합니다;;) 시스템에서도 핵심은 메모리 인데요...메모리 구조를 제대로 알아야 최적화를 비롯한 자료구조 등의 프로그래밍을 쉽게 공부 할 수 있습니다.

 

 위의 그림은 C에서의 메모리 레이아웃을 나타낸 그림입니다. 아마 프로그래밍을 공부하신 분이라면 한번 쯔~음은 보셨을 것입니다.

 우선 ROM부터 설명하겠습니다. ROM은 일반적인 데스크탑이라면 하드디스크(HDD)일 것이고, 임베디드 시스템이라면 보통 Flash ROM을 말합니다... 컴파일로 생성된 실행 파일이나...시스템이 동작하기 위한 이미지 파일이 ROM에 저장되어 있을 것입니다.

 ROM의 Text 섹션은 보통 프로그램 코드 (함수나 일반 처리문 같은....)와 읽기 전용 데이터(RO_data, 상수 데이터)로 이루어져있습니다. 

 Data 섹션은 읽기 쓰기가 가능한 (RW_data) 데이터가 들어가는데 그 예로 전역 변수나 정적 변수를 들 수 있습니다.

 ROM - Text : Code + RO_data

           Data : RW_data


 RAM은 최근 대부분의 구성이 보호 모드로 가상 메모리를 사용하게 되어있습니다. 물론 실제 모드로 위의 그림과 같이 세그먼트를 분리하여 사용하기도 하지만 그래도 가상 메모리 구조와 별차이 없게 사용하고 있습니다.

 시스템을 구동 할 경우 어셈블리로 스타트업 코드를 구현하다가 C언어의 main()으로 제어를 넘기는데 그 이유가 위와 같이 레이아웃이 설정되어 있어야 하기 때문입니다. 어셈블리로 구현된 스타트업 코드에서 가상메모리 페이지를 관리하는 MMU(Memory Management Unit)를 구동시키거나 세그먼트를 분리해야 C 코드로 제어를 넘길 수 있습니다.

 가상 메모리는 말그대로 보호 모드(말 그대로 각 프로세스. 즉, 메모리에 올라와 실행되는 프로그램마다 각자 고유의 메모리 영역을 침범되지 않게 보호되어야 하는...)로 프로세스마다 32비트 시스템을 경우 4GB(2의 32승)의 가상메모리 영역을 가지게 되고, 각 프로서스마다 공유되는 커널 영역과 프로세스마다 고유한 유저 영역 메모리의 구조를 가지게 됩니다. 실제로 프로그램의 메모리 영역을 안다는 것이 위의 구조 중 유저영역을 이해한다는 것과 같다고 보면 될것입니다. 보통 윈도우즈의 경우 하위(0x0000 0000 ~ 0x7FFF FFFF) 2GB가 유저 영역, 상위 2GB(0x8000 0000 ~ 0xFFFF FFFF)의 커널 영역을 가지고 , 리눅스의 경우 상위 1GB 커널, 하위 3GB 유저 영역을 가집니다. (지역 변수의 경우 위의 그림의 경우 스택에 저장되기 때문에 & 연산자를 이용해 주소 값을 보면, 윈도우즈일 경우 주소가 0x7FFF FFFFF 보다 작으면서 가까운 주소가 출력 될 것입니다.)

 RAM의 Text영역은 ROM의 Text 영역을 그대로 가지고 옵니다. 하지만 임베디드 시스템의 경우 고정된 값이기 때문에 RAM으로 옮길 필요는 없습니다. 그래서 ROM에서 그대로 활용할 경우도 있으며 RAM공간에 여유가 있고 빠른 속도(RAM이 CPU에 가까우므로 빠르죠...)를 필요로 할 경우 RAM에 복사를 해서 사용 합니다.

 Data 영역은 그대로 ROM의 Data 영역을 복사해서 사용합니다.

 bss 영역은 ZI_data(Zero Initialoze). 즉, 초기화 되지 않은 전역 변수나 정적 변수로 구성된 세그먼트 입니다. 아마도 실행 파일과 같은 이미지 파일에서 메타 데이터 정보만 가지고 있다가 실제 RAM에 구성될 때 공간을 확보하는 것 같습니다. 실제 데이터가 없는데 ROM에 공간을 사용하는 것은 낭비니까 당연하겠네요...

 Heap은 동적 메모리가 할당되는 영역입니다. (완전 이진 트리를 나타내는 자료 구조인 Heap과 헛갈리시면 않됨미...) C의 mallloc()이나 C++의 new 할당자로 공간을 확보합니다. 사용 완료 후 해제를 해야하겠지요...이 영역은 단편화(Fragmentation) 문제와 관련된 영역이기도 합니다.

 Stack은 지역 변수를 기억하는 공간으로 LIFO 구조를 가집니다. 이 영역이 다른 영역에 비해서 복잡하면서도 구조를 제대로 이해하면 조금 재미있는 일(?)을 할 수 있습니다. 이 구조를 이해하기 위해서 스택 프레임(Stack Frame)을 한번 쯤 공부해보면 좋습니다.

RAM - Text : Code, RO_data

        Data : RW_data

        bss   : ZI_data

        Heap : 동적 할당 data

        Stack : LIFO구조로 저장되는 지역 변수 data

 

 물론 위의 가상 메모리 구조는 기본틀이고, 심볼 테이블(Symbol Table)과 같은 추가적인 정보를 포함하고 있습니다. 컴파일러의 구조를 한번 공부해보면 도움이 될 것 같네요...


+ Recent posts