initial 램디스크로 부팅하기

고객지원 지식기반 (initrd)
적용 범위

SuSE Linux: 버전 이래로 6.3

Problem:

리눅스 커널이 로드되어 루트 파일시스템("/")이 마운트 되면 프로그램들이 실행되고 추가적 인 커널 모듈들이 추가 기능을 위해서 로드될 수 있습니다.

하지만 루트 파일시스템이 마운트되기 위해서는 특정 조건을 만족시켜 주어야 합니다. 커널 이 루트 파일시스템을 포함하는 장치에 접속하려면 적절한 드라이버를 가지고 있어야 합니 다.(특별히 SCSI 드라이버) 또한 파일시스템을 읽기 위해서는 적당한 코드(ext2, reiserfs, romfs 등)가 있어야 합니다. 게다가 루트 파일시스템이 암호화되어 있다면 키/패스워드를 사용자가 입력해 주어야 할 때도 있습니다.

SCSI 드라이버 문제의 해결에는 여러 가지가 있을 수 있습니다. 모든 필요한 드라이버를 가진 커널을 구할 수도 있지만 드라이버들 간에 잘 융합되지 않을 수 있는 문제가 있습니 다. 그리고 커널이 아주 커지게도 될 것입니다. 다른 방법은 여러 가지 다른 커널을 준비해 서 각 커널에 아주 적은 SCSI드라이버들을 가지게 하는 것입니다. 하지만 이것에도 문제가 있습니다. 필요한 커널의 개수가 아주 많아지게 됩니다. 커널들을 최적화시켜 제공해야 될 때에는 그 문제가 더욱 심각해집니다.(펜티엄 옵티마이즈드, SMP)

SCSI 드라이버들을 모듈로 로딩시키는 접근 방법에도 문제가 있습니다. 이것은 램디스크 초기화 개념과 상반됩니다. 이 개념은 루트 파일시스템이 마운트되기 전에 유저스페이스 프 로그램들을 실행시킬 수 있는 방법을 생성한다는 것입니다.

Concept of the inital ramdisk

초기 램디스크(initdisk또는 initrd라고도 함)로 위에 설명된 문제들을 풀 수 있습니다. 리눅 스 커널은 조그만 파일시스템을 램디스크에 로딩시켜 실제 루트 파일시스템이 마운트되기 전에 이곳에서 프로그램을 실행시킬 수 있는 가능성을 제공합니다. initrd의 로딩은 부트로 더(LILO, loadin 등)에 의해 이루어질 수 있습니다. 이들 부트로더들은 부트 미디아로부터 데이터를 로드하는데 BIOS 루틴만을 필요로 합니다. 부트로더가 커널을 로드시킬 수 있다 면 초기 램디스크도 로드시킬 수 있습니다. 그래서 특별한 드라이버들이 따로 필요없게 됩 니다.

Flow of operation when booting with initrd

부트로더가 커널과 initrd를 메모리로 로드한 다음에 커널을 시작하면서 메모리의 어디에서 initrd를 찾을 수 있는지 커널에 알려 줍니다.

initrd가 압축(보통 압축되어 있습니다.)되어 있다면 커널은 이것을 압축해제해서 임시 루트 파일시스템으로 마운트시킵니다. 그 다음 initrd에 포함된 linuxrc라는 프로그램이 실행됩니 다. 이 프로그램은 커널로 하여금 실제 루트 파일시스템을 마운트시키는데 필요한 모든 작 업들을 해 줍니다. 그리고 linuxrc가 종료하면 임시 initrd가 언마운트되고 실제 루트 파일시 스템이 마운트되면서 부팅이 계속됩니다. 그래서 initrd의 마운팅과 lunuxrc의 실행은 정상적 인 부팅 과정의 짧은 간주곡이라고 볼 수 있습니다.

initrd가 언마운트되지 않는다면 커널은 마운트 포인트를 /initrd로의 변경을 시도합니다. 만 약 이 경로가 존재하지 않으면 에러 메시지가 나옵니다. 이 경우 시스템은 완전한 기능을 하지만 initrd가 차지하는 메모리를 사용할 수 없게 됩니다.

