· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
User Mode Linux

User Mode Linux HOWTO


작성 : User Mode Linux Core Team

2005.1.15 (토) 00:52:30 EDT

번역 : 김남형

2005.9.8 (목) 12:04:00 KST


이 문서는 Jeff Dike 의 User Mode Linux 의 사용법을 설명한다: User Mode Linux 란 리눅스 커널을 일반 리눅스 프로세스처럼 포팅한 것이다.



1. 소개

User Mode Linux 에 온것을 환영한다. 앞으로 즐거운 일들이 가득할 것이다..

1.1. User Mode Linux 란 무엇인가?

User Mode Linux 는 리눅스내에서 리눅스를 실행할 수 있도록 해주는 것이다! 이로써 전혀 새로운 것들을 실험해 볼 수 있는 힘을 갖게 된다. User Mode Linux 는 리눅스를 가상화해서 (혹은 - 일부 사람들이 말하는 것처럼 - 시뮬레이트해서) 리눅스 전체를 그저 보통 프로세스를 실행시키는 것처럼 실행할 수 있도록 해준다.

이미 이와 비슷한 기능을 들어보았을 지도 모른다. 동일한 (혹은 서로 다른) 운영체제를 중첩 (nest) 하기 위한 프로젝트가 몇가지 있다: Linux on Linux, Windows on Linux, Linux on Windows, Linux/s390 on Linux/anythingelse 등등. 혹은 그냥 x86 on anything, 즉 'x86' 프로그램 (역주: 아마도 Bochs나 QEMU같은 프로세서 에뮬레이션 프로젝트) 이 리눅스 등의 운영체제를 부팅 하도록 만든 프로젝트도 있다.

x86과 관련된 부분에 수 많은 노력이 집중되었다. 이 HOWTO 문서의 마지막 부분에서 대안 (alternative) 프로젝트들의 리스트를 보게 될 것이다. 만약 당신의 목적이 단지 x86 리눅스 상에 또다른 x86 리눅스를 거의 손보지 않고 최대한 빨리 실행하는 것이라면 아마도 UML (User Mode Linux) 보다는 이런 프로젝트들 중 하나가 더 나을 것이다.

1.2. User Mode Linux 는 무엇이 다른가?

User Mode Linux (UML) 은 다른 모든 (상용이든 무료이든) 리눅스 가상화 프로젝트와는 다르다. UML 은 가능한한 자신을 일반적인 프로그램과 동일하게 표현하도록 노력한다. 다음은 그러한 철학하에 이루어진 결과들을 보여준다:

  1. Good speed with few compromises. UML 은 호스트 머신에서 실행되는 다른 컴파일된 프로그램처럼 동작하기 위해 native machine code 를 따른다. 그러므로 소프트웨어적으로 전체 하드웨어 아키텍처를 구현한 이식성있는 가상화 모델에 비해 훨씬 빠르게 동작한다. 또한, UML 은 특정 CPU 의 기능을 사용한 가상 시스템과 달리 극심한 하드웨어 의존성에 구애받지 않는다. UML 에서 실행되는 응용 프로그램은 일반적으로 호스트 시스템에서 실행되는 것보다 최대 20% 정도의 지연이 일어나지만 최신의 하드웨어와 효율적인 시스템 디자인에서는 이 정도는 무시될 수 있다.
  2. Futureproof. 매번 리눅스가 개선될때마다 리눅스 안에서 실행되는 프로그램들에게 이득을 주는 뭔가 새롭고 똑똑한 기능들이 제공되는데, UML은 자동적으로 이런 이득을 본다. 예컨데, 소프트웨어 중지 (suspend), SE Linux 와 같은 잘 세분화된 보안 관리, 새로운 파일 시스템 기능, 크고 빠른 하드웨어의 지원 등등. 호스트 컴퓨터 상의 많은 변화를 필요로 하는 가상화 시스템들은 그렇지 못하다.
  3. Flexible code. 보통 OS 의 커널은.. 커널이다. 이것은 하드웨어 혹은 몇몇 가상화된 하드웨어와 대화한다. 하지만 UML 은 다른 방식으로도 볼 수 있다. 예를 들어, UML 은 공유 라이브러리로 사용될 수 있으므로 리눅스에서 잘 처리하는 작업들을 이용하기 위해 다른 프로그램에서 UML 을 링크할 수도 있을 것이다. UML 은 기존의 응용 프로그램의 서브쉘로 시작될 수 있고 다른 프로그램 처럼 stdin/stdout 을 사용할 수 있다.
  4. Portable. 정말 이식성이 있다. UML의 이식성은 겨우 이제 연구되어지기 시작했지만, x86 Windows, PowerPC Linux, x86 BSD 혹은 다른 시스템들에 대한 포팅도 아주 용이할 것이라는 긍정적 전망을 갖고 있다.
  5. Mature. UML 은 1999 년 부터 개발되어졌다. 그 견고함(robustness)의 지표 중 하나는 UML은 UML 자신 내에서 컴파일 되고 실행될 수 있다는 것, 즉 'self-hosting'이 가능하다는 것이다. UML은 실제 생산 현장에서도 사용되고 있다.
  6. Free Software. UML 은 GPL 을 따른다 (리눅스 커널의 일부로서 당연히 그래야 한다).

1.3. UML 은 어떻게 동작하는가?

일반적으로, 리눅스 커널은 하드웨어 (비디오 카드, 키보드, 하드 드라이브 등) 와 하드웨어를 제어하기 위해 커널에 요청하는 소프트웨어와 직접 대화한다. 이를 그림으로 표현하면 다음과 같다:

  +-----------+-----------+----+
  | Process 1 | Process 2 | ...|
  +-----------+-----------+----+
  |       Linux Kernel         |
  +----------------------------+
  |         Hardware           |
  +----------------------------+
  


UML 커널은 이와 달라서 하드웨어와 직접 대화하는 대신 다른 프로그램들과 마찬가지로 실제 리눅스 커널 (이제부터 호스트 커널 이라고 하겠다) 과 대화한다. UML 상에서 실행되는 프로그램들은 일반 커널에서 실행되는 것처럼 실행될 수 있다. 이를 그림으로 표현하면 다음과 같다:

              +----------------+
              | Process 2 | ...|
  +-----------+----------------+
  | Process 1 | User-Mode Linux|
  +----------------------------+
  |       Linux Kernel         |
  +----------------------------+
  |         Hardware           |
  +----------------------------+
  


