다음 이전 차례

3. 그 밖의 것들

다음은 커널 프로젝트 홈으로 문의한 질문들중 몇가지를 추려보았다. 정말 잡다한 것이라 소개하기 부끄러운것도 있고 알아두면 유용한 것도있으니 참고하기 바란다.

3.1 커널 소스의 크기는 얼마나 되나?

초기 리눅스 커널 0.01의 크기가 470KB밖에 되지 않았는데 현재 최신 개발 커널 2.4.0-test5의 크기는 103MB나 된다. 놀랍지 않은가?

3.2 왜 커널 이미지를 압축하는가?

우리는 커널 컴파일을 할 때 make zImage, make bzImage 이런 식으로 커널 이미지를 압축한다.( make zlilo, zdisk, bzlilo 모두 마찬가지...) 아무런 의문 없이 무의식적으로 당연히 이렇게 쓰고 있다.

여기에는 약간의 배경지식이 필요한데 간략히 설명하겠다.

우리가 흔히 아는 매킨토시의 M68계열 processor는 8bit환경에서 32bit환경으로 발전되었지만 인텔의 8086계열은 DOS의 대중성 때문에 바로 32bit 환경으로 가지 못하고 16bit 환경을 가지게 되었다. 대중적으로 많이 쓰이고 있는 DOS를 계속 쓸 수 있도록 하기 위해서였다. 이러한 이유 때문에 리얼모드, 보호모드, 가상86모드가 생겼다.

리얼모드, 보호모드, 가상86모드 모두 세그먼트레지스터와 오프셋 레지스터를 이용하여 주소를 지정하는데 이들 레지스터의 사용방법이 다르다.

리얼모드는 세그먼트x10h + 오프셋으로 주소를 만드는데 16bit에서 세그먼트와 오프셋의 최대 값은 FFFF이다. 그러므로 최대로 지정할수 있는 주소는 FFFF0 + FFFF가 된다. 이걸 계산하면 1MB + 64KB가 된다.

보호모드에선 주소지정 방식이 리얼모드와는 많이 다르며 페이징 등을 이용하여 32bit 모두 주소 값을 만들 수 있으므로 이론적으론 4GB의 메모리를 이용할 수있으며 가상86모드 또한 선형주소를 만들어내는 과정만 다르므로 기본 매커니즘은 보호모드와 같다. (보호모드와 가상86모드의 주소 생성 법은 생략한다.)

프로그램은 code 부분과 data부분으로 나누어지는데 리얼모드에서 프로그램의 code부분은 반드시 위 최대 주소 지정영역 내에 있어야 한다는 것이다. 리얼모드에서는 여러 개의 프로그램이 메모리에 올라와서 수행될 수 없으며 (만약 여러 개의 프로그램이 메모리에서 수행된다면 다른 프로그램영역을 침범 할 수 있기 때문이다.) interrupt를 이용하는 RAM상주 프로그램만이 메모리를 같이 차지할 수 있다.

위에서 설명한 리얼모드의 약 1MB정도의 영역 중 Coventional Memory가 640KB를 차지하고 나머지는 비디오램 이나 기타 디바이스가 차지한다.

그러므로 커널 이미지는 Coventional Memory 즉 640KB내에 들어가야 하므로 커널 이미지의 크기가 640KB보나 작아야 한다. 커널 이미지의 압축으로 이러한 제약을 부분적으로 극복하였으나 640KB의 일부는 여러 가지 버퍼(DMA buffer)나 특정 주소가 시스템에 예약되어 있으므로 640KB보다 더 작은 크기의 커널이 요구된다. 이러한 문제의 대안으로 커널을 Extended Memory에 적재하는 방법을 생각해 볼 수 있다. Extended Memory 영역에 자유로이 적재하기 위해서는 보호모드를 사용해야하는데 보호모드에서는 BIOS와 같이 시스템이 완전히 준비되기 전의 기본적인 기능들을 사용할 수 없다. 이럴 경우 디스크를 액세스하는 자체적인 함수를 준비하여 커널을 Extended Memory 에 적재하거나 아니면 커널을 줄이는 수밖에 없는 것이다.

