Ctrl + C가 커널을 죽이지 않도록 하는 방법은 무엇입니까? [폐쇄]

Ctrl + C가 커널을 죽이지 않도록 하는 방법은 무엇입니까? [폐쇄]

저는 YouTube 튜토리얼(https://www.youtube.com/watch?v=asnXWOUKhTA)는 최소한의 Linux 배포판을 생성하지만 Ctrl+C를 누르면 커널이 충돌합니다!

편집: ctrl+d를 하면 혼란스러워요

답변1

이는 링크된 튜토리얼의 44:00 지점부터 정확히 발생합니다.

튜토리얼은 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/initinitrd 파일에 추가하고 마지막 줄을 /init다음으로 바꿉니다.

exec /bin/init

여기서 중요한 점은 exec현재 PID #1로 스크립트를 실행 중인 셸이 새 바이너리를 호출하기 전에 시스템 호출을 생략하여 자체적 /init으로 교체되도록 한다는 것입니다. 따라서 PID 번호는 변경되지 않으며 실제 PID #1 역할을 맡을 수 있습니다./bin/initfork()exec()/bin/init

관련 정보