1.4. 왜 UML 을 원하는가?

  1. 만약 UML 이 파괴되더라도 호스트 커널은 잘 동작한다.
  2. root 가 아닌 사용자도 usermode 커널을 실행할 수 있다.
  3. 일반적인 프로세스처럼 UML 을 디버그 할 수 있다.
  4. gprof (프로파일링) 와 gcov (커버리지 테스트) 를 실행할 수 있다.
  5. 다른 것들을 망가뜨리지 않고 커널 관련 작업을 할 수 있다.
  6. 새로운 응용 프로그램을 테스트하기 위한 sandbox 로 사용할 수 있다.
  7. 안전하게 새로운 커널을 개발할 수 있다.
  8. 동시에 서로 다른 배포판들을 실행할 수 있다.
  9. 매우 재미있다.


2. 커널과 모듈의 컴파일

2.1. 커널 컴파일하기

UML 커널을 컴파일하는 것은 다른 커널을 컴파일 하는 것과 동일하다. (이 글을 쓰는 시점에서) 최신 커널인 2.4.0-prelease 를 예제로 해서 한 단계씩 살펴보기로 하자: (2.6대 커널 사용자는 이미 커널소스에 포함되어 있음으로 별도의 패치없이 소스를 받아 5번부터 시작한다)

  1. [http]다운로드 페이지[] 에서 최신 버전의 UML 패치를 다운로드 받는다. 이 예제에서 사용된 파일은 uml-patch-2.4.0-prerelease.bz2 이다.
  2. 주로 이용하는 커널 미러 페이지에서 해당하는 커널을 다운로드 받는다.
  3. 디렉토리를 만들고 다운받은 커널을 압축을 푼다.

    host% mkdir ~/uml
    
    host% cd ~/uml
    
    host% tar -xjvf linux-2.4.0-prerelease.tar.bz2
      


  4. 다음과 같이 패치를 적용한다.

    host% cd ~/uml/linux
    
    host% bzcat uml-patch-2.4.0-prerelease.bz2 | patch -p1
      


  5. 주로 사용하는 커널 config 를 실행한다. make xconfig ARCH=um 의 형태가 가장 편리하다. make config ARCH=um 이나 make menuconfig ARCH=um 도 잘 동작할 것이다. 기본 설정으로도 충분히 유용한 커널을 제공할 것이다. 만약 무언가를 변경하기를 원한다면 그렇게 하라. 그것은 아마도 아무런 피해를 주지 않을 것이다.

    /!\ 주의: 만약 호스트 커널의 주소공간이 일반적인 3G/1G 구분이 아닌 2G/2G 로 설정되어 있다면 패키지화된 UML 실행파일들이 실행되지 않고 segment fault 를 일으킬 것이다. 이러한 시스템에서 UML 을 동작시키기 위해서는 4장 2G/2G 호스트에서 UML 실행하기 를 참고하라.

  6. make linux ARCH=um 명령을 실행한다: 이 결과로 linux 라는 이름의 파일이 소스 트리의 제일 상위 디렉토리에 생성된다. 생성된 실행 파일의 크기는 꽤 크다는 것을 알아두기 바란다 (디버깅 정보를 포함한 UML 은 10 MB 이상의 크기이다). 이것은 대부분 심볼 정보에 해당한다. 실제 실행파일의 크기는 원래의 커널과 비슷한 크기이다. 따라서 거대한 실행 파일을 실행해도 gdb 와 함께 UML 을 실행하지 않는 한 심볼들은 그저 디스크 공간을 소비할 뿐이고 오직 실제 코드와 데이터 정보만이 메모리 상에 로드될 것이다. UML 커널의 실제 크기를 알아보기 위해 다음과 같이 strip 명령을 실행할 수 있다:

    host% strip linux
      


이 커널을 /usr/src/linux 디렉토리에서 빌드하지 않도록 주의하라. 특정 배포판에서는 /usr/include/asm 디렉토리가 이 풀 (pool) 을 가리키는 링크로 되어있으므로 UML 을 이 디렉토리에서 빌드하게 되면 링크가 가리키는 곳의 내용이 변화되고 <asm/anything.h> 를 포함하는 것들은 컴파일이 중지될 것이다.

소스 파일은 이 프로젝트의 CVS 페이지에서도 얻을 수 있다. 이 페이지에서는 소스를 얻는 방법이나 CVS 풀에 대한 정보들도 얻을 수 있다.

cvs -d:pserver:anonymous@www.user-mode-linux.org:/cvsroot/user-mode-linux
cvs command
  


만약 CVS 로부터 소스 파일을 받길 원한다면 그것을 빈 디렉토리로 check out 해야할 것이다. 그리고는 각 파일들을 적절한 커널 풀의 해당하는 디렉토리로 복사해야 한다.

만약 최신의 커널 풀을 가지고 있지 않다면 해당하는 user-mode 소스는 다음과 같이 얻을 수 있다:

host% cvs co -r v_2_3_x linux
  


여기서 x 는 풀 (pool) 의 버전이다. 이후의 릴리즈에 포함된 버그 수정이나 개선 사항등은 얻을 수 없다는 것에 주의하자.

만약 자신만의 커널을 빌드했고 그것을 이 사이트에서 배포하는 파일 시스템들 중의 하나에서 부팅시키고 싶다면 거의 대부분의 경우 커널에 devfs 를 포함시켜서 컴파일하고 부팅시에 마운트되도록 설정해야 한다. 이에 대한 예외가 바로 tomsrtbt 파일 시스템으로서 이 경우, devfs 가 커널에 포함되어 있지 않거나 커널 명령행에서 "devfs=nomount" 가 반드시 입력되어야 한다. devfs 사용에 있어서의 부팅되는 파일 시스템과 커널 간의 불일치는 single-user mode 가 아닐때 부팅이 되지 않도록 할 것이다.

만약 devfs 를 사용하지 않는다면 다음과 같이 /dev/ubd 장치 파일들을 만들어서 /dev 디렉토리에 복사하면 된다:

UML# for i in 0 1 2 3 4 5 6 7; do mknod ubd$i b 98 $[ $i * 16 ]; done
  


그리고 /etc/fstab/etc/inittab 을 수정하여 devfs 가 아닌 장치를 가리키도록 한다.

2.2. 모듈 컴파일과 설치하기

UML 의 모듈은 호스트 커널의 모듈과 동일한 방법으로 설치된다. (UML 을 위해서는 항상 ARCH=um 을 명시해야 한다는 것만이 다르다)

host% make modules ARCH=um
  


이 커널에 로드하고 싶은 모듈들은 사용자 모드 풀에서 빌드되어야 한다. 호스트 커널에서 빌드된 모듈들은 동작하지 않을 것이다. 만약 모듈의 크기가 호스트 커널의 모듈에 비해 크다는 것을 알았다면, 위의 UML 실행파일의 크기를 설명한 부분을 살펴보기 바란다.

또는 ftp 나 그밖의 복사 프로그램등을 이용해 가상 머신으로 복사한 후 /lib/modules/\uname -r\ 디렉토리로 옮겨두는 방식으로도 모듈을 설치할 수 있다.

또는 커널 빌드 과정에서 다음과 같이 설치할 수 있다:

  1. 커널을 부팅하지 않고, 커널 풀의 최상위에서 루트 파일 시스템을 마운트한다.

    host% mount root_fs mnt -o loop
      


  2. 다음을 실행한다.

    host% make modules_install INSTALL_MOD_PATH=`pwd`/mnt ARCH=um
      


  3. 파일 시스템을 언마운트한다.

    host% umount mnt
      


  4. 그 위에 커널을 부팅시킨다.

어떠한 이유로 (COW 파일인 경우처럼) 호스트 시스템에 루트 파일 시스템을 마운트시키지 못한다면, 다른 방법으로 [http]hostfs[] 를 이용해서 호스트의 UML 커널 트리를 UML 로 마운트한 뒤 UML 내에서 modules_install 을 실행하는 방법이 있다:

  1. UML 을 부팅하고, 호스트의 커널 트리를 UML 내의 같은 위치에 마운트한다.

    UML# mount none -t hostfs <UML pool 의 경로> -o <UML pool 의 경로>
      


  2. make modules_install 을 수행한다.

    UML# cd <UML pool 의 경로> ; make modules_install
      


마지막의 depmod 는 unresolved symbols 에 관한 불평을 할수도 있는데 이것은 UML 파일 시스템 내에 설치된 System.map 파일이 잘못되었거나 없기 때문이다. 하지만 이로 인한 문제는 없을 것이다. 현재 insmodmodprobe 등은 잘 동작한다.

시스템이 부팅될 때, 커널 내에 모듈을 로드하기 위해서 insmod 를 주로 사용하게 될 것이다. 많은 것들이 (특히 파일 시스템이나 네트워크 프로토콜, 필터 등) 모듈로서 UML 에 로드된다. 그러므로 대부분의 필요한 심볼들은 아마도 익스포트 되어 있을 것이다. 하지만 익스포트 될 필요가 있는 심볼을 더 찾게 된 경우에는 [http]우리[]에게 알려주면 처리하도록 하겠다.

만약 UML 트리내에 존재하지 않는 외부 모듈을 빌드한다면, include 파일들을 찾을 수 없다고 에러를 내며 컴파일되지 않을 것이다. 모듈의 Makefile 이나 스크립트에서 빌드는 되었더라도 실행되지 않는 CFLAGS 에 관련된 몇가지 문제점들이 있다. 이를 해결하기 위해서는 UML 커널을 빌드할 때 사용했던 것과 동일한 CFLAGS 옵션을 사용해야 할 필요가 있다.

UML 의 CFLAGS 를 얻는 좋은 방법으로는 다음과 같은 것이 있다:

cd uml-tree ; make script 'SCRIPT=@echo $(CFLAGS)' ARCH=um
  


만약 모듈 빌드 과정에서 다음과 같은 부분이 나타난다면

$(CC) $(CFLAGS) file
  


스크립트 내의 CFLAGS 를 다음과 같이 정의할 수 있다

CFLAGS=`cd uml-tree ; make script 'SCRIPT=@echo $(CFLAGS)' ARCH=um`
  


그리고 Makefile 내에서는 다음과 같이 정의한다

CFLAGS=$(shell cd uml-tree ; make script 'SCRIPT=@echo $$(CFLAGS)' ARCH=um)
  


2.3. UML 유틸리티 컴파일과 설치하기

UML 커널의 많은 기능들은 사용자 공간에서 동작하는 도우미 프로그램을 필요로 한다. 그러므로 이러한 기능을 수행하기 위해서 커널 패치와는 별도로 uml_utilities 패키지가 배포된다. 이는 다음과 같은 것들을 포함한다:

  • port-helper - xterms 이나 port 에 연결된 콘솔들에 의해 사용됨
  • tunctl - tab 장치들의 생성과 삭제를 위한 설정 도구
  • uml_net - 자동 tab 장치 설정을 위한 setuid 실행 파일
  • uml_switch - daemon transport 에 필요한 사용자 공간의 가상 스위치

uml_utilities 트리는 다음과 같이 컴파일 한다:

host#  make && make install
  


UML 커널 패치는 특정 버전의 uml_utilities 배포판을 요구한다는 것을 유의하기 바란다. 메일링 리스트를 살펴보지 않는다면, 현재 UML 커널에서 문제를 경험한 경우 (특히 콘솔 작업이나 도우미 프로그램으로의 명령행 스위치 등을 다룰 때) 최신 버전의 uml_utilities 를 가지고 있는지 확인해 보기 바란다.


3. UML 의 실행과 로그인 하기

3.1. UML 실행하기

UML 은 커널버전 2.2.15 혹은 그 이후의 버전이나, 모든 2.4 과 2.6 커널에서 동작한다.

UML 의 부팅은 간단하다. 단순히 linux 라고 입력하면 된다: 이 경우 UML 은 현재 디렉토리의 root_fs 라는 파일을 마운트하려고 할 것이다. 이 작업을 root 권한으로 수행해야 할 필요는 없다. 만약 루트 파일 시스템의 이름이 root_fs 가 아니라면 명령행에서 ubd0=root_fs_다른이름 이라고 적어주면 된다.

