3. 루프백 루트 디바이스 만들기

이제 루프백 디바이스를 만드는 일반적인 원리를 설명하겠습니다.

3.1. 필요한 것들

루프백 루트 디바이스를 만들려면 다음 몇가지가 필요합니다.

가장 중요한 것은 우리의 작업에 사용할 리눅스 시스템입니다. 루프 디바이스는 오직 리눅스에서만 제작할수 있습니다. 이 리눅스 시스템은 커널 컴파일이 가능해야 합니다.

일단 루프백 디바이스가 만들어지면 이것은 매우 덩치큰 파일 한개가 됩니다. 필자는 80 MB 짜리 파일 한개를 사용했습니다. 하지만 X 터미널을 돌릴 생각이라면 이걸로도 부족하며 훨씬 많은 용량이 필요합니다. 이 파일은 최종적으로는 DOS 파티션으로 복사될 것입니다. 따라서 이 작업을 위해서는 네트웍을 쓰든지 아니면 상당수의 플로피 디스켓이 필요할 것입니다.

필요한 소프트웨어는 다음과 같습니다.

이 모든 것들은 최근의 리눅스 배포본에는 기본적으로 들어있습니다.

3.2. 리눅스 커널을 만들기

필자는 리눅스 커널 버전 2.0.31 을 써서 루프백 디바이스를 만들었습니다. 다른 버전들도 물론 됩니다만 최소한 다음의 옵션들은 가지고 있어야만 합니다.

필요한 커널 옵션들은 다음과 같습니다.

처음의 두가지는 램디스크 디바이스와 초기 램디스크 디바이스를 위한 것입니다. 그다음 것은 루프백 화일시스템을 위한 것입니다. 마지막 두개는 도스 파티션을 마운트하는데 필요한 것입니다.

모듈을 사용하지 않는 커널을 만드는게 가장 쉬운 방법입니다. 하지만 원하신다면 필자는 해보지 않았지만 모듈을 쓸수도 있을 것입니다. 만일 모듈이 사용된다면 최소한 위의 옵션들만은 모듈로 설정되서는 안되며 커널내에 포함시켜야 합니다.

커널 버전에 따라서는 커널 패치가 필요할 수도 있습니다. 루프백 디바이스를 루트 파일시스템으로 사용할수 있게 해주는 패치는 무척 간단합니다.

2.0.x 커널의 /init/main.c 파일에 아래처럼 수정된 한 라인을 덧붙여야 합니다. 이 라인은 "loop", 0x0700 입니다.

static void parse_root_dev(char * line)
{
	int base = 0;
	static struct dev_name_struct {
		const char *name;
		const int num;
	} devices[] = {
		{ "nfs",     0x00ff },
		{ "loop",    0x0700 },
		{ "hda",     0x0300 },

...

		{ "sonycd",  0x1800 },
		{ NULL, 0 }
	};

...

}

2.2.x 커널들은 /init/main.c 파일에 다음 세줄이 추가되어야 합니다. 추가되는 라인들은 "loop", 0x0700 과 그 위아래 한줄씩들입니다.

static struct dev_name_struct {
	const char *name;
	const int num;
} root_dev_names[] __initdata = {
#ifdef CONFIG_ROOT_NFS
	{ "nfs",     0x00ff },
#endif
#ifdef CONFIG_BLK_DEV_LOOP
        { "loop",    0x0700 },
#endif
#ifdef CONFIG_BLK_DEV_IDE
	{ "hda",     0x0300 },

...

	{ "ddv", DDV_MAJOR << 8},
#endif
	{ NULL, 0 }
};

일단 커널 설정이 끝나면 컴파일해서 zImage 파일을 만들어야 합니다(make zImage 명령). 컴파일이 끝나면 이 파일은 arch/i386/boot/zImage 에 위치할 것입니다.

3.3. 초기 램디스크 디바이스 만들기

초기 램디스크는 루프백 디바이스를 사용해 아주 쉽게 만들수 있습니다. 아래의 명령들을 실행시키기 위해서는 루트 권한을 가져야 합니다. 루트의 디렉토리(/root)에서 실행한다고 가정하겠습니다.

mkdir /root/initrd
dd if=/dev/zero of=initrd.img bs=1k count=1024
mke2fs -i 1024 -b 1024 -m 5 -F -v initrd.img
mount initrd.img /root/initrd -t ext2 -o loop
cd initrd
[create the files]
cd ..
umount /root/initrd
gzip -c -9 initrd.img > initrdgz.img

