티스토리 뷰


[커널 컴파일] 우분투 14.04환경에서 qemu에 ARM리눅스 에뮬레이터 환경 만들기

컴파일과 qemu는 우분투 14.04 환경에서 진행했습니다.

참조: 원문 포스팅

이 포스팅은 위 포스팅을 우분투 14.04에 맞게 재구성하면서 한글로 읽기 쉽게 번역도 하고, 제 나름의 주석도 달아놓은 글입니다. 우선 리눅스 소스코드를 받아야합니다. 최근 리눅스 소스는 github에 관리되고있으므로, git을 이용해 다운받을 수 있습니다.

1. Prebuilt 패키지 설치

일단 시작하기 전에 git을 포함하여, 실습에 필요한 최소 패키지를 먼저 설치하고 갑시다. git과 git의 상태를 GUI로 관리할수 있는 툴, 빌드에 필요한 컴파일러, qemu를 설치하겠습니다.

아, curses의 라이브러리도 필요합니다. curses는 CLI의 환경인 shell을 마치 GUI환경인것처럼 만들어주는 라이브러리입니다.

$ sudo apt-get install git gitk build-essential libncursesw5-dev g++-arm-linux-gnueabi qemu-system-arm

예전에는 qemu같은 에뮬레이터도 소스코드를 다운받아서 직접 빌드해야 했지만, 최신 우분투 버전에는 패키지를 포함하고 있습니다. 버전도 2.0대로 비교적 높습니다. (2014년 릴리즈버전)

2. 리눅스 소스코드 다운로드

이제 리눅스 커널 소스코드를 다운로드 받아야됩니다. git을 이용합시다!

$ git clone https://github.com/torvalds/linux.git

리눅스 커널 4.0에 이르러 코드의 양이 엄청나졌기 때문에 굉장히 오래걸립니다.. 용량으로는 약 600MB 정도 되는 것 같고, 라인수로는 1500만줄이 넘는다고 합니다.

3. 커널 빌드

리눅스 코드를 전부 다운로드 받았으면 이제 리눅스 소스코드 디렉토리로 이동하여 빌드를 해봅시다.

$ cd linux
$ make ARCH=arm versatile_defconfig
$ make ARCH=arm menuconfig

3.1. 빌드 설정

make ARCH=arm menuconfig 를 실행하게 되면, 아래와 같은 화면이 나타납니다.

모든 그림은 클릭하면 커집니다.

이 메뉴를 통해서 본인에게 필요한 기능만을 선택하여 추가/제거 하여 나에게 최적화된 커널을 컴파일 해낼 수 있습니다. 뭐, 위에 링크한 블로거의 포스팅 원문을 받아 쓰고 있는 것이니까 원문의 저자가 했던 설정 그대로 가겠습니다.

1. Enable loadable module support 제거

아래 방향키를 이용하여 Enable loadable module support로 커서를 이동 후, 스페이스바를 눌러주면 * 모양이 제거됩니다.

2. Kernel Features로 이동

지금 제 커서가 위치한 Kernel Features로 커서를 이동하여 엔터키를 누르면, 서브메뉴로 들어가게 됩니다.

3. Use the ARM EABI to compile the kernel 적용

Use the ARM EABI to compile the kernel 에 커서를 위치후, 만약 * 모양이 없다면 스페이스바를 눌러서 *모양을 만들어줍니다.

4. 저장 (Save & Exit)

좌우 방향키를 누르면 맨 아래 쪽에 <select> <exit> <help> <save> <load> 메뉴에서 움직일 수 있습니다. Save를 하시고, Exit을 눌러 나옵니다. 서브메뉴에 들어와 있기 때문에 Exit을 두번 하셔야 나갈 수 있습니다. 눈치채셨겠지만, *로 표시된 모듈들만 컴파일 시 포함됩니다.

이제 모든 설정이 끝났습니다. 본격적으로 커널 빌드를 해보도록 하죠 :)

3.2. 커널 빌드

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- all

여러분들 모두 저와 똑같이 우분투 14.04에서, 똑같은 패키지를 가지고 설치한다면 위의 명령어를 입력하시면 됩니다. 옛날 우분투 버전 같으면 arm-none-linux-gnueabi- 를 입력하셔야 하는 것 같더군요. (블로그의 원문이 그렇게 되어 있습니다.)

