저는 커널(v4.1-rc5)과 busybox(v1.23.2)로 채워진 initramfs로만 구성된 매우 작은 Linux 시스템을 구축하고 있습니다. 대부분의 경우 잘 작동하지만 내장 initramfs를 사용하든 외부 initramfs를 사용하든 /init의 명령 실행이 다르게 동작하는 것을 관찰했습니다.
/init 스크립트는 다음과 같습니다.
#!/bin/sh
dmesg -n 1
mount -t devtmpfs none /dev
mount -t sysfs none /sys
mount -t proc none /proc
echo "Welcome"
while true
do
setsid cttyhack /bin/sh
done
그런 다음 kernel.config의 CONFIG_INITRAMFS_SOURCE 옵션을 initramfs에 대한 모든 폴더가 포함된 디렉터리로 설정하거나 다음을 실행합니다.
find . | cpio -H newc -o | gzip > ../rootfs.cpio.gz
그것을 구축합니다.
그런 다음 커널을 컴파일할 때 CONFIG_INITRAMFS_SOURCE 설정 여부에 관계없이 시스템의 두 가지 변형이 생성됩니다.
initramfs에 포함된 bzImage
bzImage + rootfs.cpio.gz(외부 initramfs)
지금 그걸 사용하기 시작하면qemu
qemu-system-x86_64 -enable-kvm -kernel bzImage
또는
qemu-system-x86_64 -enable-kvm -kernel bzImage -initrd rootfs.cpio.gz
다음과 같은 행동 차이가 있습니다.
버전 2(외부 initramfs)에서는 모든 것이 잘 작동하고 "Welcome"이 표시되고 프롬프트가 표시됩니다. 그러나 버전 1(embedded initramfs)의 경우 경고가 표시됩니다.
unable to open an initial console
"환영합니다"가 표시되지 않지만 메시지가 표시됩니다.
프로세스에 대해 제가 이해한 바에 따르면, initramfs의 두 버전 모두 동일한 폴더에서 빌드했으므로(또는 커널이 빌드하도록 했기 때문에) 동일한 파일을 포함해야 합니다.
이 동작을 설명하는 데 도움을 줄 수 있는 사람이 있는지 궁금합니다.
* 갱신 *
mikeserv가 의견에서 말했듯이 커널에는 기본적으로 최소한의 내장 initramfs가 포함되어 있습니다. 외부 항목을 사용하는 경우 여전히 존재하지만 자신의 항목을 포함하면 덮어쓰게 됩니다. 나는 표준과 달리 이것이 실제로 비어 있지 않고 dev 폴더, 루트 폴더 및 /dev/console 장치를 포함한다는 것을 발견했습니다. 그러면 이 장치는 외부 initramfs를 사용할 때 사용되지만, 직접 삽입하면 재정의됩니다. 따라서 mknod -m 622 initramfs_src/dev/console c 5 1
자신의 장치를 내장할 때 initramfs 소스에 /dev/console 장치를 포함해야 합니다.
이 문제를 해결하는 데 도움을 준 mikeserv, Frostschutz 및 JdeBP에게 큰 감사를 드립니다!
답변1
정말 똑같나요?
/usr/src/linux/usr/initramfs_data.cpio.gz
다음과 같이 bzImage에서 내장 이미지를 찾거나 추출할 수 있습니다 .https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging
내장을 사용하고 외장으로 사용하면 작동이 될까요?
여전히 다르다면 커널 자체는 동일한가요? ( /proc/config.gz
둘을 비교해보세요)
약간의 차이가 있어야 합니다. 커널이 initramfs의 출처에 대해 어디에서 관심을 갖는지 모르겠습니다. qemu
매개변수를 전달할 때 다른 설정을 사용하는 것이 더 의심스럽습니다 -initrd
...
그건 그렇고, /init
나에게 당신은 무한한 껍질에 알을 낳는 것처럼 보입니다. setsid
아니요 exec
. 내가 잘못?
답변2
Buildroot 2018.02에서 이 문제를 처리하는 방법에 관심이 있을 수도 있습니다.
BR2_TARGET_ROOTFS_INITRAMFS=y
initramfs( ) 또는 initrd( ) 를 사용할 때마다 rootfs에 BR2_TARGET_ROOTFS_CPIO=n
다음이 추가됩니다./init
https://github.com/buildroot/buildroot/blob/2018.02/fs/cpio/init
#!/bin/sh
# devtmpfs does not get automounted for initramfs
/bin/mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
exec /sbin/init "$@"
사본은 다음에 의해 만들어집니다.https://github.com/buildroot/buildroot/blob/2018.02/fs/cpio/cpio.mk:
# devtmpfs does not get automounted when initramfs is used.
# Add a pre-init script to mount it before running init
define ROOTFS_CPIO_ADD_INIT
if [ ! -e $(TARGET_DIR)/init ]; then \
$(INSTALL) -m 0755 fs/cpio/init $(TARGET_DIR)/init; \
fi
endef
다른 경우와는 달리 initramfs의 초기화 경로를 아는 것도 /init
유용합니다 ./sbin/init
init와 같은 프로그램을 시작하는 대신 init=/path/to/program이 커널에 전달되는 원인은 무엇입니까?