init 프로세스가 Linux에서 쉘 스크립트 일 수 있습니까?


14

나는 사용자 정의 initramfs를 설정하는 방법에 대한 자습서를 진행했습니다.

유일하게 누락 된 것은 커널이로드 된 후에 실행되는 initramfs의 루트에있는 실행 파일 인 / init입니다. sys-apps / busybox에는 완전한 기능을 갖춘 쉘이 포함되어 있으므로 / init 바이너리를 간단한 쉘 스크립트로 작성할 수 있습니다 (컴파일해야하는 어셈블러 또는 C로 작성된 복잡한 애플리케이션 대신).

으로 시작하는 쉘 스크립트로 init의 예를 제공합니다. #!/bin/busybox sh

지금까지 init가 시작된 주요 프로세스이며 다른 모든 사용자 공간 프로세스는 결국 init의 자식이라는 인상을 받았습니다. 그러나 주어진 예제에서 첫 번째 프로세스는 실제로 bin/busybox/ sh나중에 init가 생성되는 프로세스입니다 .

이것이 올바른 상호 작용입니까? 예를 들어 그 시점에 사용 가능한 통역사가 있으면 init을 Python 스크립트 등으로 쓸 수 있습니까?

답변:


12

init는 (자식 프로세스로서) "스폰"되지 않고 오히려 exec다음과 같습니다.

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

exec전체 프로세스를 대체합니다. 최종 초기화는 여전히 첫 번째 프로세스 (pid 1)이지만, Initramfs에있는 프로세스보다 우선합니다.

/initpid 1을 가진 Busybox 쉘 스크립트 인 Initramfs 는 execBusybox switch_root( s 지금 switch_root은 pid 1)입니다. 이 프로그램은 마운트 포인트를 변경하므로 /mnt/root새로운 것 /입니다.

switch_root다시 exec에 s의 /sbin/init실제 루트 파일 시스템의; 따라서 실제 init 시스템을 pid 1을 사용하는 첫 번째 프로세스로 만들고 여러 자식 프로세스를 생성 할 수 있습니다.

어떻게 든 파이썬을 Initramfs에 넣을 수 있다면 파이썬 스크립트로도 할 수 있습니다. busybox를 포함하지 않으려는 경우 기능의 일부 (예 switch_root: 일반적으로 간단한 명령으로 수행하는 모든 기능)를 힘들게 다시 구현해야합니다 .

그러나 스크립트 바이너리 ( CONFIG_BINFMT_SCRIPT=y)를 허용하지 않는 커널에서는 작동하지 않으며 , 이런 경우에는 인터프리터를 직접 시작하여 스크립트를 어떻게 든로드해야합니다.


/얇은 공기 속으로 사라 지지 않습니다. 마운트되어 있습니다 (일반적으로 메모리를 절약하기 전에 내용이 모두 삭제됨) . 그것은이다 아직도 . switch_rootsyscall을 수행합니다 switchroot-이것은 커널 개발자가 커널 2.6에서 부팅 프로세스를 변경했을 때 제공 한 것입니다. initramfs가 필요합니다. 마술을하는 것은 커널입니다.
mikeserv

1
switchroot콜은 참으로 나에게 소식이 될 것입니다. 그 출처가 있습니까? switch_root.c 소스 코드를 보면 수동 프로세스 인 것 같으며 Documentation / filesystems / ramfs-rootfs-initramfs.txt에 설명 된 것과 같습니다. 또한 모든 것을 삭제하고 마운트하면이 시점에서 거의 사라집니다. 그렇지 않습니까?
frostschutz

pivot_root반면에 syscall입니다. 그것은 switch_root비록 사용되지 않고 일부 농구대를 뛰어 넘지 않고는 사용할 수 없으며, 어느 쪽 도이 답변에 전혀 중요하지 않으므로 방금 제거했습니다. 너무 나쁜, 정말 잘 ... P는 일이 마법을 생각하고 허공으로 사라져
frostschutz

글쎄, switch_root미안하지만, 나에게 보여줘서 고마워하는 것에 대한 잘못된 생각을 가지고 있지만 어쨌든 아무것도 사라지지 않습니다. 다시 initramfs 루트 지속되고 모두를 위해 항상있다 - 그것은 이다 루트.
mikeserv

1
당신이 링크문서 처럼 : initramfs는 rootfs입니다 : pivot_root rootfs를 마운트하거나 마운트 해제 할 수 없습니다. 대신 rootfs에서 모든 것을 삭제하여 공간을 확보하고 ( find -xdev / -exec rm '{}' ';'), 새로운 root ( cd /newmount; mount --move . /; chroot .)로 rootfs를 오버 마운트하고 , stdin / stdout / stderr을 새로운 / dev / console에 연결하고, 새로운 init를 실행하십시오.
mikeserv

4

리눅스 커널의 exec syscall은 기본적으로 shebang을 이해합니다.

실행 된 파일이 magic bytes로 시작 #!하면 커널에게 다음 #!/bin/sh과 같이 사용하도록 지시합니다 .

  • 하고 exec시스템 호출
  • 실행 가능 /bin/sh
  • CLI 인수 사용 : 현재 스크립트의 경로

이것은 다음과 같이 일반 userland 쉘 스크립트를 실행할 때 발생하는 것과 동일합니다.

./myscript.sh

파일이 .ELF대신 매직 바이트로 시작된 경우 #!커널은 ELF 로더를 선택하여 대신 실행합니다.

자세한 내용 : 사람들이 왜 파이썬 스크립트의 첫 줄에 #! / usr / bin / env python shebang을 작성합니까? | 스택 오버플로

일단 이것을 염두에두면, /init쉘 스크립트를 포함하여 커널이 실행할 수있는 모든 것이 될 수 있으며, /bin/sh이 경우 왜 첫 번째 실행 파일이 될 수 있는지 쉽게 받아 들일 수 있습니다 .

https://github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-init 는 실행 가능한 최소 예제입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.