이것은 사용자 공간 애플리케이션에 관한 질문입니다. 제 말을 들어보세요!
아마도 Linux의 기능적 배포판을 실행하려면 세 가지 "응용 프로그램"이 필요합니다.
부트로더 - 임베디드용, 일반적으로 U-Boot이지만 엄격한 요구 사항은 아닙니다.
커널 - 매우 간단합니다.
루트 파일 시스템 - 그것 없이는 쉘로 부팅하는 것이 불가능합니다. 커널이 부팅되는 form이라는 파일 시스템을 포함합니다
init
.
내 질문은 #3에 관한 것입니다. 누군가가 극도로 최소한의 rootfs를 구축하고 싶다면(이 질문에서는 GUI가 없고 쉘만 있다고 가정하겠습니다) 쉘로 부팅하려면 어떤 파일/프로그램이 필요합니까?
답변1
그것은 모두 귀하의 장치에서 사용하려는 서비스에 따라 다릅니다.
프로그램
Linux를 직접 부팅할 수 있습니다.껍데기. 프로덕션 환경에서는 그다지 유용하지 않습니다(단순히 쉘을 갖고 싶어하는 사람). 그러나 대화형 부트로더가 있을 때 개입 메커니즘으로 유용합니다. 즉, init=/bin/sh
커널 명령줄에 전달됩니다. 모든 Linux 시스템(및 모든 Unix 시스템)에는 /bin/sh
.
세트가 필요해쉘 유틸리티.바쁜 상자매우 일반적인 선택입니다. 쉘을 포함하고 있으며 파일 및 텍스트 조작( cp
, grep
, ... ), 네트워크 설정( ping
, ifconfig
, ... ), 프로세스 조작( ps
, nice
, ... ) 및 기타 다양한 시스템에 일반적으로 사용됩니다. 도구 용 유틸리티 ( fdisk
, mount
, , ... )를 사용했습니다. syslogd
BusyBox는 매우 구성 가능합니다. 컴파일 타임에 필요한 도구나 개별 기능을 선택하여 애플리케이션에 적합한 크기/기능 절충안을 얻을 수 있습니다. 그 외에는 sh
없습니다 ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, BusyBox mount
는 umount
각 유틸리티에 대한 심볼릭 링크가 있는 단일 바이너리로 설치됩니다.halt
cat
cp
mv
rm
mkdir
rmdir
ps
sync
busybox
일반적인 UNIX 시스템의 첫 번째 프로세스는 다음과 같습니다.init
. 그 임무는 다른 서비스를 시작하는 것입니다. BusyBox에는 초기화 시스템이 포함되어 있습니다. init
바이너리(일반적으로 에 있음 ) 외에도 시작할 /sbin
구성 파일(일반적으로 호출되는 /etc/inittab
일부 최신 초기화 교체에서는 이 파일을 제거하지만 소규모 임베디드 시스템에서는 찾을 수 없음) 도 필요합니다. 서비스가 제공되나요? BusyBox의 경우 /etc/inittab
선택 사항입니다 . 누락된 경우 콘솔에 루트 셸이 생기고 /etc/init.d/rcS
시작 시 스크립트가 실행됩니다(기본 위치).
물론 장치가 유용한 작업을 수행하도록 만드는 프로그램을 제외하고 이것이 필요한 전부입니다. 예를 들어, 내 집 라우터에서 실행 중입니다.OpenWrt변형에서 유일한 프로그램은 BusyBox nvram
(NVRAM의 설정을 읽고 변경하는 데 사용됨)와 네트워크 유틸리티입니다.
모든 실행 파일이 정적으로 링크되지 않는 한 동적 로더( ld.so
libc 선택 및 프로세서 아키텍처에 따라 다른 이름으로 호출될 수 있음)가 필요합니다.동적 라이브러리( /lib/lib*.so
그리고 어쩌면 그 중 일부도 /usr/lib
) 이러한 실행 파일에 필요합니다.
디렉토리 구조
이것파일 시스템 계층 표준Linux 시스템의 일반적인 디렉터리 구조를 설명합니다. 데스크탑과 서버 설치 모두에서 작동합니다. 임베디드 시스템에서는 많은 부분을 생략할 수 있습니다. 이는 일반적인 최소값입니다.
/bin
: 실행 가능한 프로그램(일부는 포함되어 있을 수 있음/usr/bin
)/dev
:장치 노드(아래 참조)/etc
:구성 파일/lib
: 동적 로더를 포함한 공유 라이브러리(모든 실행 파일이 정적으로 링크되지 않은 경우)/proc
: 마운트 지점프로세스 파일 시스템/sbin
: 실행 가능한 프로그램입니다. 차이점은 시스템 관리자에게만 유용한 프로그램에 적용된다는/bin
점 이지만, 임베디드 장치에서는 이러한 구별이 의미가 없습니다. 에 대한 심볼릭 링크를/sbin
만들 수 있습니다 ./sbin
/bin
/mnt
: 읽기 전용 루트 파일 시스템을 유지 관리 시 임시 마운트 지점으로 편리하게 사용/sys
: 마운트 지점sysfs 파일 시스템/tmp
: 임시 파일의 위치(일반적으로tmpfs
마운트됨)/usr
: 루트 파일 시스템에 존재하지 않는 하위 디렉터리bin
와 추가 파일lib
을 포함합니다. 그렇지 않은 경우 루트 디렉터리에 대한 심볼릭 링크를 만들 수 있습니다 .sbin
/usr
/usr
장치 파일
다음은 몇 가지 일반적인 최소 항목입니다 /dev
.
console
full
(글을 쓰면 항상 "장치에 남은 공간이 없습니다"라고 보고됩니다)log
(로그 항목을 보내기 위해 프로그램에서 사용하는 소켓)syslogd
데몬(예: BusyBox)은 다음에서 읽습니다.null
(항상 비어있는 파일처럼)ptmx
그리고pts
목차, 사용하고 싶다면의사 터미널(즉, 콘솔 이외의 모든 터미널) - 예를 들어 장치가 인터넷에 연결되어 있고 telnet 또는 ssh를 통해 로그인하려는 경우random
(임의의 바이트를 반환하므로 차단 위험이 있음)tty
(항상 프로그램의 터미널을 지정하십시오)urandom
(임의의 바이트를 반환하며 차단하지 않지만 새로 부팅된 장치에서는 무작위가 아닐 수 있습니다)zero
(무제한 널 바이트 시퀀스 포함)
그 외에도 하드웨어에 대한 항목이 필요합니다( 에 항목이 없는 네트워크 인터페이스 제외 /dev
): 직렬 포트, 스토리지 등.
내장형 장치의 경우 일반적으로 루트 파일 시스템에서 직접 장치 항목을 만듭니다. 고급 시스템에는 MAKEDEV
Create /dev
Entry라는 스크립트가 있지만 임베디드 시스템에서는 이 스크립트가 일반적으로 이미지에 번들로 제공되지 않습니다. 일부 하드웨어가 핫스왑이 가능한 경우(예: 장치에 USB 호스트 포트가 있는 경우 /dev
)우데브(루트 파일 시스템에는 여전히 최소한의 설정이 있을 수 있습니다).
시작 시 작업
올바른 작동을 위해서는 루트 파일 시스템 외에도 몇 가지 파일 시스템을 마운트해야 합니다.
- 프로세스 파일 시스템( 거의
/proc
필수) - 시스템 파일 시스템( 거의
/sys
필수) tmpfs
파일 시스템 열기/tmp
(프로그램이 플래시나 읽기 전용 루트 파일 시스템이 아닌 RAM에 있는 임시 파일을 생성할 수 있음)- 동적인 경우 tmpfs, devfs 또는 devtmpfs
/dev
(위의 "장치 파일"에서 udev 참조) - 개발자사용하려면 [의사 터미널]을 켜세요
/dev/pts
(위 참고 사항 참조pts
).
너 하나 만들 수 있어/etc/fstab
파일을 저장하고 호출 mount -a
하거나 mount
수동으로 실행하세요.
시작하다시스템 로그로그를 쓸 수 있는 곳이 있는 경우 데몬(및 프로그램이 처리하지 않는 klogd
경우 커널 로그 ).syslogd
그러면 장치는 애플리케이션별 서비스를 시작할 준비가 됩니다.
루트 파일 시스템을 만드는 방법
길고 다양한 이야기이므로 여기서는 몇 가지 제안을 드리고자 합니다.
루트 파일 시스템은 RAM(일반적으로 ROM 또는 플래시 메모리의 (일반적으로 압축된) 이미지에서 로드) 또는 디스크 기반 파일 시스템(ROM 또는 플래시 메모리에 저장)에 보관하거나 네트워크에서 로드(일반적으로 다음을 통해 로드)할 수 있습니다. 네트워크) .TFTP) 적용된다면. 루트 파일 시스템이 RAM에 있는 경우 다음으로 설정합니다.파일 시스템 초기화— 시작 시 내용이 생성되는 RAM 파일 시스템입니다.
임베디드 시스템용 루트 이미지를 조합하는 데 사용할 수 있는 프레임워크가 많이 있습니다. 그 안에 몇 가지 팁이 있습니다비지박스 FAQ.루트 구축Linux 커널 및 BusyBox와 유사한 설정을 사용하여 전체 루트 이미지를 빌드할 수 있는 인기 있는 이미지입니다.오픈 임베디드또 다른 프레임워크입니다.
Wikipedia에는 인기 있는 (불완전한) 목록이 있습니다.임베디드 Linux 배포판. 가까운 곳에 있을 수 있는 임베디드 Linux의 예는 다음과 같습니다.OpenWrt네트워크 장치용 운영 체제 제품군입니다(Tinkerer 홈 라우터에서 인기 있음). 경험으로 배우고 싶다면 시도해 볼 수 있습니다처음부터 리눅스, 그러나 이는 임베디드 장치가 아닌 취미 데스크탑 시스템을 겨냥한 것입니다.
Linux 및 Linux 커널에 대한 참고 사항
Linux 커널에 포함된 유일한 동작은 부팅 시 첫 번째 프로그램을 실행하는 것입니다. (나는 들어가지 않을 것이다.초기화 프로그램그리고파일 시스템 초기화여기에 미묘함. ) 이 절차는 전통적으로내부에, 프로세스 ID 1이 있고 특정 권한이 있습니다(영향을 받지 않음).킬 신호) 및 책임(수확유아). Linux 커널로 시스템을 실행하고 원하는 프로세스를 첫 번째 프로세스로 시작할 수 있지만, 가지고 있는 것은 일반적으로 "Linux"라고 불리는 것이 아니라 Linux 커널 기반 운영 체제뿐입니다. 리눅스, 용어의 상식적으로는유닉스운영 체제와 유사하게 커널은리눅스 커널. 예를 들어 Android는 Unix와 유사하지 않지만 Linux 커널을 기반으로 하는 운영 체제입니다.
답변2
필요한 것은 파일 시스템에 별도로 배치된 정적으로 링크된 실행 파일뿐입니다. 다른 파일은 필요하지 않습니다. 이 실행 파일은 init 프로세스입니다. 비지박스일 수 있습니다. 이것은 쉘과 그 안에 있는 다른 많은 유틸리티를 모두 제공합니다. 비지박스에서 수동으로 명령을 실행하고, 루트 파일 시스템을 읽기-쓰기로 마운트하고, /dev 노드를 생성하고, 실제 초기화를 수행하는 등의 작업을 통해 완전한 기능을 갖춘 시스템에 들어갈 수 있습니다.
답변3
쉘 유틸리티가 필요하지 않으면 정적으로 링크된 mksh
바이너리(예: Linux/i386의 klibc - 130K)가 필요합니다. 루프에서만 호출되는 /linuxrc
or /init
또는 스크립트가 필요합니다 /sbin/init
.mksh -l -T!/dev/tty1
#!/bin/mksh
while true; do
/bin/mksh -l -T!/dev/tty1
done
이 -T!$tty
옵션은 최근 추가되었으며 mksh
지정된 터미널에 새 셸을 생성하고 기다리도록 지시합니다. (이전에는 -T-
프로그램을 데몬화하고 -T$tty
터미널에서 생성만 할 수 있었지만 기다릴 수는 없었습니다. 별로 좋지 않습니다.) 이 -l
옵션은 단지 로그인 셸(읽기 및 읽기)을 실행하도록 지시 /etc/profile
할 ~/.profile
뿐입니다 ~/.mkshrc
.
이는 터미널이 /dev/tty1
교체되었다고 가정합니다. (더 놀라운 점은 터미널이 자동으로 검색된다는 점입니다. /dev/console
완벽한 작업 제어 기능을 제공하지는 않습니다.)
/dev
작동하려면 몇 가지 파일이 필요합니다 .
- /dev/콘솔
- /dev/비어 있음
- /dev/tty
- /dev/tty1
커널 옵션으로 부팅하려면 devtmpfs.mount=1
패딩이 필요하지 않습니다 /dev
. 단지 빈 디렉터리(마운트 지점으로 사용하기에 적합)로 설정하면 됩니다.
일반적으로 일부 유틸리티(klibc, busybox, beastiebox, toybox 또는 도구 상자 등)가 필요하지만 실제로는 필요하지 않습니다.
~/.mkshrc
$PS1과 일부 기본 셸 별칭 및 기능을 설정하는 파일을 추가할 수 있습니다 .
mksh(및 해당 예제 mkshrc 파일)와 klibc-utils만 사용하여 Linux/m68k용 171K 압축(371K 비압축) initrd를 만든 적이 있습니다. (이것은 -T!가 셸에 추가되기 전이므로 로그인 셸을 생성 /dev/tty2
하고 사용자에게 터미널을 전환하라는 메시지를 콘솔에 표시합니다.) 잘 작동합니다.
이것은정말 최소한의설정. 다른 답변은 보다 독특한 시스템에 대한 훌륭한 제안을 제공합니다. 이것은 실제로 특별한 경우입니다.
면책조항: 저는 mksh 개발자입니다.
답변4
단계별 최소 초기화 Hello World 프로그램
이 답변에서 알 수 있듯이 필요한 것은 표준 라이브러리가 아닌 정적으로 링크된 ELF 파일이므로 단일 파일이 있는 파일 시스템입니다.
종속성 없이 Hello World를 컴파일하고 무한 루프로 끝납니다. init.S
:
.global _start
_start:
mov $1, %rax
mov $1, %rdi
mov $message, %rsi
mov $message_len, %rdx
syscall
jmp .
message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
.equ message_len, . - message
우리는 그것을 사용할 수 없습니다 sys_exit
. 그렇지 않으면 커널이 패닉을 일으킬 것입니다.
그 다음에:
mkdir d
as --64 -o init.o init.S
ld -o init d/init.o
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"
/init
그러면 커널이 실행할 첫 번째 사용자 모드 프로그램인 hello world를 사용하여 파일 시스템이 생성됩니다 . 또한 더 많은 파일을 추가하고 커널이 실행되는 동안 d/
프로그램에서 해당 파일에 액세스할 수 있도록 할 수도 있습니다./init
그런 다음 cd
Linux 커널 트리로 이동하여 평소와 같이 빌드하고 QEMU에서 실행합니다.
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"
다음 줄이 표시됩니다.
FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR
에뮬레이터 화면에서! 이것이 마지막 줄이 아니므로 더 자세히 살펴보아야 합니다.
C 프로그램을 정적으로 링크하는 경우에도 사용할 수 있습니다.
#include <stdio.h>
#include <unistd.h>
int main() {
printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
sleep(0xFFFFFFFF);
return 0;
}
그리고:
gcc -static init.c -o init
USB를 사용하여 실제 하드웨어에서 실행할 수 /dev/sdX
있으며 다음을 수행할 수 있습니다.
make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX
이 주제에 대한 중요한 출처:http://landley.net/writing/rootfs-howto.htmlgen_initramfs_list.sh
또한 프로세스 자동화에 도움이 되는 Linux 커널 소스 트리의 스크립트인 이를 사용하는 방법도 설명합니다 .
쉘의 최소한의 설정을 제공합니다.
Buildroot는 제가 가장 좋아하는 옵션입니다. 아래 설명을 참조하세요.가장 작은 Linux 구현은 무엇입니까?
이 시점에서 기본적으로 표준 라이브러리를 다루어야 하는데, sh
표준 라이브러리 없이 누가 쉘을 작성하겠습니까? 따라서 일부 자동화 스크립트를 사용하여 이 모든 것을 설정하는 것이 더 좋습니다.
Ubuntu 16.10, QEMU 2.6.1에서 테스트되었습니다.