만약, 이도저도 아니시면 직접 확인하는 방법은 /usr/bin/ 아래에 gcc관련 바이너리들이 위치하고 있습니다. 사실 우분투 14.04의 arm gcc의 풀네임은 arm-linux-gnueabi-gcc 입니다.

위의 CROSSCOMPILE 옵션에는 gcc의 prefix만 넣어주는 셈이죠. 다시 말해서 본인이 arm컴파일러 이름이 너무 길어 alias를 이용하여, arm-gcc 따위로 쓰고 계시다면요. CROSSCOMPILE=arm- 까지만 해주면 되는 겁니다.

조금 기다리면 빌드가 완료됩니다. 거의 아무 피처도 포함시키지 않았기 때문에 빌드는 빨리 되는 편입니다.

4. init 프로그램 작성

커널 빌드는 완료되었으니, init 프로그램을 띄워보겠습니다. 여러분이 예측하시는 ubuntu의 1번 pid인 그 init이 맞습니다.

물론 대단히 복잡한 유저프로그램이지만, 전 아주아주 간단하게 만들예정입니다. :) 원문의 블로거가 했던 방식 고대로요. ㅎㅎ

#include <stdio.h>

int main(int argc, char* argv[])
{
    printf( "\n" );
    printf( "My ARM Init!!!\n" );

    while( true );

    return 0;
}

어때요, 참 쉽죠? 프로그램 설명은 안드리겠습니다. 한 번 arm gcc로 컴파일 해봅시다.

$ arm-linux-gnueabi-gcc -static init.c -o init

이제, 파일 시스템을 만들어 복사해주는 cpio를 이용하여 init을 svr4라는 파일 시스템위에 앉혀 볼 겁니다. svr4는 최고로 히트했던 유닉스 중 하나인 Unix System V Release 4 (SVR4)의 파일시스템입니다.

$ echo init | cpio -o --format=newc > initrd

다 됐습니다. 이제 qemu를 통해 실행해보도록 합시다. 현재의 디렉토리 위치는 리눅스 소스코드의 루트입니다. 아 그리고, 커널의 이미지는 arch/arm/boot/zImage 로 있습니다.

$ qemu-system-arm -M versatilepb -m 128M -kernel arch/arm/boot/zImage -initrd initrd -append "root=/dev/ram rdinit=init"

실행결과

QEMU 화면 하단쯤에 My ARM Init!!! 이라는 글자가 잘 보이나요? 성공적으로 init 프로그램을 부팅했습니다 :)

물론 키보드고 마우스고 아무것도 되지 않습니다.... 이건 추후 포스팅에..

5. 참고

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

댓글
  • 프로필사진 늑대랑 GDB로 ARM 커널 디버깅에 성공했습니다. ^^
    아래에 추가로 써놓겠습니다.

    커널 컴파일시 추가 셋팅
    $ make ARCH=arm menuconfig

    Kernel hacking --> Compile-time checks and compiler option --> Compile the kernel with debug info 별표 체크


    arm gdb 설치
    $ sudo apt-get -o Dpkg::Options::="--force-overwrite" install gdb-arm-none-eabi

    qemu에 -s -S 디버깅 옵션 줘서 실행 시키기
    $ qemu-system-arm -s -S -M versatilepb -m 128M -kernel arch/arm/boot/zImage -initrd initrd -append "root=/dev/ram rdinit=init"

    gdb 실행(디버깅)
    $ arm-none-eabi-gdb ./vmlinux


    GDB shell에서 target remote localhost:1234 명령을 친다.
    (gdb) target remote localhost:1234

    start_kernel 에 브레이크 포인트 셋팅
    (gdb) b start_kernel

    디버깅 시작.
    (gdb) c

    소스 확인
    (gdb) list
    493 vmalloc_init();
    494 ioremap_huge_init();
    495 }
    496
    497 asmlinkage __visible void __init start_kernel(void)
    498 {
    499 char *command_line;
    500 char *after_dashes;
    501
    502 /*
    (gdb)
    2015.08.10 18:29 신고
댓글쓰기 폼
1 ... 10 11 12 13 14 15 16 17 18 ... 45