신영진 : 충북대학교 공과대학원 wonshin@enveng.chungbuk.ac.kr
|
리눅스 박스의 전원을 켜는 순간부터 login화면에 아이디와 패스워드를 입력하고 여러분의 리눅스 박스에 로긴할 때 까지 우리는 윈도우와 사뭇 다른 메시지와 화면들을 대하게 됩니다. 처음 유닉스 계열의 리눅스 운영체제를 접한 사람들에게는 복잡 미묘하고 까다롭게만 보이는 메시지들이 가득한 화면에 부담감과 약간의 공포를 느끼게 되죠. 하지만, 이 모든 과정은 합리적이고 과학적인 방법을 이용한 부팅(Booting)과정입니다. 리눅스 박스의 부팅(Booting)은 매우 중요한 과정입니다. 또한, 부팅(Booting)과정을 이해하면, 리눅스 박스의 종료과정도 저절로 이해가 됩니다. 부팅(Booting)이라는 것은 bootstrap의 약어입니다. 이것은 보통 신발끈을 묶은 상태, 즉, 준비가 된 상태를 일컫는 말로, 스스로 일어선다는 의미로 자수성가를 말하기도 합니다. 즉, 리눅스 박스가 하드웨어 상태로 놓여져 있는 것이 아니고, 운영체제가 메모리에서 작동을 하여 시스템의 각 하드웨어(프로세서, 마우스, 키보드, 랜카드, 사운드 카드, 각종 주변기기)를 알맞게 사용할 수 있는 준비를 하는 작업입니다. 이것은 전체적으로 bootstrapping이라고 합니다. 즉, 커널(Kernel)이 메모리에 복사되고, 실행되어, 모든 하드웨어를 제어하여 일정한 작업을 할 수 있게 준비되는 상태입니다. 일반적인 유닉스 계열 운영체제의 부팅(Booting)
과정은 시스템에 장착된 ROM이 작동하고, 그후 root디스크의 0번째
디스크에 부트 프로그램(리눅스의 LILO)이 작동하여서 커널(Kernel)을
메모리에 복사하고, 실행시킵니다. (하드웨어에 따라 달라지지만,
일반적인 인텔기반의 유닉스에서는 활성화된 root파티션의 마스터
부트 레코드(Master Boot Record)에 부트 프로그램이 기록되어 있습니다.)
그러면, 시스템의 제어권이 유닉스 계열 운영체제로 옮겨서 작동을
하게 됩니다. 즉, 커널이 시스템의 작동을 관리하고, 메모리에 계속적으로
남아서 기본적인 하드웨어 제어를 담당하게 됩니다. 이것이 운영체제의
부팅입니다. 리눅스 박스의 전체적인 부팅(Booting)과정을 알아보도록
하겠습니다.
1. 리눅스 박스의 전체적인 부팅과정(Booting process) 먼저, 전체적인 리눅스 부팅(Booting) 과정에 대한 이해를 해보기로 하겠습니다. 아래의 [그림 1]은 전체적인 리눅스 부팅(Booting)과정을 설명하고 있습니다. 전원을 켜고, 콘솔에 login메시지가 나오기까지의 전체적인 과정입니다. [그림 1] 사용자가 느끼는 일반적인 리눅스 박스의 부팅(Booting)과정 전원을 사용자가 켜게 되면, 시스템의 바이오스가 작동하고, 먼저, LILO를 작동시키게 됩니다. 이때, LILO는 /etc/lilo.conf의 설정을 읽어서 커널(보통의 경우 vmlinuz를 사용합니다.)의 위치를 파악하고 읽은 커널(Kernel)을 메모리에 적재하고, 실행합니다. 그런 다음에 Sysvinit를 실행하여서 대부분의 운영체제의 서비스 데몬(아파치 웹서버, 메일 서버같은 것부터, atd, crond같은 시스템의 기초적인 작업까지 포함한 프로그램들)이 실행되고, 리눅스 박스가 정상적인 운영체제로서의 역할을 시작합니다. 가상 콘솔은 mingetty 프로그램이 터미널을 열어줍니다. 그 다음, login 과정을 위해서 /bin/login 프로그램이 실행됩니다. 그 후 설정한 쉘에 따라서 로긴을 하게 됩니다. 이 모든 과정이 리눅스가 시작되는 부팅(Booting) 진행과정입니다. 만약, 엑스윈도우로 실행을 시키셨다면, xdm이 실행되어서 리눅스 박스에서 엑스윈도우가 실행되어 로긴을 하게 됩니다. 이제부터는 리눅스 박스의 부팅(Booting)과정에 대해서 좀 더 쉽게 원리를 설명하고자 합니다. 먼저 리눅스박스에서 여러분들의 손으로 직접 전원스위치를 누르면서 리눅스박스의 부팅(Booting)이 시작됩니다.
2. LILO(Linux Loader) 대부분의 사용자들은 인텔 리눅스 박스에서 LILO나 Loadlin을 사용하고 계실 것입니다. 차이점은, 바로 리눅스 부팅(Booting)을 원할 때 하드디스크나 디스켓의 부트 섹터(디스크의 첫번째 섹터를 말합니다.)에 설치하고 LILO를 사용하고, 여러가지 사정으로 인해 다른 운영체제를 부팅(Booting)한 다음 리눅스 부팅(Booting)을 하기 위해서는 Loadlin을 사용하는 것입니다. 물론, 알파 리눅스 박스는 MILO, 스팍 리눅스 박스에서는 SILO를 사용하지만, 부팅(Booting) 과정에서 하드디스크의 커널을 읽고 커널(Kernel)을 메모리에 복사하고 실행시키는 작업을 수행하는 것은 모두 다 동일합니다. (MILO나 SILO의 경우에는 /etc/lilo.conf를 사용하지 않고 다른 외부적인 옵션이나 firmware로 해결을 합니다.) [그림 2] LILO의 작업 LILO는 [그림 2]와 같이 일단 작동을 시작하면, /etc/lilo.conf의 설정파일을 읽어서 커널(Kernel)의 위치를 파악합니다. 그 다음, 커널(Kernel)을 메모리에 복사를 하고, 실행을 합니다. 보통의 경우 아래의 메시지와 같이 커널(Kernel)의 크기가 커져서 압축을 하여서 만드므로, 실행시키기 앞서서 압축을 풀고 실행을 합니다. LILO boot: LILO는 하드웨어 설정이나, 부팅(Booting)을 맘대로 할 수 없게 패스워드 같은 것까지 /etc/lilo.conf에 설정할 수가 있어서 매우 편리합니다. 이 때는 하드디스크가 읽기만 할 수 있는 상태로 작동을 합니다.
3. 커널(Kernel) 실행 커널(Kernel)이 실행되면, [그림 3]과
같은 메시지를 접하게 될 것입니다. [그림 3] 커널(Kernel) 실행 메시지 [그림 3]은 필자가 관리하고 있는 데비안 알파 리눅스 박스의 부팅(Booting) 메시지입니다. 리눅스 박스에서 커널(Kernel)의 실행은 하드웨어에 생명을 불어넣은 과정과 같습니다. 커널(Kernel)은 리눅스 박스의 리소스를 배분하고, 메모리를 관리하며, 프로세서를 제어하는 역할을 합니다. 운영체제의 역할을 하게 됩니다. 메시지를 자세히 보면, 각 하드웨어의 역할 및 동작을 담당하고, 각종, 프로토콜이나, 표준방식에 대해서 작동하는 것을 알 수가 있습니다. ■ Linux version 2.2.10 (root@enveng) (gcc version
egcs-2.91.60 Debian 2.1 <-- 커널(Kernel)이 버전이 얼마고, 언제,
무엇으로 컴파일되었는가를 보여줍니다. ■ Booting on EB164 variation SX164 using machine
vector SX164 <-- 시스템이 어느 프로세서를 사용하는지 알 수 가 있습니다. ■ Command line: bootdevice=sda2 bootfile=boot/vmlinuz
root=/dev/sda2 <-- 부팅(Booting)디바이스명과, 부팅(Booting)커널(Kernel)의 위치를 보여줍니다.{인텔 버전에서는 보여주지 않는다.} ■ Console: colour VGA+ 80x25 <-- 콘솔이 VGA모드를 사용하고, 가로80 세로 25에 글자를 표시할 수 있다. ■ Calibrating delay loop... 528.48 BogoMIPS <-- 프로세서의 속도를 나타내는 척도입니다. 정확하지 않을 수도 있으나 BogoMIPS는 Milion Instructions Per Second의 약자로 초당 실행시키는 프로세서 명령어 수를 100만개로 잡고, 나타내는 것으로, 수치가 높은 프로세서 일수록 높은 실행속도를 나타냅니다. 하지만, 프로세서마다 조건마다 다른 수치를 나타내므로, 절대적인 것은 아닙니다. ■ Memory: 257112k available <-- 사용가능한 메모리의 양을 나타냅니다. ■ VFS: Diskquotas version dquot_6.4.0 initialized <-- 가상 파일 시스템의 초기화를 말합니다.
가상 파일 시스템이라는 것은 [그림 4]와 같이 [그림 4] Virtual File System 본래의 파일 시스템과 다른 파일 시스템간의 중간에서 완충역할을 통해 파일 시스템을 구성하므로써 서로 다른 파일 시스템간에도 파일을 읽거나, 쓸 수가 있도록 하는 리눅스만의 독특한 파일 시스템입니다. 이 파일 시스템을 통해 윈도우95/98/NT나 다른 맥, 솔라리스와 같은 운영체제의 파일 시스템을 읽을 수가 있습니다. ■ Alpha PCI BIOS32 revision 0.04 <-- PCI바이오스 버전과 설정에 대해서 나오며, 이 바이오스를 이용합니다. ■ Linux NET4.0 for Linux 2.2 <-- 네트워크를 사용하기 위한 소켓과 TCP/IP프로토콜의 실행을 나타냅니다. ■ Starting kswapd v 1.5 <-- 파일시스템의 스왑영역이 아니고 커널(Kernel)의 스왑영역을 실행하는 것입니다. ■ Detected PS/2 Mouse Port. <-- 마우스포트를 찾았다는 메시지입니다. ■ Serial driver version 4.27 with no serial options
enabled <-- 직렬포트의 값을 나타냅니다. 보통, 윈도우에서
com1, 2, 3, 4라고 불리는 것을 말합니다. ■ pty: 256 Unix98 ptys configured <-- pty를 256명까지 허용한다는 것입니다. 커널(Kernel)을 컴파일할 때 [Character devices]에서 설정을 해 줄 수가 있습니다. 동시에 접속할 수 있는 사용자 수를 결정합니다. pty라는 것은 원격으로 터미널에 접속한 것을 말합니다. ■ Floppy drive(s): fd0 is 2.88M <--플로피 디스크가 2.88메가를 사용할 수 있고, Floppy DiskControlle에 대해서 기술합니다. ■ md driver 0.36.6 MAX_MD_DEV=4, MAX_REAL=8 <-- md(Multiple Devices)는 여러 개의 디바이스를
사용하도록 하는 기능을 말합니다. ■ (scsi0) <Adaptec AHA-294X Ultra SCSI host
adapter> found at PCI 9/0 disk sda at scsi0,
channel 0, id 0, lun 0 <-- SCSI Controller를 찾고 그 다음, 스커지 번호에 따라서 시디롬, 하드디스크 등을 찾아 정보를 출력하고, 사용 가능하다는 메시지입니다. 필자는 Adaptec AHA-294X Ultra SCSI host adapter를 사용합니다. ■ ne2k-pci.c:v0.99L 2/7/98 D. Becker/P. Gortmaker
http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html <--ne2000호환 pci랜카드 두 개를 커널(Kernel)에서 찾아서 실행시킨 메시지 입니다. 또한, 3Com509 랜카드를 찾아서 eth2에 설정한 메시지입니다. ■ Partition check: <--현재 리눅스 박스의 파티션 정보가 출력됩니다. 이 중에 <sda5 sda6>의 메시지는 논리 파티션을 나타냅니다. 또한, 루트 파티션이 읽기가능으로 마운트 되었음을 나타냅니다. ■ Freeing unused kernel memory: 48k freed <--파티션의 스왑영역을 메모리에 추가하여 활성화 시키는 메시지입니다.
그밖의 메시지 ■ Soundblaster audio driver Copyright (C) by
Hannu Savolainen 1993-1996 <-- 사운드 카드가 있을 경우에는 사운드
설정에 관해서 메시지가 출력됩니다. ■ Checking 386/387 coupling... OK, FPU using
exception 16 error reporting. <-- 첫번째 메시지는 386에서 보조 수치연산 장치가 달려 있지 않을 경우에 체크하는 메시지로, 보조 수치연산 장치가 내장되어 있음을 확인하는 메시지입니다. 두 번째 메시지는 시스템에 hlt 명령어를 보내서 시스템을 일단 정지시켜 보는 메시지입니다. 일단은 시스템의 안정성을 확인하기 위해서 프로세서 명령어인 hlt를 보내서 시스템을 정지시키고, 정상적인 종료가 되는 가를 확인합니다. 세 번째 메시지는 펜티엄 버그를 수정하고 보완해 줄 수 있는 소프트웨어적인 장치인 워크어라운드를 실행하는 메시지입니다. 이와 같은 커널 메시지는 dmesg 명령어를 사용하여 다시 출력해 볼 수가 있습니다. 또한, 부팅한 후에 일정량의 버퍼에 들어 있는 메시지를 Shift키와 PageUP, DOWN키를 사용하여 최근 메시지를 볼 수 있습니다. ※ 참고
4. Sysvinit 실행 커널(Kernel)이 실행되어서 운영체제가 하드웨어의 모든 기능을 제어하게 되었을 때 Sysvinit프로그램이 실행되게 됩니다. init프로그램에는 유닉스계열처럼 System V계열과 BSD계열이 있습니다. 리눅스에서는 System V init프로세서를 사용하고 있습니다. init는 커널(Kernel)에 의해 생성되는 첫 번째 프로세서로서, initialize의 약자입니다. 즉, 초기화를 한다는 것이죠, 약간의 유닉스 지식을 가지고 계신 분이라면, 부모프로세서와 자식프로세서라는 말을 들어 보셨을 것입니다. 유닉스의 경우에는 하나의 프로그램이 실행되어서 계속적으로 인간의 자손이 아기를 낳듯이 프로세서를 낳고 낳고 하면서 이어지는 것입니다. 최초의 시작되는 프로그램을 통해서 모든 프로그램의 실행이 제어되고, 통제되어지는 것입니다. 이 같은 원리로 상위의 프로세서를 제거하면(유닉스에서는 kill라는 명령어를 사용합니다.) 아래의 하위 프로세서는 죽거나, 영혼(좀비 프로세서라고들 하지요)처럼 컴퓨터의 세계를 떠돌아 다니게 됩니다. 이런 운영방식은 거의 모든 운영체제에서 동일합니다. 사실 프로세서에서 엄격하게 말하면 처음으로 실행되어지는 것은 커널의 Scheduler라는 프로세서입니다. 이것은 실행을 위한 프로세서의 일정을 정하고, 실행할 순서, 시간, 길이를 결정하는 작용을 합니다. 한마디로 fork()와 exe()를 이용해서 프로세서를 만드는 것입니다. 이 프로세서는 커널에서 작동을 하기 때문에 ps나 pstree에서도 볼 수가 없습니다. ※ 참고 fork exec init프로세서가 시작이 되면, 그 아래로 fork와 exec를 이용해서 시스템의 기본적인 atd, crond, inted, gpm, httpd, innd, klogd, lpd등의 데몬들이 실행됩니다. init는 제일 먼저 실행되기 때문에 항상 프로세서 아이디(PID)는 1이고, 리눅스 박스가 shutdown될 때에도 제일 마지막으로 프로세서과정에서 종료됩니다. 리눅스 박스의 프로세서가 어떻게 되어 있는가는 [그림 5]와 같이 ps와 pstree를 이용하여 프로세서 아이디와 그 구조에 대해서 시각적으로 알 수가 있습니다. [그림 5] init프로세서의 프로세서 위치 위의 [그림 5]를 보면, 흥미로운 것들을 볼 수가
있습니다. inetd-in.telnetd-login-bash--pstree 이 외에도 프린터사용을 위한 lpd데몬이라든지 마우스 사용을 위한 gpm이라든지 수맣은 실행 프로그램들이 init를 통해서 실행되어지고 있다는 것을 알 수 가 있습니다. 이 중에서 앞서 이야기한 프로세서의 종속성을 실험하기 위해서 inetd-in.telnetd-login-bash-pstree중에 login이나 in.telnetd데몬을 kill명령어(kill -9 PID)를 이용해서 종료시킨다면, 아마도 하위에 있는 자식 프로세서 bash와 pstree는 init와 연결고리가 끊어지게 되어서 종료되게 될 것입니다. ※ 참고 BSD계열의 부팅과정에서는 swapper가 sched를
대신하여서 프로세서를 생성시킵니다. 그런다음에 init가 시작을
하지요. BSD와 System V의 부팅 과정은 아래와 같이 다릅니다.
5. 리눅스 박스의 자세한 Sysvinit 작동 과정 System V 실제적인 이해는 Run-level에 대한
이해를 해야만 합니다. 유닉스계열인 리눅스박스에서는 Run-level이라는
독특한 방법을 사용하여 여러가지 시작 방법을 가지고 있으며, 종료도
Run-level을 통해서 실행이 되어집니다. Run-level은 각 배포판마다
다르지만, 일정한 형식을 따르고 있으므로 약간의 지식만 가진다면,
이해하기 쉽습니다. init작용을 이해해 보기로 하겠습니다. 레드헷 리눅스의 /etc/inittab파일입니다. 한번 살펴보기로 하겠습니다. id:3:initdefault: si::sysinit:/etc/rc.d/rc.sysinit l0:0:wait:/etc/rc.d/rc 0 ud::once:/sbin/update ca::ctrlaltdel:/sbin/shutdown -t3 -r now pf::powerfail:/sbin/shutdown -f -h +2 “Power
Failure; System Shutting Down” pr:12345:powerokwait:/sbin/shutdown -c “Power
Restored; Shutdown Cancelled” 1:2345:respawn:/sbin/mingetty tty1 x:5:respawn:/etc/X11/prefdm -nodaemon id:runlevels:action:process action은 아래와 같은 명령어를 사용할 수 있습니다. ※ 참고 init가 시작되는 시점은 커널의 하드웨어 찾기와 설정이 끝난 시점부터 시작이 됩니다. 아래의 메시지는 레드헷 6.0기준으로 구성한 메시지입니다. 다른 배포판들에서 약간의 차이가 있습니다. INIT : version 2.74 booting
-----------------1 1번의 메시지는 INIT가 시작되면서 2.74버전의
SYSVINIT프로그램이 실행이 됩니다. 2번 메시지는 기본적인 키보드와 폰트가 설정되어
작동이 가능하게 됩니다. 3번 메시지는 하드 디스크의 스왑파티션이 사용가능
하도록 활성화 시킵니다. 4번 메시지는 /etc/sysconfig/network파일을
읽어서 hostname을 설정합니다. 5번 메시지는 파일 시스템을 검사하고, 마운트를
하는 과정입니다. # A return of 2 or higher means there were
serious problems. PS1=”(Repair filesystem) \#”; export PS1 6번 메시지는 마운트를 하고 나서 쿼터를 실행시키는
것입니다. if [ -x /sbin/quotaon ]; then 7번 메시지는 시간 설정을 하는 것입니다. # convert old style clock config to
new values CLOCKDEF=”” case “$UTC” in 8번 메시지는 스왑 공간을 실행시키는 메시지입니다. [그림 6] init의 부팅과정 리눅스 배포판 중 레드헷/칼데라, 데비안, S.u.S.E는
서로 다른 INIT구조로 엮어져 있습니다. 서로 다른 사람들이 만들다
보니 같은 프로그램과 같은 리눅스를 만들어도 아래 그림과 같이
서로 다른 INIT구조를 나타냅니다. 하지만, 기본적인 작동방식은
동일합니다. [그림 7] 배포판의 INIT파일 구조 레드헷/칼데라 리눅스에서는 run-level이 아래와
같습니다. 데비안 리눅스에서는 run-level이 아래와 같습니다. S.u.S.E 리눅스에서는 run-level이 아래와 같습니다. 유닉스에서는 실행시키고자 하는 프로그램(데몬)을
작동시키는 스크립트들을 한 곳에 모여두고 run-level에 따라서
rc0.d, rc1.d, rc2.d, rc3.d, rc4.d, rc5.d, rc6.d에 링크를 해
놓습니다. 이럴 때, 아주 간단한 법칙이 하나 있습니다. S로
링크를 시작하는 것은 시작을 의미하는 것이고, K로 시작하여 링크해
높은 것은 종료를 의미하는 링크입니다. 그 다음에 숫자는 우선순위를
나타내는 것입니다. 위의 이런 법칙은 스크립트에 의해서 작동이
제어됩니다. ※ 참고 #See how we were called. [그림 8]은 원본 스크립트들은 /etc/rc.d/init.d에
존재하면서 run-level 3에 링크되는 것을 보여주고 있습니다. 예제에는
웹데몬 httpd가 run-level 3에 S: 85:httpd 시작:85번째로: httpd데몬이름
형식으로 링크 되어 있는 것을 볼 수가 있습니다. 또한, run-level
0에 15번째로 링크되어 있는 것을 볼 수가 있습니다. 만약
여러분이 부팅을 하면서 run-level 3로 부팅을 하면, 웹데몬 httpd는
85번째로 실행이 됩니다. 그리고 다시 여러분이 리눅스 박스를 종료시키면
run-level 0이므로 15번째로 웹데몬 httpd가 종료를 하게 됩니다. [그림 8] run-level에 따라서 스크립트 링크하기(레드헷 리눅스 기준) ※ 참고 Red Hat Linux release 6.0 (Hedwig) 레드헷에서는 /etc/rc.d/rc.sysinit에서 부팅될
때 실행되는 스크립트가 모아져 있지만, S.u.S.E는 /etc/rc.d/boot에
있습니다. 또한, 데비안은 조금 복잡하게 구성이 되어져 있습니다.
/etc/init.d/rcS스크립트가 작동을 하게 됩니다. 그러면, /etc/rcS.d의
링크된 스크립트가 작동하게 됩니다. [그림 9] 레드헷/칼데라의 부팅과정 [그림 10] 데비안의 부팅과정 [그림11] S.u.S.E의 부팅과정 ※ 참고 S.u.S.E에서는 done이라는 메시지를 컬러풀한
메시지로 역시 볼 수 있을 것입니다. 이 설정은 /etc/rc.config에
있습니다. [그림 12] 리눅스 박스의 부팅 전원을 켜면, 바이오스가 작동이 되고, root파티션의 MBR에 있는 LILO를 읽게 됩니다. LILO는 /etc/lilo.conf파일을 참조하여서 커널의 위치를 파악하고 읽습니다. 메모리에 적재한 커널을 일단, LILO는 압축을 풀고, 실행을 합니다. 이 때, 커널은 하드웨어의 디바이스를 찾고, 설정을 수행합니다. 그리고 난 다음, 커널의 sched로 시작된 INIT프로세서가 /etc/inittab을 참조하여 초기화 작업과 run-level을 결정합니다. 그 후에는 mingetty가 가상 콘솔을 열고, 사용자가 로긴하기 위해서는 login프로그램이 작동하여 인증을 거치면, 쉘이 작동하게 됩니다. 이 모든 과정을 부족하나마, 이해하셨길 바라며, 리눅스 박스의 부팅과정 이해에 도움이 되길 바랍니다. ※ 참고 리부팅도 단지 run-level이 6으로 바뀌는 과정에
불과합니다. 이 모든 작용은 /etc/rc.d/rc6.d의 내용을 그대로 반영하게
됩니다. 다음 번에는 스크립트들에 대한 이야기를 해보도록 하겠습니다. 부팅과정에 나타나는 스크립트들은 어떻게 작성하는 것이며, 어떻게 동작하는 것에 대한 내용을 다루어 보도록 하겠습니다. |