위의 단계들을 해설하면 다음과 같습니다.

  1. 초기 램디스크를 위한 마운트 포인트를 만들어 줍니다. 디렉토리만 만들어 주면 됩니다.

  2. 필요한 크기의 빈 화일을 만듭니다. 필자는 1024 KB 를 사용하는데 사용자의 필요에 따라 다소 가감해도 좋습니다(크기를 결정하는 것은 제일 마지막 파라메터입니다).

  3. 빈 파일 위에 ext2 파일 시스템을 만듭니다.

  4. 루프백 디바이스를 사용해 마운트 포인트에 파일을 마운트합니다.

  5. 마운트된 루프백 디바이스로 이동합니다.

  6. 필요한 파일들을 만듭니다(자세한 것은 아래에).

  7. 마운트된 루프백 디바이스에서 빠져나옵니다.

  8. 디바이스를 언마운트합니다.

  9. 나중에 사용할 수 있도록 압축된 버전으로 만듭니다.

초기 램디스크에 들어갈 내용물

램디스크에 넣어두어야 할 파일들은 될수있는 한 적은게 좋습니다. 하지만 필요한 명령어들을 수행할 수는 있어야 겠지요.

필자가 사용하는 초기 램디스크의 내용은 아래와 같습니다. 파일시스템의 오버헤드까지 합쳐 약 800 KB 정도가 됩니다.

total 18
drwxr-xr-x   2 root     root         1024 Jun  2 13:57 bin
drwxr-xr-x   2 root     root         1024 Jun  2 13:47 dev
drwxr-xr-x   2 root     root         1024 May 20 07:43 etc
drwxr-xr-x   2 root     root         1024 May 27 07:57 lib
-rwxr-xr-x   1 root     root          964 Jun  3 08:47 linuxrc
drwxr-xr-x   2 root     root        12288 May 27 08:08 lost+found
drwxr-xr-x   2 root     root         1024 Jun  2 14:16 mnt

./bin:
total 168
-rwxr-xr-x   1 root     root        60880 May 27 07:56 ash
-rwxr-xr-x   1 root     root         5484 May 27 07:56 losetup
-rwsr-xr-x   1 root     root        28216 May 27 07:56 mount
lrwxrwxrwx   1 root     root            3 May 27 08:08 sh -> ash

./dev:
total 0
brw-r--r--   1 root     root       3,   0 May 20 07:43 hda
brw-r--r--   1 root     root       3,   1 May 20 07:43 hda1
brw-r--r--   1 root     root       3,   2 Jun  2 13:46 hda2
brw-r--r--   1 root     root       3,   3 Jun  2 13:46 hda3
brw-r--r--   1 root     root       7,   0 May 20 07:43 loop0
brw-r--r--   1 root     root       7,   1 Jun  2 13:47 loop1
crw-r--r--   1 root     root       1,   3 May 20 07:42 null
crw-r--r--   1 root     root       5,   0 May 20 07:43 tty
crw-r--r--   1 root     root       4,   1 May 20 07:43 tty1
crw-r--r--   1 root     root       1,   5 May 20 07:42 zero

./etc:
total 3
-rw-r--r--   1 root     root         2539 May 20 07:43 ld.so.cache

./lib:
total 649
lrwxrwxrwx   1 root     root           18 May 27 08:08 ld-linux.so.1 -> ld-linux.so.1.7.14
-rwxr-xr-x   1 root     root        21367 May 20 07:44 ld-linux.so.1.7.14
lrwxrwxrwx   1 root     root           14 May 27 08:08 libc.so.5 -> libc.so.5.3.12
-rwxr-xr-x   1 root     root       583795 May 20 07:44 libc.so.5.3.12

./lost+found:
total 0

./mnt:
total 0

유일하게 복잡한 단계는 dev 의 디바이스들에 관한 것입니다. mknod 프로그램을 써야 이 디바이스들을 만들수 있는데, 현재 시스템의 /dev 에 있는 디바이스들의 파라메터를 그대로 베끼면 됩니다.

/linuxrc 파일

아래의 예에서는 msdos 파티션으로서 /dev/hda1 을 마운트합니다. 마운트에 성공하면 /dev/loop0 에 /linux/linuxdsk.img 를 지정하고 /dev/loop1 에 /linux/linuxswp.img 을 지정합니다.

#!/bin/sh

echo INITRD: Trying to mount /dev/hda1 as msdos

if /bin/mount -n -t msdos /dev/hda1 /mnt; then

   echo INITRD: Mounted OK
   /bin/losetup /dev/loop0 /mnt/linux/linuxdsk.img
   /bin/losetup /dev/loop1 /mnt/linux/linuxswp.img
   exit 0

else

   echo INITRD: Mount failed
   exit 1

fi

첫번째 디바이스 /dev/loop0 는 루트 디바이스가 되고 두번째 디바이스 /dev/loop1 은 스왑 공간이 됩니다.

