 |
|
부트 로더
부트 로더란 무엇인가?
부트 로더(혹은 부트스트랩 로더)는 다른 프로그램을 로드하는 프로그램이다. 부트 로더 크기는 상대적으로 작지만 특수한 기능을 갖는 코드 덩어리로 타깃 시스템에 맞게 만들어져 있으며, 딱 커널을 찾아낼 만큼만 복잡하며 완전한 기능을 갖춘 커널이 아닌 상태로 커널을 로드한다. 서로 다른 시스템들은 서로 다른 다양한 부트 로더를 사용하는데, 데스크톱 PC에서 사용되는 보편적인 거대하고 복잡한 바이오스(BIOS) 프로그램부터 임베디드 시스템에서 일반적인 아주 작고 간단한 프로그램에 이르기까지 다양하다.
간단한 부트 로더
TS-7800은 범상치 않은 간단한 부트 로더로서, 단순히 SD카드나 온보드 플래시의 미리 정해진 파티션에서 간단히 커널을 읽어온다. 점퍼 셋팅을 통해 보드가 온보드 플래시에서 먼저 읽을지 아니면 SD카드에서 읽을지 결정하게 한다. 다른 설정은 없다. 이보다 복잡한 부트 로더(이를테면 데스크톱 PC에서 보통 사용되는 grub 같은 것들)는 부트 시 커널 옵션 등에서 옵션을 갖고 있다. 이 시스템에서는 이전에 설명했듯 커널의 기본 옵션이 컴파일되어야 한다.
커널 옵션을 컴파일 시에 결정해야 한다는 건 임베디드 시스템에서는 당연하다는 게 전형적인 예라 할 수 있지만 데스크톱에서는 불편스러운 제약 사항일 수도 있을 것이다.
커널 형식
커널이 저장되는 형식은 다양하다. 초기 리눅스 커널 바이너리는 이름하여 vmlinux로서 부트 로더가 작업할 파일이었으나 좀처럼 파일이라고 보긴 어려웠다. TS-7800에서는 부트 로더가 두 가지 파일을 사용할 수 있는데 하나는 Image(압축하지 않은 것)이고 하나는 zImage(압축한 것)다. 이 파일들은 커널 트리 내 arch/arm/boot 디렉터리에 생성된다.
사람들은 압축 커널을 zImage 커널이라 지칭하기에 부트 로더가 압축 해제를 해줘야 할 필요가 있을 거라고 기대한다. 사실 zImage는 이보다 훨씬 더 영리하다. zImage 커널은 압축되지 않은 실행 파일로서, 압축된 커널 이미지인 각별히 큰 정적 데이터 객체를 담고 있다. 부트 로더가 로드되고 zImage 실행 파일을 실행하면 이 실행 파일은 커널 이미지의 압축을 풀고 이를 수행한다. 이런 방식으로 부트 로더에 별도 노력을 들이지 않고도 압축의 이점을 최대한 이끌어내는 것이다.
SD카드 구성
SD카드는 도스(DOS) 스타일의 파티션 정보를 담는 MBR 테이블을 필요로 한다. 예제 MBR 테이블을 Technologic의 웹 사이트의 다운로드에서 이용 가능하다. 이 사이트에는 512MB 카드용이 있으나 사용하고자 하는 카드에 맞게 네 번째 파티션의 크기를 쉽게 편집할 수 있다. 처음 세 개 파티션은 각각 4MB이다. 첫 번째 파티션은 용량이 더 작은 카드에는 사용되지 않으며, 두 번째와 세 번째 파티션에는 커널과 초기 램디스크 이미지가 각각 담긴다.
필자의 경우 sfdisk 유틸리티를 사용했는데 반드시 추천하지는 않지만 파티션 경계를 정렬하지 않는 파티션을 생성하기 위해 sfdisk를 묻는다면 괜찮은 것 같다.
초기 커널 설치
TS-7800용 커널은 SD카드의 두 번째 파티션에 직접 써 넣는다. 카드에 대한 정확한 경로는 어떻게 써넣느냐에 따라 다르다. 보통 USB 카드 리더에 카드가 있다면 SD카드는 SCSI 장치로 인식될 것이다. 파일 시스템으로 접근할 수 없을 것임을 명심하자. 커널 그 자체를 파티션에 부어 넣는 것이다. dd 명령으로 생(raw) 데이터를 다음 예처럼 부어 넣는다.
$ dd if=zImage of=/dev/sdd2 bs=16k
93+1 records in
93+1 records out
1536688 bytes (1.5 MB) copied, 0.847047 s, 1.8 MB/s
이 명령으로 생 데이터인 zImage 파일을 /dev/sdd 두 번째 파티션에 16KB 블록 단위로 부어 넣는다.
블록 크기에 대한 약간의 내용
이 명령의 출력을 보면 좀 암호 같다(솔직히 말하면 입력도 그렇다). dd가 구동하면 데이터를 "레코드(records)" 단위로 복사하는데 기본값으로 512바이트 블록이다. 이 명령은 16k의 블록 크기로 지정함을 뜻한다(dd는 16*1024로 이해한다).
dd 명령은 우선 블록 단위로 복사된 데이터의 양을 보고한다. 더하기 기호 뒤의 수는 복사된 부분 블록의 수다. 이 경우 1,536,688은 정확한 블록 크기의 배수가 아니므로 파일의 남은 바이트는 나머지 블록으로 읽힌다(그리고 쓰인다). 이 정보는 대부분의 현대적인 장치에 대해서는 해가 없지만 일부 오래된 장치에서 문제를 진단할 때에는 치명적이다.
블록 크기를 제어할 수 있다는 것(그리고 전송 시 데이터를 재블록할 수 있다는 것)은 테이프 장치 등 특히 고정 크기에 쓰기 작업을 필요로 하는 특수한 여타 매체에 작업할 때에 꽤 유용했으며, 또한 플래시 장치에서도 성능과 신뢰성 이유에서도 도움이 된다.
플래시 매체를 표현하는 커널 장치는 종종 임의 크기의 쓰기를 할 수 있는 반면 하부 장치는 전체 블록으로만 보통 종종 다소 큰 크기(4KB 이상의 크기)로만 동작하는 게 일반적이다. 부분 쓰기를 하기 위해 플래시 장치는 전체 블록의 현재 내용을 추출해 입력 데이터를 수정해서 전체 블록을 플래시해야 한다. 장치가 4KB 블록을 사용하고 512바이트 블록으로 쓰기를 한다면 각 장치 블록은 한 카피에 대해 8번당 재쓰기를 한다. 이렇게 한다는 건 장치 수명에 좋지 않으며 성능에도 나쁘다(동일 파일을 512바이트 쓰기를 한다는 건 필자가 사용하는 플래시 카드 상에서 절반의 속도였다).
커널 부팅
커널 부팅도 간단하다. SD 부트로 점퍼를 세팅하고 시스템에 카드를 넣은 후 전원을 넣는다. 빈 카드라면 예측되는 결과는 이럴 것이다.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)
이런 암호같은 메시지는 커널이 루트 파일 시스템을 발견할 수 없었음을 가리킨다. 이는 루트 파일 시스템을 하나 만들 때가 되었음을 의미한다.
|