강좌
클라우드/리눅스에 관한 강좌입니다.
리눅스 분류

리눅스 부팅 심층과정(lilo, init, runlevel)

작성자 정보

  • 웹관리자 작성
  • 작성일

컨텐츠 정보

본문

icon01.giftitle24.gif



-lilo, init, runlevel-

신영진 : 충북대학교 공과대학원 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:
Loading linux..........
Uncompressing Linux... OK, booting the kernel

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
   (egcs-1.1.1 release)) #2 Sun Jun 30 09:55:13 KST 2019

<-- 커널(Kernel)이 버전이 얼마고, 언제, 무엇으로 컴파일되었는가를 보여줍니다.
필자가 데비안 알파2.1리눅스이고 KST(Korean Standard Time)기준으로 6월 30일날 커널(Kernel)을 2.2.10으로 egcs를 이용해서 컴파일했다는 메시지입니다.

■ 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: Probing PCI hardware
    SMC37c669 Super I/O Controller found @ 0x3f0

<-- PCI바이오스 버전과 설정에 대해서 나오며, 이 바이오스를 이용합니다.

■ Linux NET4.0 for Linux 2.2
    Based upon Swansea University Computer Society NET3.039
    NET4: Unix domain sockets 1.0 for Linux NET4.0.
    NET4: Linux TCP/IP 1.0 for NET4.0
    IP Protocols: ICMP, UDP, TCP

<-- 네트워크를 사용하기 위한 소켓과 TCP/IP프로토콜의 실행을 나타냅니다.

■ Starting kswapd v 1.5

<-- 파일시스템의 스왑영역이 아니고 커널(Kernel)의 스왑영역을 실행하는 것입니다.

■ Detected PS/2 Mouse Port.

<-- 마우스포트를 찾았다는 메시지입니다.

■ Serial driver version 4.27 with no serial options enabled
    ttyS00 at 0x03f8 (irq = 4) is a 16550A
    ttyS01 at 0x02f8 (irq = 3) is a 16550A

<-- 직렬포트의 값을 나타냅니다. 보통, 윈도우에서 com1, 2, 3, 4라고 불리는 것을 말합니다.

■ pty: 256 Unix98 ptys configured

<-- pty를 256명까지 허용한다는 것입니다. 커널(Kernel)을 컴파일할 때 [Character devices]에서 설정을 해 줄 수가 있습니다. 동시에 접속할 수 있는 사용자 수를 결정합니다. pty라는 것은 원격으로 터미널에 접속한 것을 말합니다.

■ Floppy drive(s): fd0 is 2.88M
    FDC 0 is a post-1991 82077

<--플로피 디스크가 2.88메가를 사용할 수 있고, Floppy DiskControlle에 대해서 기술합니다.

■ md driver 0.36.6 MAX_MD_DEV=4, MAX_REAL=8

<-- md(Multiple Devices)는 여러 개의 디바이스를 사용하도록 하는 기능을 말합니다.
대표적으로 RAID를 말합니다. RAID기능이 커널(Kernel)에 적재되었음을 말합니다.

