Linux KerneL CompiLe Guide 윤봉환, el@kldp.org v.0.15, 9 Mar 2001 이 문서에서는 커널과 커널 컴파일에 대해 다룹니다. 커널 소스의 설치와 세부 환경설정, 컴파일과 새 커널 설치에 대해 이야기할 것입니다. ______________________________________________________________________ 목차 1. 커널 1.1 두 가지 커널 버전 1.1.1 버전 번호 1.1.2 앨런 콕스의 커널버전 2. 최신 커널 구하기 2.1 배포판 CD-ROM 2.1.1 레드햇 계열 2.1.2 데비안 배포판 2.2 FTP Site 2.3 리눅스 유저 그룹 3. 커널 소스 설치하기 3.1 컴파일을 위한 기본 도구 알아보기 3.2 컴파일을 위한 기본 도구 설치하기 3.3 커널 소스 풀기 3.4 커널 패치 3.5 한글 패치 3.6 make mrproper 4. 컴파일 환경 설정 명령 4.1 미리 알고 있으면 좋은 것들 4.2 환경설정 인터페이스 4.2.1 make config 또는 make oldconfig 4.2.2 make menuconfig 4.2.3 make xconfig 5. 환경 설정 규칙: "내 커널은 내가 만든다" 6. Code maturity LeveL optionS 7. LoadabLe moduLe SupporT 8. ProceSSor type and featureS 9. GeneraL SetuP 9.1 APM 9.2 사라진 것들.. 10. Memory Technology Devices (MTD) 11. Parallel port support 12. PLug and PLay SupporT 13. BLock deviceS 14. Multi-device support (RAID and LVM) 15. Networking optionS 15.1 Netfilter 15.2 QoS and /or fair queueing 15.3 사라진 것들.. 16. Telephony Support 17. ATA/IDE/MFM/RLL support 18. IDE, ATA and ATAPI Block devices 18.1 사라진 것들 19. SCSI SupporT 19.1 SCSI Low-LeveL driverS 19.2 PCMCIA SCSI adapter support 20. IEEE 1394 (FireWire) support 21. I2O device support 22. Network device SupporT 22.1 Ethernet (10 of 100Mbit) 22.2 Wan interfaces : 22.3 PCMCIA network device support : 23. Amateur Radio SupporT 24. IrDA (infrared) SupporT 24.1 Infrared-port device driverS 25. ISDN SubSySteM 26. OLd CD-ROM driverS (not SCSI, not IDE) 27. Input core support 28. Character deviceS 28.1 I2C support ---> 28.2 Mice ---> 28.3 Joysticks ---> 28.4 Watchdog Cards ---> 28.5 Ftape, the floppy tape device driver ---> 28.6 PCMCIA character device support ---> 29. Multimedia devices 30. FiLe SyStemS 30.1 Native Language Support ---> 30.2 Network FiLe SyStemS 30.3 Partition TypeS 31. ConSoLe driverS 31.1 Frame-buffer support ---> 32. SounD 32.1 AdditionaL Low LeveL Sound driverS 33. USB support 34. KerneL hackinG 35. 커널 컴파일 35.1 청소 35.2 커널 컴파일 명령 35.3 모듈 컴파일 36. 새 커널 설치 36.1 부트 이미지 설치 36.2 /etc/lilo.conf 37. 문제 해결 37.1 새 커널로도 이전 커널로도 부트할 수 없다면? 37.2 나는 CD-ROM으로 부트할 수 없는데: LoadLin 38. Notebook computer 사용자 39. 문서에 대해 39.1 이전 문서와 달라진 것들 ______________________________________________________________________ 1. 커널 커널은 운영체제의 핵심입니다. 메모리에 상주하여 시스템 디바이스와 메모리, 프로세스를 관리하고, 입출력을 처리하는 등 유저의 다양한 요구에 바로 반응합니다. 지금은 다양한 프로그램들을 포함하는 운영체제를 가리키기도 하는 Linux라는 이름도 커널에 붙여진 것입니다. 리눅스의 다른 프로그램처럼 커널도 소스 형태으로 배포됩니다. 커널 소스는 모든 배포판에 들어있으며 ftp나 BBS유저그룹을 통해 다운받을 수 있습니다. 컴파일을 위한 환경은 잘 만들어진 몇 가지 스크립트를 이용하여 쉽게 설정할 수 있고 커널 해킹을 위한 문서 또한 쉽게 구할 수 있습니다. 다른 부분과 마찬가지로 리눅스의 열린 정신이 커널을 빠르고 강하게 만듭니다. 커널 컴파일은 항상 심각하게 다루어지는 주제이지만 왜 컴파일을 굳이 하느냐고 묻는 이들도 많습니다. 대개의 리눅서들이 두 세 가지 정도 이유를 말하는데, 일반적으로 커널 컴파일은 시스템 최적화의 한 수단으로 쓰입니다. 배포판에 포함되어 있는 기본 커널에는 혹시 쓰일지도 모르는 다양한 기능들이 들어 있어 실제로 여러분에게 필요한 커널보다 크기도 크고, 때로는 약간 성능이 떨어질 수도 있습니다. 그래서 많은 리눅서들이 시스템에 가장 적합한 작은 커널을 새로 만들어 리눅스 박스의 성능을 최대로 끌어올리는 것입니다. 또 한가지 이유는 새 커널을 생성해 빠르게 등장하는 진보된 기능을 사용하거나 새로운 장치를 지원하는 것입니다. 그리고 리눅서는 기쁨을 얻습니다. 그래서 어떤 커널 매니아들은 커널 컴파일 자체에 더 큰 흥미를 가진 듯 보이기도 합니다. 1.1. 두 가지 커널 버전 리누스(LinuS TorvaLdS)와 많은 해커들의 노력으로 커널은 매우 빠르게 진보하고 있습니다. 그러나 기능 향상을 위해 빠르게 성장하는 동안 문제가 발생하기도 합니다. 대부분 일반 사용자들이 해결할 수 있는 범위를 넘어서는 것들이어서, 개발자들은 안정성과 발전을 위해 리눅스 커널을 두 가지 버전으로 부릅니다. 새로운 기능들이 실험되는 개발과정의 커널을 개발버전(DeveLopmentaLverSio N)이라 부르며, 새로운 것에 열광적인 리눅서와 테스터, 개발자를 위한 버전입니다. 개발버전은 많은 테스트와 패치과정을 거쳐 안정버전(StabLe verSion or productioN)으로 일반 사용자들에 배포됩니다. 1.1.1. 버전 번호 커널의 버전번호는 2.0.36또는 2.1.35와 같이 세 부분으로 구성되어 있습니다. 처음의 숫자는 커다란 변화가 있을 때 바뀌는 주 버전 번호입니다. 리눅스 커널의 2가 도스의 7보다 하찮게 느껴집니까? 버전 번호를 올리는 것은 개발자 마음이지만 버전번호가 모든 성능을 나타내는 것은 절대 아닙니다. 가운데 숫자는 짝수일 때 안정버전을 뜻하고 홀수일 때 개발버전임을 알려 줍니다. 마지막 숫자는 패치 레벨을 나타내는 서브 넘버입니다. 1.1.2. 앨런 콕스의 커널버전 ac라는 꼬리를 붙여 리누스보다 먼저 커널을 내 놓는 이가 앨런 콕스입니다. 리누스가 새 커널 버전을 발표하기 전에 그보다 면저, 더 다양한 테스트해서 공개하므로, ac 커널이 더 새로운 기능들을 포함할 때가 많습니다. 2. 최신 커널 구하기 이 글을 쓰는 동안 최근 커널은 2.4.2 버전입니다. (이 글은 2.4.2 커널을 기초로 작성되었습니다.) 최신의 커널 소스를 구한다면 FTP사이트나 웹사이트를 통해 다운받습니다. 비교적 최근 배포판 CD-ROM을 가지고 있다면 그 안에서도 찾을 수 있습니다. 2.1. 배포판 CD-ROM 리눅스 안정버전의 커널은 배포판 CD에 포함되어 있지만 아마 가장 최신의 커널은 아닐 것입니다. 2.1.1. 레드햇 계열 국내에 가장 많은 사용자를 가진 레드햇 계열의 배포판에서 커널 소스는 CD-ROM의 RedHat/RPMS 디렉토리안에 헤더(예를 들어 kerneL- header-2.0.36-2.i386.rpm)와 소스(예를 들어 kerneL- Source-2.0.36-2.i386.rpm) 등 크게 두 부분으로 나뉘어 실려 있습니다. 커널 컴파일을 위해서는 두 패키지를 모두 설치해야 합니다. # rpm -q kerneL-source # rpm -Uvh kernel-header-2.2.14.i386.rpm # rpm -Uvh kerneL-source-2.2.14.i386.rpm 그 밖에도 여러가지 패키지들이 있는데 커널 컴파일을 위해 모두 필요한 것은 아닙니다. kernel-source... 커널 소스 rpm kernel-headers... 커널 헤더 rpm kernel-doc... 커널 문� rpm kernel-BOOT... 부팅과 모듈 관련 rpm kernel-smp... 멀티 프로세셈� 때 필요한 rpm kernel-pcmcia... 노트북 pcmcia에 필요한 rpm kernel-ibcs... Intel Binary Compatibility Specification 관련 rpm 2.1.2. 데비안 배포판 데비안 배포판(최근 안정버전인 2.2 potato 버전을 바탕으로 글을 썼습니다)은 꼬리에 .deb라는 확장이름이 붙은 패키지 파일들이 있다. KLDP에서 한글 설정을 더해서 배포하는 포테이토는 모두 세 장인데 그 중 커널 소스는 첫 번째 디스크 /cdrom/dists/potato/main/binary-i386/ 아래 devel/ 디렉토리 안에 들어 있습니다. 커널 헤더는 세번째 디스크 /cdrom/dists/potato/main/binary-i386/devel 디렉토리에 들어 있습니다: 1: devel/kernel-source-2.2.17_2.2.17pre6-1.deb 1: misc/kernel-package_7.04.potato.3.deb 3: devel/kernel-headers-2.2.17_2.2.17pre6-1.deb 3: doc/kernel-doc-2.2.17_2.2.17pre6-1.deb 데비안 패키지를 설치할 때에는 "dpkg -i" 명령을 사용합니다: 첫 번째 시디롬을 넣고: # mount /cdrom # dpkg -i /cdrom/dists/potato/main/binary-i386/devel/kernel-source-2.2.17_2.2.17pre6-1.deb # eject 두 번째 시디롬: # dpkg -i /cdrom/dists/potato/main/binary-i386/devel/kernel-headers-2.2.17_2.2.17pre6-1.deb 세 번째 시디롬: # dpkg -i /cdrom/dists/potato/main/binary-i386/doc/kernel-doc-2.2.17_2.2.17pre6-1.deb 2.2. FTP Site ftp.kernel.org에 anonymous로 접속하여 /pub/linux/kernel디렉토리에서 리누스가 새로 발표한 커널 소스를 받을 수 있습니다. 그 밖의 미러 사이트: o o o o o o o 커널 소스와 함께 패치파일을 받는 것을 잊지 말아야 합니다. 2.3. 리눅스 유저 그룹 천리안, 하이텔, 나우누리 등 PC통신망의 리눅스 유저그룹(동우회?동호회)의 자료실에서 다운 받을 수 있습니다. 일반 전화회선을 이용한 모뎀 사용자라면 인터넷을 통한 다운로드보다 오히려 빠르게 전송받을 수 있습니다. 커널 2.4.2는 25MByteS 정도 크기입니다. 3. 커널 소스 설치하기 이 절에서는 Tar-Ball(tar로 묶은 다음 gzip으로 압축한 패키지) 형태의 소스를 다운받아 적절한 곳에 풀어 놓고, 기초 환경을 구성하는 방법을 설명합니다. 3.1. 컴파일을 위한 기본 도구 알아보기 새 커널을 컴파일하기 위해 업데이트가 필요한 라이브러리나 프로그램이 있는지 확인하여 필요하다면 새로 설치합니다. 그러나 모든 도구들이 반드시 필요한 것은 아닙니다. 예를 들어 pcmcia-cs는 pcmcia장비가 없는 시스템에서는 설치하지 않아도 됩니다. 여러분이 새 커널 소스를 /usr/src아래 설치하고 linux라는 이름으로 링크해 두었다면, 관련된 문서는 /usr/src/linux/Documentation/Changes입니다. 아래는 각 도구마다 최소한의 버전(2.4.2 커널을 위한)과 확인하는 방법입니다. 예를 들어 Gnu C의 버전을 확인할 때에는 "gcc --version"이라는 명령을 사용합니다. ---------------+---------------+-------------------------------------- 패키지 | 최소버전 | 확인하는 방법 ---------------+---------------+-------------------------------------- Gnu C | 2.91.66 | # gcc --version Gnu make | 3.77 | # make --version binutils | 2.9.1.0.25 | # ld -v util-linux | 2.10o | # fdformat --version modutils | 2.4.2 | # insmod -V e2fsprogs | 1.19 | # tune2fs reiserfsprogs | 3.x.0b | # reiserfsck 2>&1|grep reiserfsprogs pcmcia-cs | 3.1.21 | # cardmgr -V PPP | 2.4.0 | # pppd --version isdn4k-utils | 3.1pre1 | # isdnctrl 2>&1|grep version ---------------+---------------+-------------------------------------- 아래는 도구들을 구하는 인터넷 위치입니다. 파일 이름이나 버전 번호는 조금씩 달라질 수도 있습니다: modutils : 위치 - 파일 - modutils-2.4.2.tar.gz util-linux : 위치 - 파일 - util-linux-2.10s.tar.gz E2fsprogs : 위치 - 파일 - e2fsprogs-1.19.tar.gz 혹은 1.19-0.i386.rpm 주의! sourceforge에서 ls 명령을 사용하지 말 것..^^ 파일과 디렉토리가 너무 많아 마치 다운된 듯 보일 수도.. Reiserfsprog : 위치 - 파일 - reiserfs_utils-3.6.25-fsck-3.x.0b.tar.gz, reiserfsprogs-3.x.0d.tar.gz Pcmcia-cs : 위치 - 파일 - pcmcia-cs-3.1.24.tar.gz PPP : 위치 - 파일 - ppp-2.4.0b4.tar.gz Isdn4k-utils : 위치 - 파일 - isdn4k-utils.v3.1pre1.tar.gz 3.2. 컴파일을 위한 기본 도구 설치하기 새 커널 컴파일과 모듈 설정에 쓰이는 도구들을 인터넷으로부터 가져왔다면 다음과 같은 과정을 거쳐 자신의 머신에 설치합니다. 예를 들어 /usr/local/src/kernel-2.4/util-linux-2.10s.tar.gz를 설치한다면: 1. 먼저 적당한 위치에 압축을 풀어놓습니다. # cd /usr/local # tar xvzf /usr/local/src/kernel-2.4/util-linux-2.10s.tar.gz 2. 아마 util-linux-2.10s라는 이름으로 새로운 디렉토리가 만들어지고 그 안에 소스 파일들이 놓일 것입니다. # cd util-linux-2.10s 3. 시스템 정보를 수집해서 컴파일을 위한 기초환경을 구성합니다. # ./configure 4. 3에서 생성한 Makefile등 설정파일을 이용해 컴파일하고 설치합니다. # make;make install 3.3. 커널 소스 풀기 일반적으로 커널 소스는 /usr/src 디렉토리 아래 설치합니다. /usr/src 아래에는 실제 헤더, 커널이 설치된 디렉토리와 그 링크가 있습니다. 이전 커널이 들어있는 디렉토리에 대한 링크를 삭제하고(우선은 링크만 지웁니다) 새 커널 소스가 설치된 디렉토리를 Linux라는 이름으로 다시 링크합니다. # cd /usr/src # rm -f linux # mkdir linux-2.4.2 # tar xvzf linux-2.4.2.tar.gz linux-2.4.2 # ln -s linux-2.4.2 linux RPM(다른 머신에서 미리 컴파일된 바이너리 패키지)이나 dpkg, 혹은 Tar- Ball 형태의 바이너리를 설치하지 않고, 소스코드를 컴파일해야 한다면 /usr/src/linux아래 코드들을 참고합니다. 새로 설치한 커널 소스가 개발버전이라면 컴파일 후 정상적으로 작동되더라도 이전의 안정버전을 삭제하지 않도록 합니다. 3.4. 커널 패치 패치파일은 diff 유틸리티를 이용하여 커널의 일부분을 수정합니다. 패치파일은 빠르게 갱신되며 새로운 패치파일은 이전 패치에 대한 정보를 포함하지 않습니다. 그러므로 패치레벨은 순서대로 모두 적용해야만 합니다. 패치가 많이 이루어진 후라면 커널 소스 전체를 다시 받는 것이 유리할 수도 있습니다. 커널 2.2.9에서 커널 2.4.2로 업그레이드하기 위해서 patch-2.2.10.gz, patch-2.2.11.gz 모두를 순서대로 적용해야 합니다. 아래에 예가 있습니다. 옵션 가운데 p0는 패치파일에 들어있는 경로에 대한 상대적인 위치를 뜻합니다. 예를 들어 패치파일 안에 패치할 대상이 들어 있는 디렉토리와 대상 파일을 "/u/howard/src/blurfl/blurfl.c"이라고 설정했다면 -p0는 "/u/howard/src/blurfl/blurfl.c", -p1은 "u/howard/src/blurfl/blurfl.c", -p4는 "blurfl/blurfl.c"가 됩니다. # cd /usr/src # ls linux linux-2.2.9 patch-2.2.10.gz patch-2.2.11.gzpatch-2.4.2.gz # gzip -cd patch-2.2.10.gz | patch -p0 # gzip -cd patch-2.2.11.gz | patch -p0 # gzip -cd patch-2.4.2.gz | patch -p0 많은 패치 작업은 셸의 for 명령을 이용해 자동화할 수 있습니다. # for LeveL in 10 11 12 ; do > gzip -cd patch-2.2.$[LeveL].gz | patch -p0 > done # /usr/src/linux/scripts 디렉토리에는 여러 단계의 패치 작업을 자동으로 실행하는 스크립트 patch-kerneL이 있습니다.patch-kerneL은 /usr/src 아래에 있는 커널 패치파일들과 커널 소스의 버전과 비교하여 순서에 따라 패치를 적용합니다. # cd /usr/src # ls linux linux-2.2.9 patch-2.2.10.gz patch-2.2.11.gzpatch-2.4.2.gz # linux/scripts/patch-kernel 패치가 성공했다면 패치 대상이 된 파일의 원본은 이름끝에 .orig를 붙여 백업됩니다. 패치 과정에서 문제가 생겨 실패했다면 실패한 파일 이름 뒤에 .rej를 붙인 파일을 만듭니다. *.rej파일을 살펴보고 패치 작업을 다시 수행합니다. # find /usr/src/linux/ -name "*.rej" *.rej 파일을 찾을 수 없고 패치가 성공했다면 *.orig파일을 삭제합니다. # find /usr/src/linux/ -name "*.orig" -exec rm -f {} \; 패치된 커널 소스 디렉토리 이름을 패치레벨 번호로 바꾸고 링크를 다시 설정합니다. # cd /usr/src # rm -f linux # mv linux-2.2.9 linux-2.4.2 # ln -s 3.5. 한글 패치 최근 버전 커널에서는 한글 코드페이지와 로케일이 들어 있어 따로 패치하지 않아도 한글로 된 파일 이름 등을 사용할 수 있습니다. 3.6. make mrproper 이전에 설정한 정보를 지우거나 새로운 커널 소스를 가져다 컴파일 할 때에는 이 명령을 먼저 사용해야 합니다. 이전 커널을 컴파일할 때 만들어진 오브젝트 파일(*.o)과 의존성 설정, 컴파일 환경 설정값, 버전 정보 등 새로 시작하는 컴파일에 영향을 주는 이전 정보들을 삭제합니다. 이전에 설정된 컴파일환경을 재사용한다면 이 과정을 건너뜁니다. # cd /usr/src/linux # make mrproper 4. 컴파일 환경 설정 명령 이 문서는 IBM PC 스타일의 시스템을 가진 일반 사용자를 위한 컴파일 환경을 조언합니다. 알파 시스템이나 선 머신을 가지고 있다면 한글 리눅스 문서 프로젝트 팀의 홈페이지를 찾아가 봅니다. 4.1. 미리 알고 있으면 좋은 것들 컴파일 환경 설정을 위해 하드웨어 구성 정보를 기록해둡니다. 사운드 카드, 네트워크 디바이스 등의 IRQ, I/O port, DMA addreSS, 그리고 비디오 카드 등 장치의 특성을 알고 있어야 합니다. 여러분의 시스템에 어떤 장치와 칩셋이 들어있는지 알아보려면 /proc/pci, /proc/sound, /proc/scsi/scsi 등 파일을 열어봅니다. 다음은 이 글을 쓰고있는 리눅스 박스입니다. PCI 버스를 지원하는 칩셋과 장치 몇 가지를 확인할 수 있습니다: # cat /proc/pci PCI devices found: Bus 0, device 0, function 0: Host bridge: VIA Technologies VT 82C598 Apollo MVP3 (rev 4). Medium devsel. Fast back-to-back capable. Master Capable. Latency=16. Prefetchable 32 bit memory at 0xe0000000 [0xe0000008]. Bus 0, device 1, function 0: PCI bridge: VIA Technologies VT 82C598 Apollo MVP3 AGP (rev 0). Medium devsel. Master Capable. No bursts. Min Gnt=12. Bus 0, device 7, function 0: ISA bridge: VIA Technologies VT 82C586 Apollo ISA (rev 71). Medium devsel. Master Capable. No bursts. Bus 0, device 7, function 1: IDE interface: VIA Technologies VT 82C586 Apollo IDE (rev 6). Medium devsel. Fast back-to-back capable. Master Capable. Latency=32. I/O at 0x6400 [0x6401]. Bus 0, device 7, function 2: USB Controller: VIA Technologies VT 82C586 Apollo USB (rev 2). Medium devsel. IRQ 9. Master Capable. Latency=32. I/O at 0x6800 [0x6801]. Bus 0, device 7, function 3: Host bridge: VIA Technologies VT 82C586B Apollo ACPI (rev 16). Medium devsel. Fast back-to-back capable. Bus 0, device 11, function 0: Ethernet controller: AMD Unknown device (rev 82). Vendor id=1022. Device id=2001. Medium devsel. Fast back-to-back capable. IRQ 11. Master Capable. Latency=32. Min Gnt=24.Max Lat=24. I/O at 0x6c00 [0x6c01]. Non-prefetchable 32 bit memory at 0xed001000 [0xed001000]. Bus 0, device 12, function 0: Ethernet controller: DEC DC21140 (rev 34). Medium devsel. Fast back-to-back capable. IRQ 10. Master Capable. Latency=32. Min Gnt=20.Max Lat=40. I/O at 0x7000 [0x7001]. Non-prefetchable 32 bit memory at 0xed000000 [0xed000000]. Bus 1, device 0, function 0: VGA compatible controller: NVidia Unknown device (rev 21). Vendor id=10de. Device id=2c. Medium devsel. Fast back-to-back capable. IRQ 10. Master Capable. Latency=32. Min Gnt=5.Max Lat=1. Non-prefetchable 32 bit memory at 0xe8000000 [0xe8000000]. Prefetchable 32 bit memory at 0xea000000 [0xea000008]. 4.2. 환경설정 인터페이스 환경 설정을 위한 인터페이스는 make config, make menuconfig, make xconfig 세 가지가 있습니다(이전 설정 정보는 그대로 둔 채 새로운 옵션들에 대해서만 물어보는 make oldconfig도 있습니다). make는 "makefile"에 서술된규칙을 이용하여 소스코드 파일들을 관리합니다. 최근 변경을 적용하여 소스코드를 오브젝트 파일로 컴파일하고 라이브러리 파일과 링크하여 실행 가능한 파일로 컴파일 하는 과정들을 자동으로 처리합니다. 4.2.1. make config 또는 make oldconfig 행 단위로 환경 설정을 하는 make config는 bash나 csh에서 실행됩니다. 세부적인 설정을 할 수 있지만 가장 불편한 인터페이스로 잘 쓰이지 않습니다. 그러나 make oldconfig는 꽤 쓸만합니다. 4.2.2. make menuconfig 아래는 메뉴식 설정화면의 한 예입니다. Linux Kernel v2.4.2 Configuration ---------------------------------------------------------------------------- +---------------------------- Console drivers ----------------------------+ | Arrow keys navigate the menu. selects submenus --->. | | Highlighted letters are hotkeys. Pressing includes, excludes, | | modularizes features. Press to exit, for Help. | | Legend: [*] built-in [ ] excluded module < > module capable | | +---------------------------------------------------------------------+ | | | [*] VGA text console | | | | [ ] Video mode selection support | | | | MDA text console (dual-headed) (EXPERIMENTAL) | | | | Frame-buffer support ---> | | | | | | | | | | | | | | | | | | | | | | | | | | | +---------------------------------------------------------------------+ | +-------------------------------------------------------------------------+ |