Linuxrc

linuxrc 프로그램은 다른 필요 사항만을 충족시켜 주면 됩니다. 이름이 'linuxrc'이고 initrd의 루트 디렉토리에 위치해 있어야 합니다. 그리고 커넬이 이것을 실행시킬 수 있어야 합니다. 이말은 linuxrc가 동적으로 링크될 수도 있지만 모든 공유된 라이브러리들이 initrd의 /lib하 에서 사용가능해야 한다는 것입니다. 또한 lunuxrc가 쉘 스크립트일 수도 있습니다. 그래서 /bin에 있는 쉘을 필요로 합니다. 결과적으로, initrd는 linuxrc가 실행될 수 있도록 해 주는 최소 리눅스 시스템을 가지고 있어야 한다는 것입니다. 수세 리눅스의 인스톨 과정은 initrd 를 가능하면 작게 만들기 위해서 정적으로 링크된 linuxrc를 사용합니다.(부트 플로피의 공 간은 협소합니다.) Linuxrc는 루트 계정으로만 실행시킬 수 있습니다.

The reall root filesystem

linuxrc가 종료되면 initrd가 언마운트되면서 실제 루트 파일시스템을 마운트시켜 주는 커널 과 함께 정상적인 부팅이 계속됩니다. 이때 어떤 루트 파일시스템이 마운트되는 가는 linuxrc에서 변경해 줄 수 있습니다. 이것은 linuxrc가 /proc 파일시스템만을 마운트시키고 실제 루트 파일시스템의 값을 /proc/sys/kernel/real-root-dev에 수치로 입력하도록 하는 것으로 가능합니다.

Bootloader

대부분의 부트로더(LILO, loadlin, syslinux 등)가 initrd를 처리해 줄 수 있습니다. 부트로더 는 initrd를 다음과 같이 사용하도록 권장됩니다.

1. LILO

다음 라인을 /etc/lilo.conf 파일에 추가시킵니다.
    initrd=/boot/initdisk.gz

여기서 "/boot/initdisk.gz" 파일이 초기 램디스크를 의미합니다. 이것은 압축될 수도 있고 안 될 수도 있습니다.

2. loadlin.exe

다음과 같이 콜합니다.
    loadlin initrd=C:\linux\initdisk.gz

3. syslinux

다음 라인을 syslinux.cfg에 추가시킵니다.

    append initrd=initdisk.gz


Use of initrd at SuSE

System installation

initrd가 사용된 것은 꽤 오래전부터의 일입니다. 사용자는 linuxrc에 모듈을 로드시키고 인 스톨에 필요한 정보(소스 미디엄 등)를 입력시킬 수 있습니다. 그러면 linuxrc는 야스트를 시작하게 되고 야스트는 인스톨을 시작합니다. 야스트가 작업을 끝마치면 linuxrc에 새롭게 인스톨될 시스템이 루트 파일시스템이 어디에 위치하고 있는가를 알려줍니다. 그러면 linuxrc는 이 값을 /proc에 입력시키고 종료를 하고 커넬이 새롭게 인스톨된 시스템을 부팅 시킵니다.

그래서 수세 리눅스를 인스톨하는 동안에 방금전에 인스톨된 시스템을 부팅시키게 되는 것 입니다. 즉 실제적인 리부팅은 현재 동작하고 있는 커널이 시스템에 인스톨된 모듈과 호환 성을 가지고 있을 때에만 가능합니다. 현재 수세 리눅스에서는 인스톨을 위해 단일 프로세 서용 커넬을 사용하기 때문에 시스템에 SMP 커넬과 이와 매치되는 모듈들이 인스톨되어 있어야 합니다. 그리고 모든 모듈들을 사용할 수 있기 위해서는 새롭게 인스톨된 SMP 커널 이 다시 부팅되어져야 합니다.

인스톨된 시스템의 부팅

과거에는 야스트가 인스톨을 위해서 40개 이상의 커널을 제공했었습니다. 이들 커널들은 특 별한 SCSI 드라이버를 각각 가지고 있었습니다. 이것은 부팅을 한 다음에 루트 파일시스템 을 마운트시키기 위해서 필요했었습니다. 그리고 추가적인 드라이버들을 나중에 모듈로 로 드될 수 있었습니다.