■ (scsi0) <Adaptec AHA-294X Ultra SCSI host adapter> found at PCI 9/0
    (scsi0) Wide Channel, SCSI ID=7, 16/255 SCBs
    (scsi0) Warning - detected auto-termination
    (scsi0) Please verify driver detected settings are correct.
    (scsi0) If not, then please properly set the device termination
    (scsi0) in the Adaptec SCSI BIOS by hitting CTRL-A when prompted
    (scsi0) during machine bootup.
    (scsi0) Cables present (Int-50 YES, Int-68 YES, Ext-68 NO)
    (scsi0) Downloading sequencer code... 413 instructions downloaded
    (scsi0):Adaptec AHA274x/284x/294x (EISA/VLB/PCI-Fast SCSI) 5.1.17/3.2.4
           <Adaptec AHA-294X Ultra SCSI host adapter>
    scsi : 1 host.
    (scsi0:0:0:0) Synchronous at 20.0 Mbyte/sec, offset 8.
      Vendor: SEAGATE   Model: ST19101W   Rev: 0014
      Type:   Direct-Access        ANSI SCSI revision: 02
    Detected scsi

     disk sda at scsi0, channel 0, id 0, lun 0
    (scsi0:0:2:0) Synchronous at 10.0 Mbyte/sec, offset 15.
      Vendor: PIONEER  Model: CD-ROM DR-U12X  Rev: 1.06
      Type:   CD-ROM             ANSI SCSI revision: 02  
    Detected scsi CD-ROM sr0 at scsi0, channel 0, id 2, lun 0
    scsi : detected 1 SCSI cdrom 1 SCSI disk total.
    sr0: scsi3-mmc drive: 12x/12x xa/form2 cdda tray
    Uniform CDROM driver Revision: 2.55
    SCSI device sda: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]

<-- 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
    ne2k-pci.c: PCI NE2000 clone ‘RealTek RTL-8029’ at I/O 0x8000, IRQ 25.
    eth0: PCI NE2000 found at 0x8000, IRQ 25, 00:A0:4B:06:00:B6.
    ne2k-pci.c: PCI NE2000 clone ‘RealTek RTL-8029’ at I/O 0x8800, IRQ 27.
    eth1: PCI NE2000 found at 0x8800, IRQ 27, 00:A0:4B:06:28:2F.
    eth2: 3c509 at 0x300 tag 1, 10baseT port, address  00 60 97 ae b7 47, IRQ 11.
    3c509.c:1.16 (2.2) 2/3/98
becker@cesdis.gsfc.nasa.gov.
    eth2: Setting Rx mode to 1 addresses.

<--ne2000호환 pci랜카드 두 개를 커널(Kernel)에서 찾아서 실행시킨 메시지 입니다. 또한, 3Com509 랜카드를 찾아서 eth2에 설정한 메시지입니다.

■ Partition check:
    sda: sda1 sda2 sda3 < sda5 sda6 > sda4
    VFS: Mounted root (ext2 filesystem) readonly.

<--현재 리눅스 박스의 파티션 정보가 출력됩니다. 이 중에 <sda5 sda6>의 메시지는 논리 파티션을 나타냅니다. 또한, 루트 파티션이 읽기가능으로 마운트 되었음을 나타냅니다.

■ Freeing unused kernel memory: 48k freed
    Adding Swap: 257000k swap-space (priority -1)

<--파티션의 스왑영역을 메모리에 추가하여 활성화 시키는 메시지입니다.

 

그밖의 메시지

■ Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996
    SB 4.13 detected OK (220)
    <SoundBlaster EMU8000 (RAM0k)>

<-- 사운드 카드가 있을 경우에는 사운드 설정에 관해서 메시지가 출력됩니다.

■ Checking 386/387 coupling... OK, FPU using exception 16 error reporting.
    Checking ‘hlt’ instruction... OK.
    Intel Pentium with F0 0F bug - workaround enabled.

<-- 첫번째 메시지는 386에서 보조 수치연산 장치가 달려 있지 않을 경우에 체크하는 메시지로, 보조 수치연산 장치가 내장되어 있음을 확인하는 메시지입니다. 두 번째 메시지는 시스템에 hlt 명령어를 보내서 시스템을 일단 정지시켜 보는 메시지입니다. 일단은 시스템의 안정성을 확인하기 위해서 프로세서 명령어인 hlt를 보내서 시스템을 정지시키고, 정상적인 종료가 되는 가를 확인합니다. 세 번째 메시지는 펜티엄 버그를 수정하고 보완해 줄 수 있는 소프트웨어적인 장치인 워크어라운드를 실행하는 메시지입니다.