UML 을 부팅시키기 위해서는 파일 시스템이 필요하다. 이 파일 시스템들은 [http]여기[] 에서 다운로드 받을 수 있다. 미디어로 부터 직접 UML 에 호환되는 파일 시스템 이미지를 생성해주는 [http]여러가지 도구들[] 도 존재한다.

이렇게 커널이 부팅되면 로그인 프롬프트가 나타날 것이다.

/!\ 주의: 호스트 시스템의 주소공간이 일반적인 3G/1G 구분이 아닌 2G/2G 구분으로 설정되어 있다면 패키지로 들어있는 UML 실행 파일들은 동작하지 않고 바로 segment fault 를 일으킬 것이다. 이러한 시스템에서 UML 을 실행시키기 위해서는 4장 2G/2G 호스트에서 UML 실행하기 를 참고하라.

3.2. 로그인 하기

미리 패키지로 만들어진 파일 시스템은 패스워드가 root 로 설정된 root 계정과 패스워드가 user 로 설정된 user 계정을 가진다. 일반적으로 로그인 배너가 로그인하는 방법을 알려줄 것이다. 그대로 따라하면 가상 머신 상으로 로그인해 들어갈 수 있을 것이다. 이 파일 시스템에는 많은 커맨드와 도구들이 설치되어 있으며 (또한 더 추가하는 것도 매우 쉽다), 시스템을 자세히 살펴볼 수 있는 여러가지 도구들도 가지게 될 것이다.

로그인은 다음과 같은 방법으로도 할 수 있다:

  • 가상 콘솔 상으로 로그인 하기
    설정된 각각의 콘솔 (즉, /dev 디렉토리 밑에 장치파일이 존재하고 /etc/inittab 에서 그 위에 getty 가 동작하도록 지정된 콘솔) 로 xterm 이 연결될 수 있다. xterm 에 싫증났다면 콘솔에 호스트의 pty 와 같은 다른 것들을 연결하는 방법을 위해 5장 시리얼 라인과 콘솔 설정하기 를 읽어보기 바란다.

  • 시리얼 라인 상으로 로그인 하기
    부팅시에 나오는 메시지 중에 다음과 같은 부분을 찾는다.

    serial line 0 assigned pty /dev/ptyp1
       


    주로 사용하는 터미널 프로그램을 해당하는 tty 에 연결한다. minicom 의 경우 다음과 같은 형태가 될 것이다.

    host% minicom -o -p /dev/ttyp1
       


  • 네트워크 상으로 로그인 하기
    네트워크가 동작하고 있다면 telnet 을 이용해 가상 머신으로 로그인 할 수 있다. 6장 네크워크 설정하기 부분을 읽어서 가상 네트워크를 설정하는 방법을 알아두기 바란다.

시스템을 다 사용했다면 halt 를 실행하라. 그러면 커널은 자신을 종료하고 프로세스를 종료시킬 것이다.

3.3. 예제

다음은 실제적인 UML 동작의 예제들이다.

4. 2G/2G 호스트에서 UML 실행하기

4.1. 소개

대부분의 리눅스 머신은 4G 의 주소공간 중에서 커널이 상위 1G (0xc0000000 - 0xffffffff) 를 사용하고, 프로세스가 하위 3G (0x00000000 - 0xbfffffff) 를 사용하도록 설정되어 있다. 하지만 특정한 머신에서는 커널이 상위 2G (0x80000000 - 0xffffffff) 를 사용하고, 프로세스가 하위 2G (0x00000000 - 0x7fffffff) 를 사용하는 2G/2G 구분으로 설정되어 있다.

4.2. 문제점

UML 사이트에서 제공하는 미리 빌드된 UML 실행파일은 이러한 2G/2G 호스트에서는 동작하지 않을 것이다. 왜냐하면 UML 은 프로세스의 3G 주소공간 중에서 상위 0.5G (0xa0000000 - 0xbfffffff) 를 사용하도록 설정되어 있기 때문이다. 2G/2G 호스트에서 이는 분명 커널 주소공간의 한가운데에 위치하게 되므로, UML 은 로드되지 않고 즉시 segfault 를 일으킬 것이다.

4.3. 해결책

이러한 문제점을 해결하기 위해서는 UML 소스를 빌드할 때 (General Setup 밑의) 2G/2G host address space split 를 선택하여 CONFIG_HOST_2G_2G 를 설정하면 된다. 그러면 UML 은 2G 로 줄어든 프로세스 주소공간의 상위 0.5G 부분에 로드되어 동작할 것이다. UML 을 소스로부터 빌드하는 방법은 2장 커널과 모듈의 컴파일 부분을 참조하기 바란다.


5. 시리얼 라인과 콘솔 설정하기

명령행 옵션을 통해 UML 의 시리얼 라인과 콘솔을 많은 종류의 호스트 I/O 채널 (ptys, ttys, 파일 디스크립터, 포트 등) 에 연결 (attach) 할 수 있다. 이는 다음과 같은 작업을 가능하게 해준다.

  • 사용하지 않는 호스트의 콘솔에 UML 콘솔이 나타나게 한다.
  • 한쪽의 가상머신은 pty 에 연결하고 다른 하나의 가상 머신은 해당 tty 에 연결하여 두개의 가상 머신을 함께 후킹한다.
  • 가상머신의 콘솔을 호스트의 포트에 연결함으로서 가상 머신을 네트워크를 통해 접근 가능하도록 한다.

명령행 옵션의 일반적인 형태는 장치=채널 의 형태이다.

5.1. 장치 지정하기

장치는 con 이나 ssl 의 형태로 지정한다 (각각 콘솔과 시리얼 라인에 해당). 특정 장치를 지정하고 싶은 경우에는 옵션으로 장치 번호를 명시할 수 있다.

단지 con 이나 ssl 이라고만 지정한 경우에는 모든 콘솔이나 시리얼 라인을 말하게 된다. 만약 3번 콘솔이나 10번 시리얼 라인을 지정하고 싶은 경우라면 con3 이나 ssl10 이라고 명시해야 한다.

