앞 절에서 설명한 바와 같이 init 프로세스가 자신에게 할당된 초기화 과정을 모두 끝마치고 나면, inittab 파일의 맨 끝부분에 명시된 것처럼 mingetty 혹은 getty 프로세스를 실행시킵니다. 실행시키는 방법은 최초에 pid 0 의 프로세스 [1] 에 의해 실행된 init 가 fork() 시스템 콜을 한번 수행하고, 그에 의해 생성된 자식 init 가 exec() 시스템 콜을 이용해서 getty 혹은 mingetty 등의 프로세스를 수행하게 됩니다.
프롬프트를 띄우고서 사용자의 userid 가 입력되기를 기다리는 일입니다. 사용자가 자신의 userid 를 입력하고서 엔터키를 치게 되면, getty 는 /bin/login 을 실행시키게 됩니다.
login :
라는 프롬프트를 띄우고, 사용자가 password 를 입력하기를 기다립니다. 사용자가 암호를 입력하면, /etc/passwd 혹은 /etc/shadow 파일로부터 패스워드를 읽어서 암호화 한 패스워드와 일치하는지를 검사합니다. 만약 패스워드가 일치하지 않으면, login 프로그램은 에러를 내고 종료합니다. 그러면, init 프로세스는 다시 자신을 fork() 하고, /sbin/getty 프로그램을 exec() 해서 화면에 로그인 프롬프트를 출력하도록 하고 사용자의 입력을 기다리게 됩니다. 만약 패스워드가 일치하면, login 프로그램은 홈디렉토리를 바꾸는 등 여러가지 작업을 하고, 최종적으로 exec()를 하여, 로그인 쉘 [2] 을 띄우게 됩니다.
Password:
그러면, 사용자는 자신의 쉘 (주로 bash) 로 작업을 하고, 쉘에서 입력하는 명령어들은 먼저 쉘이 fork() 를 한 후 쉘의 자식프로세스가 exec() 를 하여 실행되고, 종료하는 것입니다. 이 과정을 간단하게 그림으로 그리면 다음과 같습니다.
+-------------+ | init | | (pid 1) | +------+------+ | <-------------------------------------+ | fork() | respawn \|/ | +------+------+ | | "자식" init | | | (pid 266) | | +------+------+ | | | | exec() | \|/ | +------+------+ | | mingetty | | | (pid 266) | | +------+------+ | | | | exec() | \|/ | +------+------+ | | login | | | (pid 266) | | +------+------+ | | | | exec() | \|/ | +------+------+ | | bash +---------------------------- 쉘 종료 | (pid 266) | 로그아웃 +------+------+ | 명령어 수행 | fork() \|/ +------+------+ | bash | | (pid5909) | +------+------+ | | exec() \|/ +------+------+ |다른 프로세스| | (pid5909) | +------+------+ |
[1] | 최초의 init 는 커널의 init 쓰레드에 의해 실행됩니다. |
[2] | ps 를 수행했을 때 bash 등의 앞에 '-' 기호가 붙어서 -bash 등과 같이 표시된 것이 로그인 쉘입니다. 자세한 것은 다른 문서를 찾아보세요. |