이와 같은 커널 메시지는 dmesg 명령어를 사용하여 다시 출력해 볼 수가 있습니다. 또한, 부팅한 후에 일정량의 버퍼에 들어 있는 메시지를 Shift키와 PageUP, DOWN키를 사용하여 최근 메시지를 볼 수 있습니다.  

※ 참고
부팅할 때 실행되는 /etc/rc.d/rc.sysinit의 맨 아래 보면 아래와 같은 메시지를 볼 수가 있습니다.
즉, dmesg명령어로 부팅된 후의 모든 부팅 메시지를 /var/log/dmesg에 저장하도록 되어 있습니다.
# Now that we have all of our basic modules loaded and the kernel going,
# let’s dump the syslog ring somewhere so we can find it later dmesg > /var/log/dmesg

 

4. Sysvinit 실행

커널(Kernel)이 실행되어서 운영체제가 하드웨어의 모든 기능을 제어하게 되었을 때 Sysvinit프로그램이 실행되게 됩니다. init프로그램에는 유닉스계열처럼 System V계열과 BSD계열이 있습니다. 리눅스에서는 System V init프로세서를 사용하고 있습니다.

init는 커널(Kernel)에 의해 생성되는 첫 번째 프로세서로서, initialize의 약자입니다. 즉, 초기화를 한다는 것이죠, 약간의 유닉스 지식을 가지고 계신 분이라면, 부모프로세서와 자식프로세서라는 말을 들어 보셨을 것입니다. 유닉스의 경우에는 하나의 프로그램이 실행되어서 계속적으로 인간의 자손이 아기를 낳듯이 프로세서를 낳고 낳고 하면서 이어지는 것입니다.

최초의 시작되는 프로그램을 통해서 모든 프로그램의 실행이 제어되고, 통제되어지는 것입니다. 이 같은 원리로 상위의 프로세서를 제거하면(유닉스에서는 kill라는 명령어를 사용합니다.) 아래의 하위 프로세서는 죽거나, 영혼(좀비 프로세서라고들 하지요)처럼 컴퓨터의 세계를 떠돌아 다니게 됩니다. 이런 운영방식은 거의 모든 운영체제에서 동일합니다.

사실 프로세서에서 엄격하게 말하면 처음으로 실행되어지는 것은 커널의 Scheduler라는 프로세서입니다. 이것은 실행을 위한 프로세서의 일정을 정하고, 실행할 순서, 시간, 길이를 결정하는 작용을 합니다. 한마디로 fork()와 exe()를 이용해서 프로세서를 만드는 것입니다. 이 프로세서는 커널에서 작동을 하기 때문에 ps나 pstree에서도 볼 수가 없습니다.

※ 참고

fork
새로운 프로세서를 생성하는 것을 말합니다. 즉, 부모프로세서에서 자식프로세서를 만든 것을 말합니다. 유닉스 프로그램밍을 작성하려면, 반드시 이 개념에 대해서 잘 아셔야 합니다.

exec
사용했던 프로세서와 같은 프로세서 아이디(PID)를 사용하여서 프로세서를 시작하는 것을 말합니다. 아주 새로운 프로세서를 시작해서 프로세서 오버헤드를 올리는 것보다 효과적인 방법입니다.

init프로세서가 시작이 되면, 그 아래로 fork와 exec를 이용해서 시스템의 기본적인 atd, crond, inted, gpm, httpd, innd, klogd, lpd등의 데몬들이 실행됩니다. init는 제일 먼저 실행되기 때문에 항상 프로세서 아이디(PID)는 1이고, 리눅스 박스가 shutdown될 때에도 제일 마지막으로 프로세서과정에서 종료됩니다.  

리눅스 박스의 프로세서가 어떻게 되어 있는가는 [그림 5]와 같이 ps와 pstree를 이용하여 프로세서 아이디와 그 구조에 대해서 시각적으로 알 수가 있습니다.

[그림 5] init프로세서의 프로세서 위치