지정된 장치 이름은 일반적인 con= 이나 ssl= 의 설정을 덮어쓰게 (override) 될 것이다. 예를 들어 처음의 2개를 제외한 시리얼 라인을 pty 에 할당하고 싶은 경우는 다음과 같이 할 수 있다:

ssl=pty ssl0=tty:/dev/tty0 ssl1=tty:/dev/tty1
  


설정시 명령행에서 나타나는 순서에 상관없이 장치의 이름만으로 지정된다.

5.2. 채널 지정하기

UML 장치가 연결될 수 있는 여러 타입의 채널들이 있고, 각각은 정확히 어떤 장치들이 연결될 지를 지정하는 방법이 서로 다르다.

  • 가상 터미널 - 장치=pty, pts 터미널 - 장치=pts 이는 UML 이 해당 장치를 위한 호스트의 이용가능한 가상 터미널을 할당하도록 한다. 얻어진 터미널 정보는 부트 로그에 표시될 것이다. 터미널 프로그램을 해당하는 tty 에 연결함으로서 여기에 접근할 수 있게 된다.

    • screen /dev/pts/n
    • screen /dev/ttyxx
    • minicom -o -p /dev/ttyxx - minicom 프로그램은 pts 장치를 다룰 수 없는 것 같다.
    • kermit - 시작한 후 장치를 open 하고 connect 한다.

  • 터미널 - 장치=tty:tty장치파일 이는 UML 이 해당 장치를 지정된 tty 에 연결하도록 한다 (아래의 예제는 1번 콘솔을 호스트의 /dev/tty3 에 연결할 것이다).

    con1=tty:/dev/tty3
        


  • 만약 지정한 tty 가 tty/pty 쌍의 슬레이브라면 다른 곳에서 해당 pty 를 이미 open 한 상태여야 동작할 것이다..?? - If the tty that you specify is the slave end of a tty/pty pair, something else must have already opened the corresponding pty in order for this to work.

  • xterm - 장치=xterm UML 은 xterm 을 실행시키고 장치가 xterm 에 연결될 것이다.

  • 포트 - 장치=port:포트 번호 이는 UML 의 장치를 호스트의 지정된 포트에 연결할 것이다. 1번 콘솔을 호스트의 9000 번 포트에 연결하기 위해서는 다음과 같이 하면 된다:

    con1=port:9000
        


  • 모든 시리얼 라인을 9000 번 포트에 연결하는 것도 동일한 방법으로 할 수 있다:

    ssl=port:9000
        


    이 장치에 접근하기 위해서는 telnet 을 이용해 해당 포트로 접속하면 된다. 각각의 활성화된 텔넷 세션은 서로 다른 장치를 얻게 된다. 만약 연결된 장치보다 많은 텔넷 접속이 요청된다면 이후의 텔넷 세션들은 기존의 접속이 해제되거나 (/etc/inittab 에 의해 지정된) 다른 장치가 활성화 될 때까지 블럭된다.

    이러한 채널은 여러 UML 장치들을 하나에 연결할 수 있게 하고 UML 부트 로그를 읽지 않고도 접근하는 방법을 알 수 있게 하는 두가지 장점을 가진다. 또한 UML 이 네트워크에 물려있지 않은 상태에서도 원격 머신에서 UML 에 접근할 수 있는 방법이 존재한다. 이는 UML 에 공개적으로 접근 (public access) 할 수 있도록 할 때 유용하게 사용될 수 있다. 왜냐하면 네트워크를 통해 UML에 접근할 수 있지만 UML 자체로는 네트워크에 연결되지 않은 상태이기 때문에 이에 대한 어떤 네트워크 필터링도 수행하지 않기 때문이다.

    만약 메인 콘솔을 portal(포트?) 에 연결한다면 UML 부팅은 멈춰있게 (hang) 될 것이다. 실제로 이것은 텔넷 접속을 기다리게 되고 접속이 이루어지는 시점에서 부팅은 계속 진행될 것이다.

  • 이미 존재하는 파일 디스크립터 - 장치=fd:파일 디스크립터 만약 UML 명령행에서 파일 디스크립터를 설정한다면 해당 파일 디스크립터에 UML 장치를 연결할 수 있다. 이것은 다음과 같이 다른 콘솔들을 설정하고 메인 콘솔을 표준 입력과 표준 출력으로 다시 지정하는 경우에 주로 사용된다:

    con0=fd:0,fd:1 con=pts
        


  • 없음 (nothing) - 장치=null 이것은 none 과 달리 장치를 열려있게 한다. 해당 장치에 대한 읽기 연산은 블럭되고 쓰기 연산은 성공하게 되지만 쓰여진 모든 데이터는 버려질 것이다.

  • 없음 (none) - 장치=none 이것은 장치를 사라지게 한다. devfs 를 사용하는 경우라면, /dev 밑에 장치들이 보이지 않게 된다. 그렇지 않다면 해당 장치를 open 하려는 시도는 -ENODEV 를 반환할 것이다.

또한 컴마 (,) 를 통해 입력 채널과 출력 채널을 구분하여 서로 다르게 지정할 수도 있다.

ssl3=tty:/dev/tty2,xterm
  


위의 경우 3번 시리얼 라인은 호스트의 /dev/tty2 을 통해 입력을 받아들이고 xterm 에 출력을 보여줄 것이다. 위의 예제는 설명을 위해 든 것일 뿐이고 이러한 기능을 주로 사용하는 것은 위에서 설명했듯이 메인 콘솔을 표준 입출력으로 다시 지정할 때이다.

만약 메인 콘솔을 표준 입출력에서 제거하기로 했다면 초기의 부트 메시지는 UML 이 동작하는 터미널 상에 표시될 것이다. 하지만 콘솔 드라이버가 정식으로 초기화 되면 부트 메시지는 0번 콘솔로 지정한 곳으로 출력될 것이다. 이후의 모든 출력은 해당 장치가 받게될 것이다.

5.3. 예제

이러한 기능을 이용해 할 수 있는 몇가지 흥미로운 일들이 있다.

먼저 메시지가 넘쳐나는 콘솔 터미널 (bleeding console xterm) 을 호스트 가상 터미널에 연결함으로서 제거하는 방법이다:

con=pty con0=fd:0,fd:1
  


아래는 호스트의 사용되지 않는 가상 콘솔을 UML 이 사용하도록 지정하는 방법이다. 이후에 해당 콘솔에 대한 접근은 호스트의 로그인 프롬프트가 아닌 UML 로그인 프롬프트를 보여줄 것이다:

con1=tty:/dev/tty6
  


두개의 가상 머신을 시리얼 라인을 통해 함께 연결시키는 방법은 다음과 같다:

먼저 하나의 UML 을 pty 에 연결된 시리얼 라인으로 동작시킨다.

ssl1=pty
  


부트 로그를 살펴서 어떤 pty 를 얻었는지 알아본다. (이 예제에서는 /dev/ptyp1 을 얻었다고 가정한다)

또다른 UML 을 해당하는 tty 에 시리얼 라인을 연결하여 부팅한다

ssl1=tty:/dev/ttyp1
  


로그인 해서 해당 시리얼 라인에 getty 가 연결되어 있지 않음을 확인하고, minicom 과 같은 터미널 프로그램을 해당 시리얼 라인으로 연결하면 다른 가상 머신의 로그인 프롬프트를 볼 수 있을 것이다.


6. 네트워크 설정하기

이번 절에서는 다양한 전송 방법의 설정과 UML 프로그램을 호스트나 로컬 네트워크 상의 다른 머신들, 그리고 인터넷 상의 머신들에서 접근할 수 있도록 설정하는 방법을 설명한다.

커널 버전 2.4.5 에 이르러 UML 네트워킹은 설정을 간편하게 하고 버그를 수정하고 새로운 기능을 추가하여 완전히 새로 쓰여졌다.

새로운 헬퍼 프로그램으로 uml_net 이 있어서, 호스트의 설정을 도와주며 이를 실행하기 위해서는 수퍼 유저 권한이 필요하다.

현재는 UML 가상 머신이 다른 호스트와 패킷을 교환하기 위한 방법으로 5 가지의 전송 타입이 있다:

  • ethertap
  • TUN/TAP
  • 멀티 캐스트
  • switch 대몬
  • slip
  • slirp
  • pcap

TUN/TAP, ethertap, slip, slirp 전송은 UML 프로그램과 호스트 간의 패킷 교환을 가능하게 한다. 이들은 호스트에 직접 연결되거나 호스트가 다른 가상 혹은 실제 머신에 대한 접근 방법을 제공하는 라우터로서 동작하도록 한다.

pcap 전송은 통합적인 읽기 전용 인터페이스로서 libpcap 의 파일을 이용하여 호스트의 인터페이스에서 패킷을 모아서 필터링한다. 이것은 미리 설정된 트래픽 모니터나 스니퍼를 구축하는데 유용하다.

대몬과 멀티 캐스트 전송은 다른 가상 머신에 대한 완전한 가상 네트워크를 제공한다. 이러한 네트워크는 하나의 가상 머신이 게이트 웨이로서 동작하지 않는 한 실제의 네트워크와 완전히 분리된다.

이렇게 많은 전송 타입 중에서 어떠한 것을 사용하여야 할까? 여기에 각 상황에 맞게 사용할 수 있는 타입에 대한 설명이 있다:

  • ethertap - 호스트의 네트워킹에 접근할 수 있고 2.2 버전에서 동작하는 경우
  • TUN/TAP - 호스트의 네트워킹에 접근할 수 있고 2.4 버전에서 동작하는 경우. 또한 TUN/TAP 전송은 미리 설정된 장치를 사용할 수 있고, setuid 가 설정된 uml_net 프로그램을 이용하지 않아도 되므로 보안 상의 이점이 있다.
  • 멀티캐스트 - 순수한 가상 네트워크를 원하며 UML 이외의 다른 어떤 것도 설정하고 싶지 않은 경우
  • switch 대몬 - 순수한 가상 네트워크를 원하며 성능 상의 이점이 중요치 않은 경우
  • slip - ethertap 이나 TUN/TAP 가 동작하지 않고 slip 백엔드를 동작시킬 특별한 이유가 없는 경우
  • slirp - 호스트의 네트워크를 설정한 권한을 가지고 있지 않거나 UML 에 IP 를 할당하고 싶지 않은 경우
  • pcap - 실제로 네트워크에 연결될 필요가 없이 호스트의 트래픽을 감시하고 싶은 경우

ethertap 은 이제 2.4 버전에서도 이용가능하며 실제로 잘 동작한다. 하지만 ethertap 은 공식적으로 2.4 버전에서 제외되었고 성능상의 이유로 해서 TUN/TAP 이 더 선호된다. 또한 ethertap 에서는 모든 패킷을 처리할 때 마다 루트 사용자 권한이 필요한 반면 TUN/TAP 에서는 가끔씩만 필요하게 된다. 그러므로 악의를 가진 UML 사용자가 헬퍼 프로그램의 루트 권한을 얻으려고 하는 시도에 대한 기회를 줄이게 되므로 약간의 보안 상의 이점도 얻을 수 있다.

6.1. 일반 설정

먼저 UML 내의 가상 네트워크를 설정해야 한다. 이 싸이트에서 미리 빌드된 커널을 받아서 사용한다면 이미 모든 것이 설정되어 있을 것이다. 만약 스스로 커널을 빌드하는 경우라면 "Network device menu" 아래의 "Network device menu" 과 세가지 전송 타입에 대한 옵션을 선택하자.

다음 단계는 가상 머신에게 네트워크 장치를 제공하는 일이다. 이것은 커널의 명령행 옵션을 통해 가능하며 일반적인 형태는 아래와 같다:

eth <n> = <전송 타입> , <전송 타입에 따른 인자>
   


예를 들어 가상의 이더넷 장치를 호스트의 ethertap 장치에 연결(attach)하기 위해서는 다음과 같이 할 수 있다:

eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
   


위의 경우 가상 머신의 eth0 장치를 호스트의 /dev/tap0 장치에 연결하고, eth0 장치의 이더넷 주소와 호스트의 tap0 장치의 IP 주소를 할당한다.