3.3 LILO에서 최대 커널 이미지 개수

여기에 대해선 전혀 모르고 있었는데 어느 날 2.4.0-test1-ac18 버전을 더더욱 최적화하기 위해 커널 컴파일을 하고 lilo.conf에 이미지를 등록시키고 lilo란 명령으로 커널 이미지를 write하는데 다음과 같은 메세지가 나왔다.

     Only 19 image names can be defined
그때까지 나의 lilo.conf에는 19개의 커널 이미지가 정의되어있었는데 하나 더 추가해서 20개 가 되자 위와 같은 메세지를 출력한 것이었다. 커널 이미지를 20개 이상 등록(?)하지 않았다면 아마 몰랐을 것이다.

3.4 스왑파일도 있는데 스왑 파티션을 쓰는이유?

결론적으론 속도 때문이다. 스왑파일을 쓴다면 파일에 접근하기위해 VFS와 파일 시스템 드라이버 그리고 파일정보를 담고있는 여러 가지를 읽어오고 쓸때도 일반 파일이 writing 되는 경로를 거칠 것이다. 스왑 파티션에서는 위의 과정없이 특정 블럭에 바로 접급할 수 있으므로 불 필요한 오버헤드가 발생하지 않아 속도가 더 빠르기 때문이다.

3.5 서브 디렉토리를 60000개 이상 만들고 싶다.

현재 리눅스의 기본 파일 시스템은 ext2이다. (SuSE는 Reiser 파일시스템이다.) ext2란 Second Extended File System의 약어이며 초기 리눅스 파일 시스템이었던 MINIX에서는 최대 파일이름 14문자, 최대 파티션 64MB밖에 되지 않았고 이런 여러 가지 문제로 파일 시스템이 오늘날의 ext2까지 발전하였다. ext2에서는 255문자의 파일명, 최대 2GB의 파일, 4TB의 디스크 용량을 지원하며 서브디렉토리는 테스트해본결과 32000개까지만 만들어졌다. 다음을 참고하라.


#!/bin/sh
count=70000
i=1
while [ $i -lt $count ]
do
  mkdir $i && echo "$i"
  i=$(($i+1))
done

위는 서브 디렉토리를 만들어주는 shell script이며 서브 디렉토리 이름은 1번부터 count로 지정한 값만큼 만들어 준다.

디렉토리 링크가 둘 다 2Byte 범위까지 표현할 수 있는 것 같은데 파일 시스템에 따라 위와 같은 차이가 났다.

3.6 Reiser 파일시스템 만들기

현재 리눅스의 기본 파일 시스템인 ext2는 신뢰성, 충돌 복구 등의 문제가 있는데 이런 부분들을 해결 할 수 있는 것이 저널링 파일 시스템이다. Reiser 파일 시스템 또한 이런 저널링 파일 시스템의 일종으로 이미 SuSE에서는 기본 파일 시스템으로 Reiser를 선택하고 있다. 머지않아 리눅스의 기본 파일 시스템도 저널링 파일 시스템으로 바뀔 것이다.

  1. 패치파일 받아오기
    
    
    http://devlinux.com/projects/reiserfs/ 또는 
    http://kernel.pe.kr/data.php 에서 자신의 버전에 맞는 패치를 받아온다.
  2. 패치를 적용시킨다.(/usr/src/linux 에서 패치한다.)
    # patch -p1 < 패치파일명 (압축을 풀었을때)
    또는 
    # gzip -cd 패치파일명.gz | patch -p1
    
  3. 커널옵션 선택
    Code maturity level options  --->
       [*] Prompt for development and/or incomplete code/drivers 를 선택하고
    File systems  ---> <*> Reiserfs support 선택한다.
    
  4. 커널 컴파일및 모듈 컴파일, lilo 정보도 고쳐준다.
  5. ReiserFS 유틸 컴파일(mkreiserfs을 만들기위해)
    # cd /usr/src/linux/fs/reiserfs/utils/
    # make
    # make install
    
  6. ReiserFS가 적용된 커널 이미지로 재부팅한다.
  7. ReiserFS 만들기
    (/dev/hdb1 에 만든다고 가정하며 기존 ext2 파일시스템의
     데이터는 지워지므로 백업하던지 아님 새 하드를 달았다고 가정한다.)
    
    # umount /dev/hdb1 (mount 되어있지 않다면 이건 필요없다.)
    # mkreiserfs /dev/hdb1
    # mount /dev/hdb1 /TEST(mount 시킬 디렉토리는 각자 알아서..)
    
  8. /etc/fstab 수정하기
    /dev/hdb1            /TEST             reiserfs    defaults        1 2
    ext2를 reiserfs로 바꾸면 된다.
    
  9. 확인하기
    $ mount
    ...
    /dev/hdb1 on /TEST type reiserfs (rw)
    ...
    위와 같이 reiserfs 라고 나오면 성공
    