현재는 최적화된 커널을 제공하고 있기 때문에 위에 언급한 내용들이 더 이상 적용되지 않 습니다.(이렇게 하려면 커널 이미지가 100개 이상 필요하게 될 것입니다.

그래서 이제는 initrd가 정상적인 시스템을 시작하는데에도 사용되고 있습니다. 메카니즘은 인스톨시와 비슷하지만 여기에 사용되는 linuxrc는 간단한 쉘 스크립트에 지나지 않습니다. 이 스크립트는 특정 모듈들만을 로드시켜 주는 작업을 합니다. 다시 말하면 이 스크립트는 루트 파일시스템에 접속하는데 필요한 SCSI 드라이버를 가진 하나의 모듈이라고 할 수 있 습니다.

initrd 생성

initrd의 생성은 mk_initrd 스크립트로 할 수 있습니다. 수세 리눅스에서는 로드될 모듈들이 /etc/rc.config 파일의 INITD_MODULES 섹션에 명시되어 있습니다. 인스톨이 끝나면 이 변 수는 정확한 값들로 변경됩니다.(linuxrc가 로드된 모듈들을 알기 때문입니다.) 이때 모듈들 이 INITRD_MODULES에 나타나는 순서대로 로드되는 가를 잘 주목해야 합니다. 이것은 SCSI 드라이버가 두 개 이상 사용될 때 특별히 중요합니다. 만약 순서대로 로드되지 않으 면 디스크의 이름이 변경되게 됩니다. 엄밀히 말하면 루트 파일시스템을 접속하는데 필요한 SCSI 드라이버만 로드시키면 충분합니다. 하지만 추가 SCSI 드라이버들을 자동적으로 로딩 되게 하는 것에도 문제가 있습니다.(디스크가 두 번째 SCSI 컨트롤러에 연결되어 있을 때 어떻게 트리거할 수 있겠습니까?) 그래서 인스톨시에 initrd를 사용해서 모든 SCSI 드라이버 들을 로드시키는 것입니다.

현재 사용되는 mk_initrd는 루트 파일시스템을 접속한는데 SCSI 드라이버가 실제로 필요한 지를 체크해 줍니다. 루트 디렉토리(/)가 EIDE 디스크 상에 존재하는 시스템에서 mk_initrd 를 콜해도 initrd를 생성해 주지 않습니다. 왜냐하면, 수세 커넬들이 항상 EIDE 드라이버들 을 가지고 있어서 추가로 필요하지 않기 때문입니다. 하지만 현재 특별한 용도의 EIDE 컨 트롤러의 수가 계속해서 증가하고 있는 추세에 있기 때문에 앞으로는 바로 언급한 경우들에 있어서도 인스톨된 시스템을 부팅시키기 위해서 initrd가 사용될 것으로 보입니다.

중요:

    부트로더에 의한 initrd의 로딩이 우연하게도 커널의 로딩과 유사하게 이루어지기 때문에 (LILO는 맵 파일에서 해당 파일의 위치를 참조합니다.) initrd에 변화가 있을 때마다 LILO를 다시 인스톨해 주어야 합니다. 그래서 mk_initrd를 실행한 다음에는 lilo를 또한 실행시켜 주 는 것이 필요합니다.

수세 리눅스 6.3의 버그들과 문제점

사용자 정의 컴파일 커널

사용자가 직접 컴파일 시킨 커널을 사용하면 다음과 같은 문제들이 일어날 수 있습니다. 관 습적으로 SCSI 드라이버가 커널에 컴파일되는데 initrd가 수정되지 않은 채 있을 수 있습니 다. 그러면 부팅시 다음 상황이 벌어집니다. 커널이 이미 SCSI 드라이버를 가지고 있기 때 문에 하드웨어가 정확히 검색됩니다. 이제 initrd가 같은 드라이버를 로드하려고 시도합니다.

하지만 이때는 initrd가 모듈로 동작합니다. 결과적으로 몇 몇 SCSI 드라이버들의 경우 (aic7xxx가 악명을 떨치고 있습니다.) 시스템이 다운될 수 있습니다. 엄밀히 따지자면 이것 은 커널 버그입니다.(이미 로드된 드라이버를 모듈로 다시 로드하는 것은 불가능합니다. 하 지만 이 문제는 다른 상황(시리얼 드라이버) 등에서도 알려진 문제입니다.

이 문제를 해결하는데는 몇 가지 해결책이 있습니다. 첫 번째는 드라이버를 모듈로 환경 설 정해 주는 것입니다.(그러면 이것이 initrd에 의해서 정확히 로드될 수 있습니다.) 두 번째로 는 /etc/lilo.conf 파일로부터 initrd를 위한 엔트리를 삭제시키는 것입니다. 두 번째 방법과 유사한 방법으로 INITRD_MODULES로부터 드라이버를 제거하고 mk-initrd를 콜할 수도 있 습니다. 이 때 mk_initrd는 initrd가 필요없다는 것을 알게 됩니다.

모듈 파라미터

모듈이 로드되기 위해서 모듈에 파라미터가 전해져야 하는 경우 파라미터를 인스톨후에 잃 어 버릴 수가 있습니다. 이들 파라미터들은 시스템을 부팅하는데 사용되는 initrd에 입력되 어 있지 않습니다. 하지만 다행히도 파라미터를 요구하는 SCSI 드라이버들이 별로 없습니 다. 이 문제에 부딪히면 인스톨 부트 플로피 디스켓으로 시스템을 부팅시켜야 하고 SCSI드 라이버들을 포함하는 커널을 스스로 만들어야 합니다.

하지만 이 문제는 수세 6.4에서 모두 해결되었습니다. initrd로부터 시스템을 시작할 대 모 듈 파라미터가 또한 사용됩니다.

initrd에 들어 있는 네트워크 드라이버

인스톨시 네트워크 드라이버가 로드될 때 이 드라이버들은 INITRD_MODULES에도 입력되고 따라서 initrd에도 로드됩니다. 이 자체로는 에러라고 할 수 없지만 어떠한 경우들에서는 문 제로 이어질 수 있습니다.

1. NE2000 호환 카드: 이 카드의 드라이버들은 추가적인 모듈(8390.o)을 필요로 합니다. 모듈 디펜던시가 현재는 무시되고 있기 때문에 ne.o의 로딩이 실패하게 됩니다. 네트워크 환경 설정시 네트워크 드라이버의 로딩은 kerneld에 의해 트리거됩니다.(이번에는 "modprobe"가 사용되기 때문에 디펜던시가 참조됩니다.) 이렇게 되면 문제가 생깁니다. 첫 번째 로드는 실패하면서 에러 메시지를 내고 두 번째 로드는 eth0=ne 알리아스가 /etc/modules.conf에 정확히 설정되어 있기 때문에 성공합니다.

2. 특정 환경설정의 강제: 네트워크 카드를 풀 듀플렉스 모드로 하고 특정 미디어 타입을 사용하도록 강제하는 것이 필요해도 성공할 수가 없습니다.(예, optons=xxx의 튤립 드라이 버로의 패싱) 왜냐하면 위에서도 언급되었듯이 인스톨시 사용된 파라미터가 나중에 다시 사 용되지 않기 때문입니다.

이 문제도 지금 해결되어 있습니다. 먼저 앞으로는 모듈 파라미터들이 인스톨후에도 다시 사용되고 또한 linuxrc가 INITRD_MODULES에 SCSI 드라이버들만을 입력시켜 줄 것입니다.

추가 정보는 다음 문서들에서 볼 수 있습니다.

/usr/src/linux/Documentation/ramdisk.txt
/usr/src/linux/Documentation/initrd.txt


관련 내용:
o SuSE Linux 6.3 Boot 개념

키워드: BOOT, INITRD, RAMDISK, VFS, SCSI, LILO, LOADLIN

카테고리:

SDB-initrd, Copyright SuSE Linux AG, Nrnberg, Germany - 버전: 22. Feb 2001
SuSE Linux AG - 최근에 만들어진 : 22. Feb 2001 에 의해 pthomas (sdb_gen 1.40.0)