728x90
반응형




커널 이미지는 내가 원래 영상처리에서 알던 이미지와 아주 다른 개념이었다.




1. 커널 이미지의 개요 


: 리눅스에서 부팅은 도스나 윈도우의 부팅과 상당히 다르며, 도스나 윈도우의 부팅은 컴퓨터를 쓰고 싶으면 전원을 넣고 부팅과정을 거치게 된다. 그러나 리눅스에서의 부팅은 간만에 있을까 말까 하는 중요한 사건이다. 그래서 부팅 속도가 빠른 것이며, 부팅 과정은 매우 복잡하다.



로더(LILO 또는 loadlin)라고 하는 프로그램은 커널을 메모리에 올려놓는 일을 수행한다. 컴퓨터에 전원이 들어오고 나면 제일 먼저 디스크의 첫 부분을 읽어서 로더를 실행시킨다. 



로드는 커널 이미지의 위치를 알고 있어서 스스로 커널 이미지를 찾아서 메모리에 올려 놓는다.







2. 커널 이미지란?


: 커널이 하나의 파일로 디스크에 저장되어 있는 것이다. 커널은 원래 파일에 저장되어있는 것이 아니라 컴퓨터가 꺼지기 전까지는 항상 메모리에 존재한다. 그러므로 디스크에 저장되어있는 파일은 커널 그 자체는 아니고 커널의 내용을 담고 있는 것이다. 



대부분의 리눅스 시스템에서는 이러한 커널 이미지는 압축된 형태로 사용된다. 첫번째 이유는 디스크 공간을 낭비하지 않기 위해서이고, 두번째 이유는 로딩 시간을 줄이기 위해서이다. 



커널 내부에 설치되어있는 기능들과 현재 설치되어있는 하드웨어를 점검하고 인식하는 과정이 화면에 나오는데, 이 때 출력된 내용은 dmesg 라는 명령을 통해서 다시 볼 수 있다. 



~$ dmesg | less 


위 명령어는 한 화면씩 끊어서 보여주는 명령어이다.







3. 커널 이미지 파일의 구조


: 커널을 컴파일하면 최종 커널 이미지 파일이 압축되어 있다. 이러한 커널 이미지는 LILO가 메모리에 커널을 읽어 올리고 실행해주게 된다. 


커널 이미지 파일의 구조는 아래와 같으며, zImage 와 bzImage 커널 구조는 같다. 단지 메모리에 올려지는 위치나 동작 방식이 약간 차이가 있기 때문에 감안된 각각에 맞는 코드가 사용될 뿐이다.





그림에서 회색 부분이 리눅스 커널이고, 압축되어있는 상태이다. 


여기에 압축을 풀어주기 위한 head 와 misc 가 앞부분에 붙어있고, 다시 이 한 덩어리의 이미지에 메모리에 올려진 커널의 압축이 제대로 풀리도록 준비하는 "setup"과 부팅 시 사용되는 "bootsect"가 붙어서 최종 커널 이미지 파일이 만들어진다.


bbootsect나 bsetup 앞에 붙은 b는 bzImage의 앞에 붙은 b와 같은 의미로 "big kernel"을 의미한다.


LILO에 의해 부팅이 시작되면 LILO는 bzImage를 하드 디스크에서 읽어 메모리에 올려놓고 LILO에 의한 부팅일 경우 필요없는 bbootsect를 건너 뛴 bsetup에서부터 실행되도록 해준다. LILO의 역할은 bsetup에 실행 권을 넘겨주는데 까지이다. 


실행된 bsetup은 메모리 셋팅을 마치고 압축된 커널 이미지의 압축을 풀기위한 코드로 실행을 옮긴다.


"head + misc"로 표시된 부분이고, 이곳이 실행되면 piggy.o는 압축이 풀려 실행 가능한 리눅스 커널이 메모리에 존재하게 된다. 압축이 풀릴 때 화면에 "Uncompressing Linux ..." 라는 메세지가 출력된다.


