저는 YouTube 튜토리얼(https://www.youtube.com/watch?v=asnXWOUKhTA)는 최소한의 Linux 배포판을 생성하지만 Ctrl+C를 누르면 커널이 충돌합니다!
편집: ctrl+d를 하면 혼란스러워요
답변1
이는 링크된 튜토리얼의 44:00 지점부터 정확히 발생합니다.
이 튜토리얼에서는 최소한의 쉘 스크립트를 사용합니다 /init
.
#!/bin/sh
mount -t sysfs sysfs /sys
mount -t proc proc /proc
mount -t devtmpfs udev /dev
sysctl -w kernel.printk="2 4 1 7"
/bin/sh
이 자습서에서는 추가된 줄이 initrd 파일을 생성하는 스크립트의 poweroff -f
마지막 줄로 /init
추가되지만 initrd는 실제로 명령을 포함하도록 업데이트되지 않습니다.
PID #1은 스크립트를 실행하는 셸이고 /bin/sh
루트 프롬프트를 표시하는 하위 프로세스가 되므로 PID #1 셸은 /bin/sh
종료될 때까지 기다리며 일단 종료되면 PID #1도 마찬가지입니다. 그 이후에는 어떤 프로세스도 없을 것입니다. 다른 사람들이 댓글에서 지적했듯이 PID #1이 손실되면 커널이 매우 불행해질 것입니다. 이로 인해 다음 메시지와 함께 커널 패닉이 발생합니다.
Kernel panic - not syncing: Attempted to kill init!
(이 경우 init
종료되는 것이 아니라 실제로 자체적으로 종료됩니다. PID #1은 일반적으로 시스템을 종료하거나 자체적으로 유효한 후속 항목을 제공하지 않고 종료되어서는 안 됩니다.)
이 "최소 Linux 배포판"이 매우 기본적인 장난감 설정이라는 다른 징후가 있습니다. 시작 시 다음과 /bin/sh
같이 표시됩니다.
/bin/sh: can't access tty; job control turned off
/bin/sh
이는 올바르게 설정된 콘솔 세션에서 실행되고 있지 않으며 일반적인 방식으로 Ctrl+ C또는 + 키 입력에 Ctrl응답 하지 않음을 나타냅니다 . Z대신 Ctrl-C를 받으면 /bin/sh
일반 쉘 명령처럼 종료됩니다. 그 후에는 스크립트가 /init
파일 끝에 도달하므로 스크립트를 실행한 쉘(PID #1)도 종료됩니다.
Ctrl-D는 표준 Unix 파일 끝 키 입력이기 때문에 동일한 효과를 가질 수 있습니다. 일반적으로 TTY 드라이버는 Ctrl-D를 감지하고 이를 파일 끝 조건으로 변환하지만 쉘이 여기에서 말한 것처럼 can't access tty
, 자체적으로 Ctrl을 감지할 수도 있습니다 -D. 기본적으로 쉘은 표준 입력의 파일 끝 조건을 "사용자가 어떻게든 연결을 끊었습니다"로 해석하므로 쉘이 종료되어 PID #1 스크립트가 끝에 도달하게 됩니다.
이 "최소 Linux 배포판"을 추가로 개발하기 위한 첫 번째 단계는 /init
스크립트를 PID #1의 요구 사항을 충족하는 프로세스로 바꾸는 것입니다.
exec()
이상적으로는 절대 종료하지 않지만 새 버전으로 업데이트를 활성화 할 수도 있습니다 .- 콘솔 세션 및 기타 구성된 TTY를 적절하게 초기화합니다(항상 존재하는 이와 연관된 프로세스를 모니터링하고
getty
콘솔 또는 구성된 TTY에 라이브 프로세스가 없는 것으로 확인되면 해당 프로세스를 시작). wait(-1)
고아 좀비 수확: PID #1 은 커널이 PID #1을 PPID로 할당하는 고아 프로세스에서 SIGCHLD 신호를 얻는 데 대부분의 시간을 소비해야 합니다 . 이러한 고아 프로세스가 죽을 때마다wait()
그 결과 코드를 읽고, 일단 완료되면 커널은 프로세스 테이블에서 죽은 프로세스를 지울 수 있으므로 좀비처럼 돌아다니지 않습니다.
이는 적절한 구성을 추가하여 달성할 수 있습니다.바쁜 상자/bin/init
initrd 파일에 추가하고 마지막 줄을 /init
다음으로 바꿉니다.
exec /bin/init
여기서 중요한 점은 exec
현재 PID #1로 스크립트를 실행 중인 셸이 새 바이너리를 호출하기 전에 시스템 호출을 생략하여 자체적 /init
으로 교체되도록 한다는 것입니다. 따라서 PID 번호는 변경되지 않으며 실제 PID #1 역할을 맡을 수 있습니다./bin/init
fork()
exec()
/bin/init