Reiser 파일 시스템을 만들고 마운트 시키면 기본으로 32MB의 용량을 잡아먹는다. 이 공간에다가 자체적인 정보를 기록하므로 Reiser 파일 시스템을 위해선 최소 32MB이상의 파티션을 필요로 한다.(나의 /boot 파티션은 16MB여서 reiserfs를 적용시키지 못하였다.)

3.7 커널 2.4.0-test버전에서 X 4.0을 쓰고싶다.(RIVA TNT)

현재 nVidia에서 나오는 X 4.0 드라이버들은 커널 2.2.x의 안정버전에만 적용된다. 개발버전에 적용시킬려면 http://www.darkrock.co.uk/nv/에서 NVIDIA_kernel-0.9-2.3.x.tar.gz를 받아 컴파일 해야한다.(테스트해본 결과 커널 2.4.0-test1-ac18까지만 적용된다.)

3.8 커널 버전을 어떻게 바꾸는가?

어떤 학교의 전산관련 과목 리포트인지 이런 질문을 많이 받았다. 커널 버전만을 가짜로 바꿀려는 이유를 모르겠다.


# vi /usr/src/linux/Makefile

        VERSION = 2
        PATCHLEVEL = 4
        SUBLEVEL = 0
        EXTRAVERSION = -test1-ac18


# vi /usr/src/linux/include/linux/version.h

        #define UTS_RELEASE "2.4.0-test1-ac18"
        #define LINUX_VERSION_CODE 132096
        #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))

위의 Makefile에서 버전 정보를 고쳤다면 컴파일할때 version.h는 자동으로 바뀐다.

이 두 파일들을 원하는 버전으로 바꾸고 컴파일 하면 된다. 잘못 바꾸어서 커널 버전이 맞지 않을 경우 System.map에서 버전이 틀리다고 메세지를 보낼 것이다. 그럴 경우 해당 커널 이미지의 System.map을 없애버려도 무관하다. (System.map이 없다면 어디서 문제가 발생했는지 알 수 없을 것이다.)

3.9 CPU의 정보를 바꾸고 싶다, Bogo Mips를 높이고 싶다

이건 그냥 내가 하고 싶어서 해봤다.

# vi /usr/src/linux/arch/i386/kernel/setup.c
        $ cat /proc/cpuinfo 정보를 고쳐준다.

# vi /usr/src/linux/init/main.c
        $ dmesg 의 보고 밉스를 고쳐준다.
위 두 파일을 원하는 대로 고치면 된다. 약간의 C 프로그래밍만 할 수 있다면 쉽게 원하는대로 바꿀 수 있을것이다.

3.10 KERNEL32.DLL에서 잘못된 연산수행!?

위와 같은 질문을 하시는 분들이 가끔 계신데 MS-WINDOWS 커널을 어떻게 손볼 수 있겠는가? (검색엔진에서 kernel로 검색해서 커널 프로젝트 홈으로 들어왔다더군요.) 성의는 대단하나 단지 손상 안된 다른 KERNEL32.DLL을 카피하라고 할 수밖에...


다음 이전 차례