압축이 풀렸다고해서 바로 커널을 실행하는 것은 아니고, 메모리 낭비를 막기 위한 정리를 한번 하고 나서 커널이 실행된다. 압축이 풀리고 나면 처음 LILO에 의해 읽혀진 커널 이미지는 필요없게 된다. 그러므로 이부분을 남겨두면 메모리 낭비가 일어나게 되므로 압축 풀린 커널 이미지를 옮겨와 되도록 많은 메모리를 사용하도록 한 후 커널을 실행해 준다. 커널이 실행되기 시작하면 "ok, booting the kernel."이라는 메세지가 출력되고, 커널에 의한 출력이 화면에 나타나게 된다. 







4. zImage 와 bzImage의 차이


: 커널의 크기가 너무 커서 압축 후에도 일정 크기를 넘어가면 zImage 대신 bzImage를 사용해야한다. 


왜냐하면 PC가 처음에 만들어질 땐 OS로 도스가 사용되었고, 마이크로소프트사의 빌게이츠는 640KB면 충분하다고 했다. 처음 PC가 만들어질 때의 CPU는 8086으로 16bit CPU 였다. 이 프로세서가 지원하는 최대의 메모리는 1MB였기 때문에 모든 어드레스 스페이스가 1MB 내로 제한됐다. 그러므로 램을 640kb 사용하고 나머지 영역엔 MGA, VGA와 같은 다른 디바이스를 할당해 줬다.


문제는 여기서 시작되는데 AT시절의 PC 기본 구조는 현재까지도 계속 유지되고 있기 때문에 PC가 처음 부팅되면 하위 1MB 만을 사용한다고 생각하면 된다. 보호모드라고 알고 있는 386 이상의 cpu가 가진 기능을 사용하지 않고 리얼모드란 8086 호환 모드를 사용하기 때문인데 이는 OS가 보호모드를 사용할 상태를 만들고 전환하기 전까지는 계속 리얼모드로 남아있기 때문이다.


리눅스 커널의 크기가 커서 커널을 읽어들이는 프로그램 크기나 시스템에서 사용되는 약간의 메모리를 제외한 나머지 램의 빈공간에 읽어 들이지 못하면 하위 1MB가 아니라 그 이상의 연속된 메모리에 커널을 읽어 들이고 압축을 푸는 등의 일을 해야할 것이다. 반대로 남은 용량에 커널이 들어갈 수 있다면 당연히 읽어 들이고 압축을 풀면 끝날 것이고...


이렇게 메모리에 처음 적재되고 압축 풀리고 하는 절차와 위치가 다르기 때문에 zImage와 bzImage로 나뉜 것이고 커널 이미지 파일의 앞부분 bootsect와 setup이 각각에 따라 맞는 것으로 합쳐지게된다. 그리고 bzimage의 경우 하위 1M는 사용하지 못하는데 리눅스에선 그렇다.


컴파일 단계에서 make zImage 했을 경우 System is too big. Try using bzImage or modules. 라고 에러가 난다면 더 많은 부분을 module로 만들거나 bzImage를 사용해야한다.



참고로 boot.img 와 system.img 는 다음과 같은 구조로 구성된다고 한다. 



boot.img = boot header + Linux kernel + ramdisk/rootfs 

system.img = Android user space applications and libraries




참고자료 1 : http://www.linuxlab.co.kr/docs/5-2.htm

참고자료 2 : http://jhkim3624.tistory.com/83?category=605941

참고자료 3 : https://wiki.kldp.org/KoreanDoc/html/EmbeddedKernel-KLDP/kernel-image-file-structure.html

참고자료 4 : http://egloos.zum.com/taehyo/v/4020820

728x90
반응형

'Programming > Linux' 카테고리의 다른 글

[Linux] dmesg 명령어  (1) 2018.08.21
[Linux] 부트로더  (0) 2018.08.21
[Embedded linux] timeconst.pl 에러 해결법  (2) 2018.08.05
[Embedded linux] 임베디드 리눅스 개념  (0) 2018.08.05
[Linux] .bashrc 수정 후 적용  (0) 2018.08.05