여기서 주의할 것은 호스트 측의 tap 장치에 할당한 IP 주소와 UML 내의 eth 장치에 할당한 IP 주소가 반드시 달라야 한다는 점이다. 만약 IP 주소가 부족하여 UML 당 2 개의 IP 주소를 할당하고 싶지 않은 경우에는 호스트 측의 tap 장치에 호스트이 eth 장치와 같은 IP 주소를 할당할 수 있다. 내부적으로 각각의 UML 은 자신의 eth 장치에 대해 고유한 IP 주소를 가져야 한다. 또한 UML 장치에게 사설 IP (192.168.x.x 혹은 10.x.x.x) 를 할당하고 호스트에서 이를 매스커레이딩(masquerading) 하는 방법도 가능하다. 이 방법을 이용하면 외부로 나가는 패킷에 대해서는 잘 동작하지만 포트 포워딩과 같이 내부로 들어오는 패킷에 대해서는 동작하지 않게 된다.

그리고 호스트 측의 장치들을 설정할 때는, 그것이 게이트 웨이로 동작한다는 것을 명심하자. 해당 장치에 대해 로컬에서 ping 을 보내면 응답을 하지만, 이것은 호스트 장치이기 때문에 아무 의미가 없다. 즉, 이 장치를 통해 ping 을 보내더라도 UML 과 통신하는 것이 아니라는 말이다.

또한 UML 이 동작하는 중에도 동적으로 장치를 추가하거나 제거하는 것이 가능하다. 자세한 내용은 관리 콘솔 부분을 참조하기 바란다.

다음에 나오는 절에서는 각각의 방법에 대한 자세한 설명을 할 것이다.

일단 장치를 어떻게 설정할 지 결정했다면, UML 을 부팅시키고 로그인 하여 UML 측의 장치를 설정한 뒤, 외부로 나가는 라우팅 정보를 설정한다. 이 때부터 네트워크 상의 다른 머신들(가상이건 실제 머신이건)과 통신할 수 있을 것이다.

만약 UML 내의 ifconfig 명령이 실패하고 네트워크 기능이 동작하지 않는다면, dmesg 명령을 실행하여 맨 마지막 부분의 커널 로그를 살펴보기 바란다. 보통의 문제들은 여기에서 원인을 찾을 수 있을 것이다.

6.2. 사용자 영역 데몬

아마도 setuid 도우미 프로그램이나, 스위치 데몬, 혹은 둘 다가 필요할 것이다. 이들은 RPM 과 deb 를 통해 설치되므로, 둘 중의 하나를 통해 설치했다면 이 절의 나머지 부분은 건너뛰어도 좋다.

그렇지 않다면 CVS 에서 체크 아웃해서 빌드한 후에 설치해야 한다. 도우미 프로그램은 uml_net 이고 CVS 내의 /tools/uml_net 에서 받을 수 있으며, 스위치 데몬은 uml_switch 이고 CVS 내의 /tools/uml_router 에서 받을 수 있다. 이들은 모두 단순히 make 명령을 통해서 빌드된다. 이들은 당신의 path 에 지정된 디렉토리 내에 설치되어야 한다 - /usr/bin 을 추천. 그리고 무엇보다 uml_net 은 setuid root 권한이 필요하다.

6.3. 이더넷 주소 지정하기

이후의 TUN/TAP, ethertap, 데몬 인터페이스에 대한 부분에서 가상의 이더넷 장치에 대해 하드웨어 주소를 지정하는 것을 보게 될 것이다. 이것은 일반적으로 불필요한 부분이다. 만약 하드웨어 주소를 지정해야 하는 특별한 이유를 가지고 있지만 않다면 지정하지 말아야 한다. 명령행에서 하드웨어 주소를 지정하지 않으면 드라이버는 장치의 IP 주소를 통해 자동적으로 하드웨어 주소를 할당한다. 만약 장치의 IP 주소가 nn.nn.nn.nn 인 경우에는 fe:fd:nn:nn:nn:nn 와 같은 형태로 주소가 할당된다. 거의 대부분의 경우 이 방법을 통해 장치에게 고유한 하드웨어 주소를 부여하는 것이 가능하지만 다음과 같은 예외 사항이 있다:

  • 또다른 가상 이더넷 장치들이 같은 네트워크 상에 있고 이들이 UML IP 주소 기반의 방식(scheme)과 충돌을 일으킬 만한 다른 방식을 사용하여 하드웨어 주소를 할당받은 경우
  • IP 네트워킹에 사용하지 않을 장치이기 때문에 IP 주소를 할당하지 않은 경우

하드웨어 주소를 드라이버에서 자동으로 할당하도록 하려면, 장치가 사용되기 전에 장치에 대한 IP 주소가 먼저 할당되어 있어야 한다. UML 에서는 다음과 같이 할 수 있다:

UML# ifconfig eth0 192.168.0.250 up
   


스스로 하드웨어 주소를 지정하는 경우에는 첫번째 바이트 값이 짝수가 되도록 해야 한다. 첫번째 바이트가 홀수인 경우에는 브로드 캐스트 주소를 말하는 것이기 때문에 장치에 할당하면 안된다.

6.4. UML 인터페이스 설정

일단 네트워크 장치가 명령행 옵션으로 지정되면 UML 을 부팅하고 로그인 한다.

먼저 장치를 시작시킨다.

UML# ifconfig ethn ip-address up
   


이제부터 호스트와 ping 이 가능해 진다.

외부의 네트워크에 연결하기 위해서는 기본 라우터를 호스트로 설정한다.

UML# route add default gw <호스트의 IP 주소>
   


즉, 호스트의 IP 주소가 192.168.0.4 라면 아래와 같이 설정한다:

UML# route add default gw 192.168.0.4
   


이 문서에서는 네트워크 라우팅 정보를 설정할 때 주로 로컬 네트워크를 사용하도록 추천하고 있다. 이것은 잘못된 것이다. UML 은 로컬 네트워크 내의 머신들의 하드웨어 주소를 알아내기 위해 호스트에 연결된 장치를 통해 arp 요청을 보내지만 기본적으로 하나의 장치에 두 개의 노드(호스트와 UML)가 연결된 형태이기 때문에 arp 요청은 네트워크로 전송될 수 없고 어떠한 응답도 받을 수 없게 된다. 그래서 UML 에서는 그저 모든 패킷을 호스트에게 넘겨주고 호스트에서 모든 일을 해 주길 바랄 것이다.