부팅종료후 루트권한이 아닌 일반 사용자가 도스파티션에 쓰기가능하려면 대신 mount -n -t msdos /dev/hda1 /mnt -o uid=0,gid=0,umask=000,quiet 을 써야 합니다. 이것은 도스 파티션에 대한 모든 액세스를 루트권한으로 변환시켜 퍼미션 문제를 해결합니다.

3.4. 루트 디바이스 만들기

당신이 사용할 루트 디바이스는 linuxdsk.img 이라는 파일입니다. 위의 초기 램디스크 제작과 똑같은 방법으로 만들면 되는데, 다만 이 파일은 훨씬 큽니다. 원하는 어떤 리눅스 시스템이라도 이 디스크위에 설치할 수 있습니다.

가장 쉬운 방법은 현재의 리눅스 시스템을 그대로 이리로 복사해넣는 것입니다. 다른 방법으로는 이 위에다 새로운 리눅스 시스템을 인스톨하는 것입니다.

여기까지 다 완료했다면 이제 다음의 몇가지 자잘한 수정을 해주어야만 합니다.

/etc/fstab 파일은 반드시 루트파티션과 스왑파티션이 초기램디스크로 셋업된 루프 디바이스들임을 기록하고 있어야만 합니다.

/dev/loop0     /      ext2   defaults 1 1
/dev/loop1     swap   swap   defaults 1 1

이는 진짜 루프 디바이스가 사용될 때 커널이 루트 디바이스의 위치를 혼동하지 않도록 해줍니다. 또한 스왑 공간이 보통의 일반적인 스왑 파티션처럼 사용되게 해줍니다. 이들 이외의 또다른 루트 디바이스나 스왑 파티션에 대한 지정이 있어서는 안됩니다.

리눅스가 가동된 후 도스파티션을 읽으려면 몇가지 추가적인 작은 수정이 필요합니다.

/initrd 이라는 디렉토리를 만들어 주십시오. 이것은 루프백 루트 파일시스템이 일단 마운트 된 후 초기 램디스크가 마운트되는 위치입니다.

/DOS 같은 심볼릭 링크를 만들어 진짜 도스 파티션이 마운트 되는 /initrd/mnt 로 링크시키십시요.

디스크들을 마운트시키는 스크립트 한줄을 rc 파일에 추가하세요. 이는 mount -f -t msdos /dev/hda1 /initrd/mnt 같은 명령이면 됩니다. 이것은 도스 파티션을 가짜(fake)로 마운트시키는 것인데 이렇게 하면 모든 프로그램들(가령 df)이 도스 파티션이 여기에 있는 것으로 알게됩니다. 만일 당신이 /linuxrc 파일내에서 다른 옵션들을 썼다면 필히 여기에도 그것들을 사용해야 합니다.

루트 디바이스상에 커널이 있을 필요는 전혀 없습니다. 왜냐하면 커널은 이미 그전에 로드됐기 때문이다. 하지만 당신이 커널 모듈을 사용한다면 모듈들을 루트디바이스에 포함시켜야 합니다.

3.5. 스왑 디바이스 만들기

당신이 사용할 디바이스는 linuxswap.img입니다 이 스왑 디바이스는 극히 간단하게 만들수 있습니다. 위에서처럼 빈 파일 하나를 초기 램디스크용으로 만든 후 mkswap linuxswap.img 해서 초기화시키십시오.

스왑 공간의 크기는 설치한 시스템으로 당신이 무슨 일을 할것인가에 따라 다릅니다. 하지만 필자는 8 MB 부터 당신이 가진 램용량 사이의 값을 추천하겠습니다.

3.6. MSDOS 디렉토리 만들기

사용될 파일들을 도스파티션상으로 옮겨야 합니다.

C:\LINUX 라는 도스 디렉토리에 필요한 파일들은 다음과 같다.

3.7. 부트 플로피 만들기

사용될 부트 플로피는 단순한 보통의 도스포맷 플로피 한장입니다.

이것은 도스상에서 format a: /s 명령으로 만듭니다.

이 디스크 위에 아래와 같은 AUTOEXEC.BAT 파일과 커널, 압축된 초기 램디스크, LOADLIN 실행화일을 복사해 넣습니다.

AUTOEXEC.BAT 파일은 아래의 한줄을 포함해야만 합니다.

\loadlin \zImage initrd=\initrdgz.img root=/dev/loop0 ro

이것은 사용할 커널이미지, 램디스크 이미지, 초기 램디스크가 끝난후의 루트 디바이스, 읽기전용으로 마운트되는 루트 파티션을 지정한 것입니다.