리눅스 시작 프로세스

리눅스 시작 프로세스는 리눅스 부팅 시에 수행되는 다단계 초기화 과정이다. 이것은 리눅스가 파생된 BSD 및 다른 유닉스 계열 부팅 프로세스와 비슷하다.
리눅스를 부팅하는 것은 펌웨어 초기화, 부트 로더의 실행, 리눅스 커널 이미지의 로딩과 시작 그리고 다양한 시작 스크립트들과 데몬들의 실행을 포함하는 여러 단계와 여러 소프트웨어 구성 요소들과 관련된다. 이 단계들 각각에서는 다른 방식과 접근법이 존재한다; 예를 들면 GRUB, LILO, SYSLINUX 또는 Loadlin는 부트 로더로서 사용될 수 있지만, 시작 스크립트들도 전통적인 init 스타일 또는 (systemd나 Upstart 같은 현대의 대체재들을 통해 수행될 수 있는) 시스템 설정으로도 가능하다.
개요.
리눅스 시작 프로세스의 초기 단계들은 컴퓨터 구조에 매우 의존적이다. IBM PC 호환의 하드웨어가 리눅스가 일반적으로 사용되는 가장 흔한 구조이다; 이러한 시스템들에서 바이오스가 중요한 역할을 하는데, 다른 시스템들에서도 똑같은 방식이 사용되는 것은 아니다. 다음의 예시에서 IBM PC 호환 하드웨어는:
종료 시에, 모든 init은 모든 사용자 공간 기능을 종료하기 위해 호출된다. init은 그 후 종료되며 커널은 자신의 종료를 수행한다.
부트 로더 단계.
부트 로더 단계는 컴퓨터 구조에 따라 다르다. 초기 단계들은 운영 체제에 관련 없었기 때문에, 바이오스 기반 부트 과정은 마스터 부트 레코드 코드가 리얼 모드에서 실행되고 첫 번째 단계 부트 로더가 로드되었을 때 실행될 것이라고 여겨진다. UEFI 시스템에서 리눅스 커널 같은 페이로드는 직접적으로 실행된다. 그래서 부트 로더가 필요치 않다. 아래는 몇몇 유명한 부트 로더들에 대한 개략적인 설명이다.
커널 국면.
리눅스에서 커널은 메모리 관리, 태스크 스케줄링, 입출력, 프로세스 간 통신 그리고 전체적인 시스템 제어 같은 모든 운영 체제 프로세스들을 다룬다. 이것은 두 단계로 로드되는데 첫 단계에서 커널은 (압축된 이미지 파일로서) 메모리에 로드되며 압축 해제되고 몇몇의 중요한 함수들이 설치된다. 제어는 이후 주요 커널 시작 프로세스로 넘어간다. 커널이 완전하게 동작 가능해지면 커널은 실행 시킬 init 프로세스(각각 요구되는 사용자 환경과 로그인을 위한 사용자 공간과 프로세스들을 설치하는)를 찾는다. 커널 자체는 이후 idle 상태로 가며 다른 프로세스의 호출을 기다린다.
커널 로딩 단계.
로드된 커널은 일반적으로 이미지 파일이며 zImage 또는 bzImage 포맷으로 압축되어 있다. 헤드 부분의 루틴은 최소한의 하드웨어 설치, 이미지를 완전하게 메모리로 압축 해제 그리고 설정된 경우 램 디스크를 알아 놓는다. 그 후 codice_3 와 codice_4 (x86 기반 프로세서의 경우) 프로세스를 통해 커널 스타트업을 시작한다.
커널 스타트업 단계.
커널에서의 스타트업 함수는 메모리 관리(페이징 테이블과 메모리 페이징)를 수립하고, CPU의 종류와 부동소수점 가용성 같은 추가적인 기능을 탐지하며 이후 codice_1를 호출함으로써 아키텍처에 명시적이지 않은 리눅스 커널 기능으로 전환된다.
start_kernel은 넓은 범위의 초기화 함수들을 실행한다. 이것은 인터럽트 핸들링(IRQs)을 설치하고, 나아가 메모리를 설정하며, Init 프로세스(첫번째 사용자 영역 프로세스)를 시작한다. 이후 codice_6를 통해 유휴 태스크를 시작한다. 특히 커널 스타트업 프로세스는 또한 부트 단계에서 임시 루트 파일 시스템으로써 이전에 로드된 초기 램 디스크("initrd")를 마운트한다. initrd는 드라이버 모듈들이 다른 장치들(예를 들면 하드 디스크) 그리고 드라이버들과의 의존성 없이 메모리에서 직접적으로 로드되게 한다. 이 몇몇 드라이버들의 분리는 통계적으로 커널과 initrd에서 로드된 다른 드라이버들로 컴파일된다. 루트 파일 시스템은 이후 임시 루트 파일 시스템을 언마운트하고 이것을 실제의 것으로 대체하는 codice_7 에 대한 호출을 통해서 전환된다. 임시 루트 파일 시스템에 의해서 사용되는 메모리는 그 때 되찾아 진다.
커널은 장치들을 초기화하고 부트 로더에 의해서 읽기 전용으로 명시된 루트 파일 시스템을 마운트하며, 시스템에 의해 실행되는 첫 번째 프로세스로 디자인된 Init (codice_8)을 실행한다(PID=1). 파일 시스템을 마운팅하는 과정 중에서 커널에 의해서 그리고 Init 과정 중 Init에 의해 메시지가 보여진다. 또한 옵션으로 Initrd를 실행해서 설치와 장치 관련 사항들이 루트 파일 시스템이 마운트되기 전에 처리될 수 있게 한다.
레드햇에 따르면, 이 단계에서 자세한 커널 과정은 다음과 같이 요약될 수 있다:
이 지점에서 인터럽트가 활성화되며 스케줄러는 선점적인 멀티 태스킹을 제공하기 위해서 시스템의 전체적인 관리의 제어를 가지며, init 프로세스는 사용자 공간에서 사용자 환경을 계속 부팅하기 위해 남아 있는다.
초기 사용자 공간.
initramfs, 또한 "초기 사용자 공간"으로도 불리는 이것은 리눅스 커널 버전 2.5.46 이후로 사용 가능하며, 스타트업 과정 동안 커널이 수행되기 이전에 가능한 많은 함수들을 대체하기 위한 목적으로 사용된다. 초기 사용자 공간의 일반적인 사용은 주요 사용자 공간 파일 시스템을 로드하기 위해 어떤 장치 드라이버들이 필요한지를 탐지하고 임시 파일 시스템에서 이것들을 로드하는 것이다.
Init 프로세스.
SysV init.
Init이 하는 일은 커널이 완전히 실행되기 시작할 때 "그렇게 되어야 하는 모든 것을 얻는" 것이다. 근본적으로 이것은 전체 사용자 공간을 수립하고 가동한다. 이것은 파일 시스템을 검사하고 마운트하며 필요한 사용자 서비스를 시작하고 궁극적으로 시스템 스타트업이 완료될 때 사용자 환경으로 전환하는 것을 포함한다. 이것은 유닉스와 BSD의 init 과정들과 비슷하지만 몇몇 차이점이 존재한다. 표준 리눅스 시스템에서 Init은 런레벨로 알려진(0부터 6의 값을 갖는) 파라미터와 함께 실행되며 어떤 서브시스템이 동작할 지를 결정한다. 각 런레벨은 자신만의 스크립트를 가지며 주어진 런레벨에서 해야할  일이 적어져 있다. Init 스크립트들은 일반적으로  codice_9codice_10와 같은 이름을 갖는 디렉토리에 존재한다. init의 상위 수준 설정 파일은 codice_11에 존재한다.
시스템 부트 동안 디폴트 런레벨이 /etc/inittab에 명시되어 있는지를 검사하고 존재하지 않는다면 시스템 콘솔을 통해서 런레벨을 요청한다. 이후 주어진 런레벨 하에서 관련된 부트 스크립트들을 진행하고(모듈들의 로딩, 루트 파일 시스템의 무결성 검사 등) 완전 읽기-쓰기 접근으로 리마운팅하며 네트워크를 설정한다.
명시된 모든 과정들이 진행된 후에, init은 휴면 상태에 진입하고 세 이벤트 중 하나가 일어나기를 기다린다: 종료를 위한 과정의 시작, 정전 신호, 런레벨을 바꾸기 위한 codice_12을 통한 요청.
이것은 SysV-스타일 init에서 적용된다.
systemd.
Systemd의 개발자들은 유닉스 시스템 V와 BSD 운영 체제에서 나온 리눅스 init 시스템을 대체하려는 것에 초점을 두었다. init과 비슷하게 systemd는 다른 데몬들을 관리하는 데몬이다. Systemd를 포함한 모든 데몬들은 백그라운드 프로세스들이다. Systemd는 부팅 시에 시작되는 첫번째 데몬이며 셧다운 시에 종료되는 마지막 데몬이다.
Systemd를 초기에 개발한 소프트웨어 엔지니어들은 여러 방식들에서 init 데몬의 효율성을 능가하려고 했다. 이들은 시스템 부팅 동안에 과정들이 더 동시에 또는 병렬로 진행되게 해서 소프트웨어 프레임워크를 향상시키고 셸의 오버헤드를 감소시키려고 했다.
각 데몬들을 위한 systemd의 초기화 명령어들은 셸 스크립트가 아닌 설정 파일에 저장된다. 프로세스 간 통신을 위해서, systemd는 유닉스 도메인 소켓과 D-Bus를 동작하는 데몬들에게 사용 가능케 했다. Systemd는 또한 적극적인 병렬화가 가능하다.
Upstart.
전통적인 init 과정은 근본적으로 단지 전력이 공급된 이후에 컴퓨터를 정상적인 실행 상태로 되돌리고 셧다운 이전에 서비스들을 정상적으로 종료시키는 것을 다룬다. 결과적으로 설계는 엄격하게 동기적이며 현재 작업이 완료되기 전까지는 추후의 작업을 막는다. 이 작업들은 반드시 이전에 정의되어야 한다. 이것은 현대의 데스크탑 컴퓨터에서 다양한 비 스타트업 작업들을 다루지 못하게 한다.
Upstart는 비동기적으로 동작한다; 이것은 부팅 시에 작업들과 서비스들의 시작 그리고 종료 시에 이것들의 정지를 다루며 또한 시스템이 돌아가는 동안 이 작업들을 감시한다.
Sysvinit을 통한 쉬운 이행과 완벽한 하위 호환성이 명백한 설계의 목표이다; 그에 따라 Upstart는 수정되지 않은 sysvinit을 실행할 수 있다. 이 방식으로 이것은 적절한 실행을 위해 일반적으로 완전한 이행을 가정하고 요구하는 그리고 과거와 현재의 스타트업 방식들이 혼합된 환경을 지원하지 않는 대부분의 다른 init 대체재들과는 다르다.
Upstart는 확장으로 inictl, 싱글 이벤트 또는 이벤트 브릿지(많은 복잡한 이벤트들을 통합하기 위한)들의 사용을 통해 자신의 이벤트 모델을 가능케 한다. 디폴트로 Upstart는 소켓, dbus, udev, file 그리고 dconf 이벤트들의 브릿지들을 포함한다.
runit.
Runit은 유닉스 계열 운영 체제들을 위한 init 구조로서 운영 체제를 통해 초기화, 감독 그리고 프로세스들의 종료를 담당한다. 이것은 리눅스, 맥, BSD 등에서 돌아가는 "seminal" 데몬툴즈 프로세스 감독 툴킷의 "재구현"이다. Runit은 운영 체제의 부트 시간을 줄여줄 수 있는 시스템 서비스의 스타트업의 병렬성을 특징으로 갖는다.
Runit은 init 데몬으로서 모든 다른 프로세스들의 직접적인 또는 간접적인 조상이다. 이것은 부팅 시에 시작되는 첫 번째 프로세스이며 시스템이 종료되기 전까지 실행된다.