주의: 만약 실제 이더넷 상의 다른 호스트들과 통신할 수 없다면, 아마도 자동 설정된 네트워크 라우트 정보 때문일 것이다. route -n 명령을 실행하면 다음과 같은 내용이 표시된다:

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0      0   eth0
   


마스크 값이 255.255.255.255 가 아니면, 호스트에 대한 라우팅 정보로 대체한다.

UML# route del -net 192.168.0.0 dev eth0 netmask 255.255.255.0

UML# route add -host 192.168.0.4 dev eth0
   


이것과 기본 라우터를 호스트로 설정하면, UML 에서도 이더넷 상의 다른 호스트 들과 통신할 수 있게 된다.

6.5. 멀티캐스트

여러 개의 UML 간의 가상 네트워크를 설정하는 가상 쉬운 방법은 멀티캐스트 전송을 이용하는 것이다. 이것은 Harald Welte 가 작성하였으며, UML 버전 2.4.5-5um 이후에서 사용가능하다. 이를 위해서는 시스템의 커널이 멀티캐스트를 지원해야 하며 호스트의 네트워크 장치에서도 멀티캐스트를 지원해야 한다. 여기에서는 eth0 을 가지고 설명했지만 일반적으로 호스트 내에 이더넷 장치가 없는 경우에는 UML 상에서 장치를 활성화 시킬 때 (bring up) 이상한 에러 메시지를 보게 될 것이다.

이를 사용하기 위해서는 다음과 같은 명령행 옵션을 주어 UML 을 시작한다:

eth0=mcast
   


그리고 로그인 해서, 각각의 머신에 대해 고유한 IP 주소를 주어 장치를 설정한다.

UML1# ifconfig eth0 192.168.0.254

UML2# ifconfig eth0 192.168.0.253
   


그러면 이제부터 각 장치들 간에 상호 통신이 가능할 것이다.

이 전송 타입에 대한 완전한 명령행 옵션은 다음과 같다:

ethn=mcast,<이더넷 주소>,<멀티캐스트 주소>,<멀티캐스트 포트>,ttl
   


이에 대한 자세한 사항과, 몇 가지 다른 이슈들을 다룬 Harald 의 원본 README 문서는 [http]여기 에서 볼 수 있다.

6.6. uml_helper 를 이용한 TUN/TAP

TUN/TAP 은 2.4 버전에서 호스트와 통신하는 경우에 사용하는 더 나은 방법이다. TUN/TAP 백엔드는 2.4.9-3um 버전부터 UML 내에 포함되었다.

이것을 설정하고 동작시키는 가장 쉬운 방법은 setuid 가 설정된 uml_net 이라는 도우미 프로그램을 이용하여 호스트를 설정하는 것이다. 이것은 필요한 경우 tun.o 모듈을 insmod 하고, 장치를 설정한 후에 IP 포워딩, 라우팅, 프록시 arp 등을 설정한다. 처음 UML 네트워킹을 사용하는 경우에는 먼저 이 방법을 사용하기를 권한다. 만약 이 setuid 도움미 프로그램으로 인한 보안 상의 문제를 고려하는 경우에는, 우선 이를 이용하여 설정 작업과 동작을 시킨 후, 다음 절에 나오는 uml_net 을 사용하지 않고 미리 설정된 tap 장치를 사용하는 법을 읽어보기 바란다.

만약 호스트 측 장치의 IP 주소를 지정한 경우에는, uml_net 도우미 프로그램은 호스트 설정에 필요한 모든 작업을 처리해 줄 것이다 - 오직 필요한 것은 커널에 포함된 형태이든 tun.o 모듈의 형태이든 커널에서 TUN/TAP 을 사용할 수 있도록 설정하는 일이다.

TUN/TAP 장치에 장치를 연결하는 명령행 옵션은 다음과 같다:

eth <n> =tuntap,,, <호스트 IP 주소>
   


예를 들어, 다음과 같이 설정한 경우라면 UML 의 eth0 장치를 이용가능한 tap 장치에 연결하고, 호스트 측의 tap 장치에는 IP 주소 192.168.0.254 를 할당하고, UML 내의 ifconfig 로 할당한 IP 주소를 기반으로 하여 이더넷 주소를 할당한다.

eth0=tuntap,,,192.168.0.254
   


이 예제에서와 같이 호스트 측 네트워크 설정을 위해서 uml_net 을 사용한 경우에는 UML 의 IP 주소를 바꾸게 되면 uml_net 은 매치를 위한 호스트의 라우팅 정보와 arp 정보를 바꾸게 된다. 그래서 UML 내에 악의가 있는 사용자가 있는 경우, uml_net 을 사용하는 것은 위험의 요소를 포함하게 된다. uml_net 을 사용하는 것은 편리하지만 UML 을 네임 서버나 메일 서버처럼 보이게 할 수도 있다. 이 경우 호스트는 여전히 그러한 서버에게 패킷을 보내려고 하지만 이는 UML 로 전달될 것이다. 보안을 고려하여 네트워크를 설정하려고 한다면 다음 절을 읽어보기 바란다.

2.4 버전의 호스트 커널에서 TUN/TAP 전송을 사용하는 것에는 두 가지의 잠재적인 문제점이 남아 있다:

  • TUN/TAP 은 2.4.3 이전 버전에서는 동작하지 않는다. 이 경우 호스트 커널을 업그레이드 하거나 ethertap 을 사용해야 한다.
  • 커널을 업그레이드하면 다음과 같은 에러를 보이며 TUN/TAP 은 실패할 것이다:
    File descriptor in bad state
       


    이것은 업그레이드된 커널과 원래 설치되어 있던 커널 간에 헤더가 일치하지 않아 생기는 문제이다. 이 경우 /usr/src/linux 가 현재 실행 중인 커널의 디렉토리를 가리키도록 수정한다.

이것은 [http]Tim Robinsonhttp://www.geocrawler.com/lists/3/SourceForge/597/0/ 에서 지적한 내용이다.



sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2007-07-26 06:51:08
Processing time 0.0434 sec