위의 [그림 5]를 보면, 흥미로운 것들을 볼 수가 있습니다.
httpd-10*[httpd]
웹서버 데몬을 fork와 exec를 이용해서 10개를 작동시키고 있을 알 수가 있습니다.

inetd-in.telnetd-login-bash--pstree
pstree를 실행시키기 위해서 inetd데몬이 실행시킨 in.telnetd데몬에 의해서 원격으로 접속한 터미널에서 login를 수행하여 접속한 사용자가 bash쉘을 통해서 pstree를 사용하고 있는 것을 볼 수가 있습니다.
6*mingetty
6개의 mingetty가 실행되어서 가상 콘솔이 6개가 작동중인 것을 알 수가 있습니다.

이 외에도 프린터사용을 위한 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의 부팅 과정은 아래와 같이 다릅니다.
BSD                                        System V
swapper        - 프로세서 0         sched         - 프로세서 0
init                - 프로세서 1         init             - 프로세서 1
pagedaemon - 프로세서 2

 

5. 리눅스 박스의 자세한 Sysvinit 작동 과정

System V 실제적인 이해는 Run-level에 대한 이해를 해야만 합니다. 유닉스계열인 리눅스박스에서는 Run-level이라는 독특한 방법을 사용하여 여러가지 시작 방법을 가지고 있으며, 종료도 Run-level을 통해서 실행이 되어집니다. Run-level은 각 배포판마다 다르지만, 일정한 형식을 따르고 있으므로 약간의 지식만 가진다면, 이해하기 쉽습니다. init작용을 이해해 보기로 하겠습니다.
우선적으로 init는 LILO가 /etc/lilo.conf를 읽듯이 /etc/inittab를 읽습니다. 이 파일에는 리눅스 박스가 어떤 일부터 해야할지를 상세하게 기술해 놓은 것입니다. 이 파일이 하드디스크에 없을 때는 리눅스 박스는 단일 사용자(single user)모드로 부팅을 합니다. 여기서 initdefault를 읽어서 시스템의 run-level를 결정합니다.

레드헷 리눅스의 /etc/inittab파일입니다. 한번 살펴보기로 하겠습니다.

id:3:initdefault:
<-- 이 설정은 기본 run-level이 3임을 나타내 주고 있습니다.

si::sysinit:/etc/rc.d/rc.sysinit
<-- 시스템의 초기 시작 스크립터를 지정해 주고 있습니다.

l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
<-- 각 run-levle에 대해서 나타내 주고 있습니다.

ud::once:/sbin/update
<-- 시스템 충돌을 보증하는 sync 명령어의 실행에 의해 모든 파일 시스템의 슈퍼블럭들을 정기적으로 갱신하는 프로세서입니다. 이 데몬은 일반적으로 bdflush라고 불려집니다. 리눅스에서는 update와 bdflush라고 불려집니다. 이 데몬은 파일 시스템 무결성을 보장합니다.

ca::ctrlaltdel:/sbin/shutdown -t3 -r now
<-- ctrl+alt+delete키를 누르면 shutdown 시킬 수 있는 설정입니다. 이것은 주석처리하면 키가 먹지 않습니다.

pf::powerfail:/sbin/shutdown -f -h +2 “Power Failure; System Shutting Down”
<-- 리눅스 박스에 UPS가 설치되었을 경우에 전원불량 시그널이 수신되면 바로 shutdown 시키는 설정입니다.

pr:12345:powerokwait:/sbin/shutdown -c “Power Restored; Shutdown Cancelled”
<-- 만약 지정된 시간에 전원이 정상으로 돌아오면 shutdown명령를 취소하는 설정입니다.

1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
<-- run-level당 표준적으로 실행되는 가상콘솔의 정의입니다. 6개를 정의했군요

x:5:respawn:/etc/X11/prefdm -nodaemon
<-- run-level이 5인경우에 xdm을 실행하여 엑스윈도우 부팅을 가능하게 하는 설정입니다.

