답변:
나는 어두운 숲으로 이끄는 정원 경로 인 LFS를 엉망으로 만들지 않았습니다.
Arch와 같은 초기 설치 또는 Ubuntu 서버와 같은 헤드리스 버전을 많이 제어 할 수있는 배포판으로 시작하십시오. 이것의 요점은 init 구성의 복잡성을 제한하기 위해 공간을 절약하는 데 그다지 중요하지 않습니다. 헤드리스 배포판에서 시작하여 실행하려는 응용 프로그램에 GUI가 필요한 경우 init로 시작한 GUI 로그인 (일명 디스플레이 관리자 또는 DM) 및 완전한 데스크탑으로 끝나지 않고도 필요한 것을 추가 할 수 있습니다. 그것과 함께 갈 환경.
그런 다음 init 시스템 을 목적 에 맞게 구성 하는 방법을 배우려고합니다 . init 없이는 수행 할 수 없으며 목표를 달성하는 가장 좋은 방법 일 수 있습니다. 리눅스에서 일반적으로 사용되는 init에는 세 가지 변형이 있지만 다른 것도 있습니다 .
데비안은 전형적인 Unix SysV 스타일 init 변형을 사용합니다 . 대로의 jessie
방출 데비안도 전환했다 systemd
( https://wiki.debian.org/systemd )
우분투와 파생어는 upstart를 사용 합니다.
Fedora, Arch 및 파생 상품은 systemd를 사용 합니다.
아직 이것들에 대해 아는 것이 없다면, 다른 것보다 사용하기가 특히 어렵지 않습니다. 나중에 두 가지 중 하나를 사용하면 SysV와의 이전 버전과의 호환성을위한 메커니즘을 제공 하지만 그에 신경 쓰지 않으면 더 간단하지 않습니다. 1
여기서 중요한 점은 부팅시 초기화 작업을 최소화하는 것입니다. 즉, 집중하려는 응용 프로그램을 지원하기 위해 최소량의 소프트웨어를 실행하는 시스템을 만드는 방법입니다. BTW, 그것은 일반적인 작업입니다 (적어도 "유용하지 않은"하나의 userland 프로세스를 문자 그대로 실행할 수는 없습니다).
실행하려는 응용 프로그램이 GUI 프로그램 인 경우 (GUI 응용 프로그램에 X 서버가 필요하므로 문자 그대로 하나의 응용 프로그램을 실행할 수없는 좋은 예) ~/.xinitrc
다음과 같은 모양을 가질 수 있습니다 .
#!/bin/sh
myprogram
그러면 startx
프로그램이 유일하게 실행되고 창 관리자 나 데스크탑 환경이 없기 때문에 데스크탑을 변경하거나 다른 것을 시작할 수 없습니다 (따라서 창 프레임이나 제목 표시 줄도 없음).
1. 요점을 조금만 이해하려면 :이 문제를 조사 할 때 이전에 SysV에 익숙한 사람들 (예 : 너무 복잡하다고 주장하는 사람들)의 시스템 및 신생에 대한 불만이있을 수 있습니다. 그러나 객관적으로 SysV보다 복잡하지는 않지만 (IMO 시스템은 실제로 사용하기가 더 간단합니다) 대부분의 개는 오래된 트릭을 선호합니다. 이 그립은 이제 두 시스템이 한동안 사용되어지고있다.
init
있지만, 확실히 당신이없이 할 수 있습니다 upstart, systemd,
또는 sysv. init
이름을 그냥 실행 파일 init
이 마운트 할 때 커널 호출하는 initramfs.
이 다른 세조차하지 않은 대부분의 경우 init
그러나 실제로있어 exec
의한에 에드 init,
하는 일반적입니다busybox.
busybox
별도의 답변으로 별도의 치료를받을 자격이 있기 때문에 의도적으로 제외 했지만 나에게는 그렇지 않습니다.
최소한의 init hello world 프로그램 단계별
무한 루프로 끝나는 종속성없이 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
종료 시스템 호출이나 커널 패닉을 사용할 수 없습니다.
그때:
mkdir d
as --64 -o init.o init.S # assemble
ld -o d/init init.o # link
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"
이것은 hello world at에서 파일 시스템을 생성하는데 /init
, 이것은 커널이 실행되는 최초의 userland 프로그램입니다. 또한 파일을 더 추가 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 프로그램을 정적으로 연결하면 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
동적 링크는 동적 링커 실행 파일을 설정해야하며, 가장 일반적인 것은 glibc와 같은 C 표준 라이브러리의 일부입니다.
USB가 켜진 상태에서 실제 하드웨어에서 실행할 수 있습니다 /dev/sdX
.
make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX
이 주제에 대한 훌륭한 소스 : 기술 팁 : initramfs 사용 방법 | landley.net 또한 gen_initramfs_list.sh
프로세스를 자동화하는 데 도움이되는 Linux 커널 소스 트리의 스크립트 인 사용 방법에 대해서도 설명합니다 .
Ubuntu 16.10, QEMU 2.6.1에서 테스트되었습니다.
다음 단계
다음으로 할 일은 BusyBox 를 설정하는 것 입니다.
BusyBox는 POSIX-y 쉘을 포함한 기본 POSIX-y CLI 유틸리티를 구현하여 시스템을 대화식으로보다 쉽게 실험 할 수 있습니다.
개인적으로,이 시점에서 나는 Buildroot에 의존하는 것을 선호합니다. Buildroot 는 소스에서 모든 것을 빌드하고 루트 파일 시스템을 만드는 것을 자동화하는 놀라운 스크립트 세트입니다.
https://github.com/cirosantilli/linux-kernel-module-cheat 에서 매우 상세하고 자동화 된 도우미를 업로드했습니다.
프로그래밍에 익숙하지 않고 처음부터 새로 작성하려면 LFS, 즉 Scratch에서 Linux를 사용할 수 있습니다. http://www.linuxfromscratch.org/
ubutnu를 사용자 정의하려면 ubunt-builder를 사용하고 rpm 기반으로 원한다면 SUsE-Studio를 사용할 수 있습니다 .Suse studio를 사용하면 사용자 정의 수세 리눅스를 만들 수 있습니다
건배
"하나의 프로그램"에 필요한 것이 더 있습니다.
LFS (일명 " Linux From Scratch ") 를 구축하여 구성하는 방법을 이해하기 시작할 수있다 . 그런 다음 LFS에서 Gnome 또는 KDE 와 같은 무거운 하위 시스템을 구축 하는 것이 정말 어려울 수 있기 때문에 프로그램에 필요한 것을 추가하거나 전체 배포를 진행할 것입니다 .
물론 처음에는 뒤로 가기가 더 쉬울 수 있지만 전체 배포에서 항목을 제거하는 것은 번거로울 수 있습니다. VM에서이를 수행하고 모든 단계에서이 VM을 복사하십시오.
(나의 2 센트)
편집 :
CentOS 또는 Ubuntu 와 같은 전체 배포에서 시작하는 대신 SecurityBeast에서 지적한 것처럼 다음과 같은 배포 도구를 작성하는 방법을 살펴볼 수도 있습니다.
"하나의 프로그램"에 필요한 것은 무엇이며 어떤 자원이 필요한지 물어보십시오.
다양한 라이브러리와 지원 바이너리가 필요한 경우 "일반"리눅스 배포판 (데비안 또는 이와 유사한 것)을 사용하고 부팅 프로세스를 약간 망쳐 놓는 것이 가장 좋습니다.
더 좁은 지원 항목이 필요하지만 네트워킹이나 다른 커널 모듈 또는 사용자 랜드 지원 비트를 사용하는 다양한 하드웨어 지원이 여전히 필요하고 일반 배포판의 디스크 공간 오버 헤드를 원하지 않는 경우 임베디드 배포판 (buildroot 또는 이와 유사한 것) 또는 아마도 처음부터 리눅스 (유지 보수 두통 일 수 있음)
비 모듈 식 커널이 제공 할 수있는 것 외에 다른 것이 없으면 커널에서 직접 바이너리를 실행하는 것이 가장 효과적 일 수 있습니다.
busybox
것이 좋지만 아마도 원하는 것이 아닐 수도 있습니다. 따라서 필요한 시간을내어 귀하의 필요를 표현하면 도와 드릴 수 있습니다. 주저하지 말고 편집 그 안에 모든 관련 요소를 추가 할 수있는 질문을.