id:runlevels:action:process
보통 inittab파일의 기술 방식은 위와 같습니다. id는 보통 레이블입니다. 여러분이 쓰고 싶은데로 1-4글자와 숫자로 사용이 가능합니다. runlevels는 말 그대로 run-level입니다. 이 명령이 어느 run-level에서 작동하기 원하는지 run-level번호를 쓰면 됩니다. 위의 예제에서처럼 복수로, 2345라고 쓰셔도 되고 3이라고 하나면 쓰셔도 됩니다. action은 init프로세서에 있는 명령어입니다. process는 여러분이 실행시키고 싶은 명령어를 기술하시면 됩니다. 자세하게 알아야 할 것은 action부분입니다.

action은 아래와 같은 명령어를 사용할 수 있습니다.
respawn : 프로세서가 종료되면 항상 다시 시작하게 하는 명령어입니다.
wait : 지정된 run-level에서 실행이 되고, init는 이 프로세서가 종료되기를 기다립니다.
once : 지정된 프로세서가 한번만 명령어를 실행합니다.
boot : 시스템 부팅 때에 그 프로세스를 실행한다. 이때는 runl-evel 값이 무시됩니다.
bootwait : boot과 once의 기능을 합친 것입니다.
initdefault : 시스템의 기본 run-level을 지정합니다.
sysinit : 제일 먼저 실행이 됩니다.
process : 필드는 보통 생략됩니다.
powerwait : 전원에 문제가 생겼을 때 실행합니다. 프로세서 작업이 끝날 때까지 기다립니다.
powerfail : 위와 같으나, 프로세서 작업을 종료를 기다리지 않습니다.
ctrlaltdel : ctrl, alt, del키를 동시에 누르면 작동합니다.
kbrequest : 특정한 키를 입력 받을 때 실행합니다.

※ 참고
아직 하드 디스크를 정식으로 마운트하지 않았는데도하드 디스크를 읽을 수 있지요? 이 이유는 처음에 커널도 시작될 때부터, 하드 디스크를 읽기 모드로 설정하여 (read-only) 마운트하여 읽기 때문입니다.

init가 시작되는 시점은 커널의 하드웨어 찾기와 설정이 끝난 시점부터 시작이 됩니다. 아래의 메시지는 레드헷 6.0기준으로 구성한 메시지입니다. 다른 배포판들에서 약간의 차이가 있습니다.

INIT : version 2.74 booting           -----------------1
Loading default keymap   [OK]     -----------------2
Setting default font          [OK]
Activating swap partitions [OK]     -----------------3
Setting hostname enveng.chungbuk.ac.kr   [OK]   ------4
Checking root filesystem              -----------------5
/dev/hda1 : clean, 84695/514000 files, 1517933/2048001 blocks
Mounting local filesystems            -----------------6
Turning on user and group quotas for local filesystems                  
Setting clock : Wed Jun 21 20:52:32 KST 1999    -------7
Enabling swap space            ----------------8
INIT : Entering run-level : 3      ----------------9

1번의 메시지는 INIT가 시작되면서 2.74버전의 SYSVINIT프로그램이 실행이 됩니다.
/etc/inittab의 아래 메시지를 읽어서 /etc/rc.d/rc.sysint 스크립트를 실행합니다.
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit

2번 메시지는 기본적인 키보드와 폰트가 설정되어 작동이 가능하게 됩니다.
 /etc/rc.d/rc.sysinit 파일의  아래 메시지를 읽어서 실행을 하게 됩니다.
# Load keymap (kbd를 이용해서 키보드 설정)
 if [ -n “$KEYTABLE” -a -d “/usr/lib/kbd/keymaps” ]; then
 echo -n “Loading default keymap”
 success “Loading default keymap” || failure “Loading default keymap”
# Load system font(setsysfont를 이용해서 기본 폰트 설정)
if [ -x /sbin/setsysfont ]; then
action “Setting default font” /sbin/setsysfont

3번 메시지는 하드 디스크의 스왑파티션이 사용가능 하도록 활성화 시킵니다.
/etc/rc.d/rc.sysinit 파일의 아래 메시지를 읽어서 실행을 하게 됩니다.
# Start up swapping.
action “Activating swap partitions” swapon -a

4번 메시지는 /etc/sysconfig/network파일을 읽어서 hostname을 설정합니다.
# Read in config data.
if [ -f /etc/sysconfig/network ]; then . /etc/sysconfig/network else
    NETWORKING=no
    HOSTNAME=localhost
fi
# Set the hostname.
action “Setting hostname ${HOSTNAME}” hostname ${HOSTNAME}

5번 메시지는 파일 시스템을 검사하고, 마운트를 하는 과정입니다.
# Check filesystems
if [ ! -f /fastboot ]; then
        STRING=”Checking filesystems”
        echo $STRING
        initlog -c “fsck  -T -R -A -a $fsckoptions”
        rc=$?
        if [ “$rc” = “0” ]; then
                success “$STRING”
                echo
        elif [ “$rc” = “1” ]; then
                passed “$STRING”
echo
fi

# A return of 2 or higher means there were serious problems.
if [ $rc -gt 1 ]; then
                failure “$STRING”
                echo
                echo
                echo “*** An error occurred during the file system check.”
                echo “*** Dropping you to a shell; the system will reboot”
                echo “*** when you leave the shell.”

PS1=”(Repair filesystem) #”; export PS1
                sulogin
                echo “Unmounting file systems”
                umount -a
                mount -n -o remount,ro /
                echo “Automatic reboot in progress.”
                reboot
elif [ “$rc” = “1” -a -x /sbin/quotacheck ]; then
action “Checking filesystem quotas” /sbin/quotacheck -v -R -a
fi
fi

6번 메시지는 마운트를 하고 나서 쿼터를 실행시키는 것입니다.
# Mount all other filesystems (except for NFS and /proc, which is already
# mounted). Contrary to standard usage,
# filesystems are NOT unmounted in single user mode.
action “Mounting local filesystems” mount -a -t nonfs,smbfs,ncpfs,proc

if [ -x /sbin/quotaon ]; then
action “Turning on user and group quotas for local filesystems” /sbin/quotao  n -a
fi

7번 메시지는 시간 설정을 하는 것입니다.
# Set the system clock.
ARC=0
UTC=0
if [ -f /etc/sysconfig/clock ]; then  . /etc/sysconfig/clock

 # convert old style clock config to new values
 if [ “${CLOCKMODE}” = “GMT” ]; then
 UTC=true
 elif [ “${CLOCKMODE}” = “ARC” ]; then
 ARC=true
 fi
 fi

CLOCKDEF=””
if [ -x /sbin/hwclock ]; then
    CLOCKFLAGS=”--hctosys”
    CLOCK=/sbin/hwclock
    $CLOCK --adjust
else
    CLOCKFLAGS=”-a”
    CLOCK=/sbin/clock
fi

case “$UTC” in
  yes|true)
    CLOCKFLAGS=”$CLOCKFLAGS -u”;
    CLOCKDEF=”$CLOCKDEF (utc)”;
  ;;
esac
if [ “$CLOCK” = “/sbin/clock” ]; then
 case “$ARC” in
   yes|true)
     CLOCKFLAGS=”$CLOCKFLAGS -A”;
     CLOCKDEF=”$CLOCKDEF (arc)”;
   ;;
 esac
fi
$CLOCK $CLOCKFLAGS
action “Setting clock $CLOCKDEF: `date`” date

8번 메시지는 스왑 공간을 실행시키는 메시지입니다.
# Right, now turn on swap in case we swap to files.
swapon -a >/dev/null 2>&1
action “Enabling swap space” /bin/true
9번 메시지는 /etc/inittab의 id:3:initdefault의 부분을 읽고 나서 run-level 3로 부팅을 시키는 메시지입니다.

[그림 6] init의 부팅과정

리눅스 배포판 중 레드헷/칼데라, 데비안, S.u.S.E는 서로 다른 INIT구조로 엮어져 있습니다. 서로 다른 사람들이 만들다 보니 같은 프로그램과 같은 리눅스를 만들어도 아래 그림과 같이 서로 다른 INIT구조를 나타냅니다. 하지만, 기본적인 작동방식은 동일합니다.

[그림 7] 배포판의 INIT파일 구조

레드헷/칼데라 리눅스에서는 run-level이 아래와 같습니다.
Run-level 0 - halt   (시스템의 종료와 같습니다.)
Run-level 1 - single user   (네트워크가 작동하지 않습니다.)
Run-level 2 - multi-user without NFS   (NFS와 다수의 데몬이 작동이 안됩니다.)
Run-level 3 - muti-user with NFS   (가장 일반적인 작동 모드입니다.)
Run-level 4 - not used   (사용자가 정의해서 사용이 가능합니다.)
Run-level 5 - X11   (xdm을 이용해서 엑스윈도우로 부팅)
Run-level 6 - reboot   (리부팅모드입니다.)

데비안 리눅스에서는 run-level이 아래와 같습니다.
Run-level 0 - halt   (시스템의 종료와 같습니다.)
Run-level 1 - single user   (네트워크가 작동하지 않습니다.)
Run-level 2, 3, 4, 5 - muti-user (보통은 2로 작동하지만, 모두 다 사용자 정의로 설정이 가능합니다.)
Run-level 6 - reboot   (리부팅모드입니다.)

S.u.S.E 리눅스에서는 run-level이 아래와 같습니다.
Run-level 0 - halt   (시스템의 종료와 같습니다.)
Run-level 1 - single user   (네트워크가 작동하지 않습니다.)
Run-level 2 - multi-user without network    (네트워크 없이 다중 사용모드입니다.)
Run-level 3 - muti-user with network   (가장 일반적인 작동 모드입니다.)
Run-level 4 - not used   (사용자가 정의해서 사용이 가능합니다.)
Run-level 5 - muti-user with network and xdm   (xdm을 이용해서 엑스윈도우로 부팅)
Run-level 6 - reboot   (리부팅모드입니다.)

유닉스에서는 실행시키고자 하는 프로그램(데몬)을 작동시키는 스크립트들을 한 곳에 모여두고 run-level에 따라서 rc0.d, rc1.d, rc2.d, rc3.d, rc4.d, rc5.d, rc6.d에 링크를 해 놓습니다. 이럴 때, 아주 간단한 법칙이 하나 있습니다.  S로 링크를 시작하는 것은 시작을 의미하는 것이고, K로 시작하여 링크해 높은 것은 종료를 의미하는 링크입니다. 그 다음에 숫자는 우선순위를 나타내는 것입니다. 위의 이런 법칙은 스크립트에 의해서 작동이 제어됩니다.
레드헷/칼데라에서는 /etc/rc.d/init.d/functions에서 찾을 수 있고, 데비안은 /etc/init.d/rc와 /etc/init.d/rcS에서 찾을 수 있습니다. S.u.S.E에서는 /etc/rc.d/rc에서 찾아 볼 수가 있습니다. (만약에 이러한 자동을 바꾸고 싶다면....)

※ 참고
S와 K를 사용한다고 해서 실행과 종료를 결정짓는 것은 모든 데몬의 실행 스크립터에는 start와 stop의 파라미터가 아래처럼 있기 때문에 S로 링크 되어 있으면, [scripts name] start파라미터를 K로 링크 되어 있으면, [scripts name] stop파라미터를 작동시키는 것입니다.

#See how we were called.
case “$1” in
  start)
        echo -n “Starting httpd: “
        daemon httpd
        echo
        touch /var/lock/subsys/httpd
        ;;
  stop)
        echo -n “Shutting down http: “
        killproc httpd
        echo
        rm -f /var/lock/subsys/httpd
        rm -f /var/run/httpd.pid
        ;;

[그림 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에 따라서 스크립트 링크하기(레드헷 리눅스 기준)

※ 참고
종종 레드헷 리눅스에서 아래의 issue메시지 때문에 /etc/rc.d/rc.local파일을 vi에디터로 열고 일일히 주석을 달아 주시는 분들을 많이 봤습니다. /etc/rc.d/rc.local파일은 레드헷 리눅스의 /etc/rc.d/rc2.d/S99local, /etc/rc.d/rc3.d/S99local, /etc/rc.d/rc5.d/S99local에 각각 링크가 되어 있습니다. 이 링크를 지우시면 작동하지 않습니다.

Red Hat Linux release 6.0 (Hedwig)
Kernel 2.2.5-22 on an i686

레드헷에서는 /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의 부팅과정

※ 참고
리눅스 레드헷 6.0을 접하게된 사용자들은 데몬이 뜰 때 [OK]라는 컬러풀한 메시지를 보게 되고 매우 인상적으로 생각되는 분들이 많을 것입니다.  
이 메시지는 /etc/rc.d/init.d/functions에 의해서 /etc/sysconfig/init에 있는 스크립트로 실행이 됩니다. 다른 메시지로 바꾸시고 싶으신 분들은 여기에서 바꾸어 보시는 것도 좋을 것입니다.

S.u.S.E에서는 done이라는 메시지를 컬러풀한 메시지로 역시 볼 수 있을 것입니다. 이 설정은 /etc/rc.config에 있습니다.
이제 이야기를 정리해 보면서 리눅스 박스의 부팅은 아래의 [그림 12]과 같은 과정을 거치게 됩니다.

[그림 12] 리눅스 박스의 부팅

전원을 켜면, 바이오스가 작동이 되고, root파티션의 MBR에 있는 LILO를 읽게 됩니다. LILO는 /etc/lilo.conf파일을 참조하여서 커널의 위치를 파악하고 읽습니다. 메모리에 적재한 커널을 일단, LILO는 압축을 풀고, 실행을 합니다. 이 때, 커널은 하드웨어의 디바이스를 찾고, 설정을 수행합니다. 그리고 난 다음, 커널의 sched로 시작된 INIT프로세서가 /etc/inittab을 참조하여 초기화 작업과 run-level을 결정합니다. 그 후에는 mingetty가 가상 콘솔을 열고, 사용자가 로긴하기 위해서는 login프로그램이 작동하여 인증을 거치면, 쉘이 작동하게 됩니다. 이 모든 과정을 부족하나마, 이해하셨길 바라며, 리눅스 박스의 부팅과정 이해에 도움이 되길 바랍니다.

※ 참고
여러분이 리눅스 박스를 리부팅 한다면, 아래와 같은 메시지를 접하시게 될 것입니다.
INIT : Switching to runleve : 6
INIT : Sending processes the TERM signal

리부팅도 단지 run-level이 6으로 바뀌는 과정에 불과합니다. 이 모든 작용은 /etc/rc.d/rc6.d의 내용을 그대로 반영하게 됩니다.
시스템 작동중에 run-level을 바꾸려면 telinit명령어를 쓰면 됩니다.

다음 번에는 스크립트들에 대한 이야기를 해보도록 하겠습니다.  부팅과정에 나타나는 스크립트들은 어떻게 작성하는 것이며, 어떻게 동작하는 것에 대한 내용을 다루어 보도록 하겠습니다.


관련자료

댓글 0
등록된 댓글이 없습니다.

공지사항


뉴스광장


  • 현재 회원수 :  60,045 명
  • 현재 강좌수 :  35,861 개
  • 현재 접속자 :  76 명