จะสร้างระบบ Linux ที่ใช้งานแอพพลิเคชั่นเดียวได้อย่างไร?


17

ฉันพยายามเรียกใช้แอปพลิเคชัน Linux และสิ่งที่ฉันต้องการเรียกใช้คือแอปพลิเคชันนี้เดียวที่บูต ฉันต้องการระบบเครือข่ายและนั่นคือทั้งหมด (ไม่มีจอแสดงผลอุปกรณ์ต่อพ่วงและอื่น ๆ ) ฉันไม่ต้องการให้แอปพลิเคชันอื่นทำงานเพื่อให้แอปพลิเคชันที่ฉันใช้มี CPU 100% เป็นไปได้ไหม


มันจะไม่สามารถคว้าซีพียู 100% ที่เห็นเนื่องจากระบบปฏิบัติการของคุณยังต้องการทรัพยากรบางอย่าง
n0pe

@ MaxMackie เห็นได้ชัดว่า แต่ฉันอยากให้ระบบปฏิบัติการใช้ในนามของแอปพลิเคชันเท่านั้น (สำหรับจุดประสงค์ในการเชื่อมต่อเครือข่าย)
dschatz

1
คุณตระหนักดีว่าแม้จะมีสภาพแวดล้อมเดสก์ท็อปที่โหลด แต่เมื่อไม่มีการใช้งานก็ไม่ได้ใช้ซีพียูใช่ไหม? และหน่วยความจำที่ใช้นั้นขึ้นอยู่กับการแลกเปลี่ยนหากแอปพลิเคชันอื่นต้องการ
psusi

@dschatz มันจะช่วยถ้าคุณมีรายละเอียดเพิ่มเติมในคำถามของคุณ เช่นบอกเราเพิ่มเติมเกี่ยวกับแอปพลิเคชันที่คุณต้องการเรียกใช้วิธีที่คุณต้องการให้แอปพลิเคชันทำงานและฮาร์ดแวร์ประเภทใดที่คุณใช้งานอยู่
NN

ถ้าเป็นไปได้ฉันอยากจะรู้ว่าทำไมคุณถึงต้องการสิ่งนี้ จากสิ่งที่ฉันเข้าใจคุณต้องการลบทุกสิ่งออกจากระบบปฏิบัติการ (รวมอยู่ในคอนโซล) เพื่อเรียกใช้แอปของคุณ ประสิทธิภาพที่เพิ่มขึ้นจะได้รับเพียงเล็กน้อยดังนั้นอะไรคือจุดประสงค์ของการทำงานทั้งหมด?
nmat

คำตอบ:


13

CPIO ที่เริ่มต้นน้อยที่สุดโปรแกรมสวัสดีชาวโลกทีละขั้นตอน

ป้อนคำอธิบายรูปภาพที่นี่

คอมไพล์สวัสดีชาวโลกโดยไม่ต้องพึ่งพาใด ๆ ที่สิ้นสุดในวงวนไม่สิ้นสุด 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"

สิ่งนี้สร้างระบบไฟล์ด้วย hello world ของเรา/initซึ่งเป็นโปรแกรม userland แรกที่เคอร์เนลจะทำงาน เราสามารถเพิ่มไฟล์เพิ่มเติมd/และพวกเขาจะสามารถเข้าถึงได้จาก/initโปรแกรมเมื่อเคอร์เนลทำงาน

จากนั้นcdเข้าไปในเคอร์เนลลินุกซ์สร้างเป็นปกติและเรียกใช้ใน 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.htmlนอกจากนี้ยังอธิบายถึงวิธีการใช้gen_initramfs_list.shซึ่งเป็นสคริปต์จากทรีของเคอร์เนล Linux เพื่อช่วยให้กระบวนการทำงานโดยอัตโนมัติ

ขั้นตอนถัดไป: ตั้งค่า BusyBox เพื่อให้คุณสามารถโต้ตอบกับระบบ: /unix/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

ทดสอบกับ Ubuntu 16.10, QEMU 2.6.1


3

คุณสามารถเริ่มต้นเคอร์เนลกับinit=/path/to/myappพารามิเตอร์ที่กำหนดไว้ใน bootloader ของคุณ


2
นี่เป็นวิธีการแก้ปัญหาที่ค่อนข้างรุนแรง การแทนที่สคริปต์เริ่มต้นด้วยแอปพลิเคชันผู้ใช้จะทำให้แอปพลิเคชันทำงานโดยไม่มีระบบเครือข่ายโดยไม่มีระบบไฟล์ใด ๆ นอกเหนือจากรูทที่เมาท์ (ไม่มี sysfs หรือ proc หรือ tmpfs) และอาจไม่สามารถสร้างโหนดอุปกรณ์ได้
ขี้เลื่อย

2
@sawdust: เห็นด้วยทั้งหมด แต่คำถามก็สุดขั้วเช่นกัน ... :-)
MichałŠrajer

2

ดูเหมือนว่าคุณกำลังพยายามที่จะตั้งค่าคีออสก์ คำแนะนำส่วนใหญ่รอบ ๆ อินเทอร์เน็ตมุ่งเน้นไปที่เว็บเบราว์เซอร์เช่น Firefox เป็นแอปพลิเคชันเดียวที่ทำงาน ลองดูที่คู่มือนี้สำหรับแนวคิด


2
อืมฉันแค่พยายามเรียกใช้แอปพลิเคชันเดียวด้วยระบบเครือข่าย ฉันไม่ต้องการให้ X ใด ๆ และแอปพลิเคชั่นอื่น ๆ ทำงานน้อยที่สุด ฉันไม่เห็นว่าสิ่งนี้จะ จำกัด การทำงานของ daemons ที่ไม่จำเป็นทั้งหมดได้อย่างไร
dschatz

แอปพลิเคชันสามารถทำงานโดยไม่มี X ได้หรือไม่
Geek

2

แน่นอนคุณสามารถเรียกใช้แอปพลิเคชันผู้ใช้เดียวหลังจากบูตเคอร์เนล แต่จะไม่ได้ 100% ของ CPU เพราะจะมีกระบวนการที่เกี่ยวข้องกับเคอร์เนลอื่น ๆ ที่ต้องมีอยู่ โดยทั่วไปจะทำในอุปกรณ์ที่ฝังตัวกับ Linux เช่นเราเตอร์ไร้สาย ฉันยังมีประสบการณ์โดยตรงในการทำสิ่งนี้สำหรับแอพพลิเคชั่นแบบมัลติเธรด

เมื่อเคอร์เนลบู๊ตแล้วจะมีการเริ่มต้นหรือสคริปต์เริ่มต้นทำงาน อ่านข้อมูลเกี่ยวกับลินุกซ์runlevelsและกระบวนการ init มีรูปแบบการเริ่มต้นใช้งานที่หลากหลายดังนั้นจึงไม่สามารถระบุได้อย่างเฉพาะเจาะจง แต่ลีนุกซ์จะอนุญาตให้คุณตั้งค่าแอพพลิเคชั่นและ daemons ใดที่จะทำงานในสถานการณ์ของคุณอย่างแน่นอน นอกเหนือจากไฟล์เริ่มต้นที่รูทไฟล์ที่ต้องแก้ไขอยู่ใน/ etcและโดยเฉพาะอย่างยิ่ง/etc/init.d

BTW ถ้าคุณไม่ได้เป็น superprogrammer หรือก่อนที่คุณจะเรียกใช้เซิร์ฟเวอร์ GDB ระยะไกลคุณจะต้องใช้คอนโซล debug บางอัน (ทั้งคอนโซล PC หรือพอร์ตอนุกรม) สำหรับแอปพลิเคชันของคุณ สิ่งนี้จะช่วยให้คุณได้รับการแจ้งเตือนข้อผิดพลาดของ seg ข้อผิดพลาดของบัสและการยืนยันที่ล้มเหลว ดังนั้นวางแผนที่จะมี "อุปกรณ์ต่อพ่วง" นอกเหนือจาก "เครือข่าย"


1

มีแอปพลิเคชั่นระบบบางตัวที่จะต้องเรียกใช้นอกเหนือจากนั้นแน่นอนคุณสามารถอุทิศทรัพยากรส่วนที่เหลือของคอมพิวเตอร์ให้กับแอปพลิเคชันนั้นได้ หากต้องการมีค่าต่ำสุดคุณสามารถดู distros Linux ที่มีขนาดเล็กมาก ๆ เช่น TinyCore Linux เป็นต้น

นอกจากนี้ยังขึ้นอยู่กับแอพพลิเคชั่นเองเช่นกันบริการใดบ้างที่ต้องการนอกเหนือจากเครือข่ายเป็นต้น

ฉันคิดว่าถ้าคุณสามารถให้ข้อมูลที่เฉพาะเจาะจงมากขึ้นคุณจะได้รับการตอบสนองอย่างละเอียดมากขึ้น

ชอบแอปประเภทใด ฯลฯ


แอปพลิเคชันของฉันใช้ไลบรารี pthread เพื่อรันเวิร์กโหลด mulithreaded จำนวนหนึ่ง (การดำเนินการทางคณิตศาสตร์) และสามารถสั่งให้ทำการคำนวณที่แตกต่างกันตามอินพุตจาก tcp / ip เมื่อมองดู TinyCore Linux มันจะบู๊ตในสภาพแวดล้อมเดสก์ท็อปเต็มรูปแบบซึ่งฉันไม่ต้องการ
dschatz

TinyCore มีน้องชายคนเล็กที่เรียกว่า MicroCore ไม่มี GUI ตรวจสอบ
n0pe

1
@ MaxMackie ฉันไม่ต้องการอินเทอร์เฟซบนเครื่องนอกสแต็ค tcp / ip แอปพลิเคชันสามารถบล็อกบนพอร์ตและสามารถควบคุมผ่านแพ็คเก็ต tcp ที่ส่งไปยังพอร์ตนั้น
dschatz

1
ฉันขอแนะนำสภาพแวดล้อมที่มีบริการเล็ก ๆ น้อย ๆ กำลังทำงานอยู่ (ลองดูlinuxhelp.blogspot.com/2006/04/… ) และสิ่งอื่น ๆ ที่นอกเหนือจากแอปพลิเคชันของคุณและแทบจะไม่ได้ติดตั้งเลย
n0pe

1
@dschatz ดีแล้วคุณต้องแฮกเคอร์เนลเอาทุกอย่างออกแล้วรวบรวมแอปของคุณเข้าไป ไม่ทุบตีไม่มีอะไรอย่างอื่น เพียงแค่แอปของคุณ .. ฮ่า ๆ
bakytn

1

หากคุณไม่ต้องการอะไรนอกจากลินุกซ์เคอร์เนลเครือข่ายและแอปพลิเคชันของคุณวิธีเดียวที่ทำได้คือ:

  • คุณจะต้องทำให้แอปพลิเคชันของคุณเป็นโมดูลเคอร์เนล - ตรวจสอบให้แน่ใจว่ามันถูกดีบั๊กและทดสอบอย่างดี โมดูลเคอร์เนลนี้จะต้องเริ่มต้นสิ่งที่มักจะทำผ่าน userspace เช่นตั้งค่าที่อยู่ IP ของอินเตอร์เฟสและสิ่งที่ดีทั้งหมด
  • คุณจะต้องดาวน์โหลดและกำหนดค่า ( make menuconfig) เคอร์เนลที่กำหนดเองของคุณและลบคุณลักษณะทั้งหมดที่ไม่เกี่ยวข้องกับการเรียกใช้ระบบและระบบเครือข่าย make menuconfigคุณจะต้องปิดการใช้งานไปยังชั้นบล็อกผมไม่ทราบวิธีการที่จะทำเช่นนี้ในเมล็ดที่ผ่านมาผ่าน
  • จากนั้นคุณต้องรวมโมดูลของคุณลงในเคอร์เนลดังนั้นจึงรวมเป็นส่วนหนึ่งของเคอร์เนลและไม่ใช่โมดูลที่โหลดได้ คุณน่าจะปิดการใช้งานโมดูลที่โหลดได้ในขั้นตอนข้างต้น หากคุณรู้จัก C / C ++ มากพอที่จะสร้างโมดูลเคอร์เนลสิ่งนี้น่าจะง่ายสำหรับคุณ
  • คุณต้องแก้ไขส่วนใดส่วนหนึ่งของเคอร์เนลที่ตื่นตระหนกหากinitล้มเหลวที่จะไม่ทำเช่นนั้นหรือเตรียมพร้อมที่จะใช้ชีวิตด้วยกระบวนการพื้นที่ผู้ใช้เพิ่มเติม 1 กระบวนการ

ฉันรู้ว่ามันเป็นไปได้สำหรับโมดูลเคอร์เนลเพื่อสร้างกระบวนการ - ง่ายps auxจะแสดงจำนวนมากในระบบทั่วไป (พวกเขาทั้งหมดอยู่ในวงเล็บ) คุณอาจต้องการให้โมดูลของคุณสร้างกระบวนการเคอร์เนล ในการกำจัดกระบวนการที่สร้างเคอร์เนลทั้งหมดนอกเหนือจากของคุณคุณจะต้องปิดการใช้งานเธรด [ kthreadd], การจัดการพลังงาน [ pm], เลเยอร์เหตุการณ์ [ events] และอื่น ๆ


หากคุณต้องการให้การติดตั้งเคอร์เนล + 1 กระบวนการผู้ใช้เป็นไปได้มากขึ้น

Linux มีตัวเลือกบรรทัดคำสั่งเคอร์เนลชื่อinit=- นี่คือสิ่งที่เคอร์เนลจะเริ่มเมื่อโหลดเสร็จ โปรแกรมต้องอยู่บนอุปกรณ์รูทที่ระบุด้วยroot=หรือใน initrd (โหลดโดย bootloader ของคุณ)

หากโปรแกรมนี้ออกจากการทำงาน Linux จะตื่นตระหนกดังนั้นตรวจสอบให้แน่ใจว่าไม่ได้ออกจากระบบ

หลายคนกระจายที่ทันสมัยของลินุกซ์มีมันติดตั้งดังนั้นinitโปรแกรมใน initrd ไม่เริ่มต้นใช้พื้นที่บางส่วนเพิ่มเติมก่อนที่จะเริ่มหรือ/sbin/init /sbin/systemdคุณจะต้องค้นหาสิ่งที่ distro ของคุณไม่ได้ที่นี่ (ข้อมูลสำหรับ Debian เป็นที่นี่ ) และหาสถานที่ที่คุณสามารถระบุสุดท้าย "แฮนด์ออฟ" โปรแกรมและจากนั้นคุณสามารถบอกให้เริ่มต้นโปรแกรมของคุณแทนหรือ initsystemd

systemdจัดการฟังก์ชั่นพื้นฐานมากมายเช่นการสร้าง/devการตั้งค่าชื่อโฮสต์และสิ่งอื่น ๆ ดังนั้นหากคุณมีความยืดหยุ่นคุณอาจต้องการดูการกำหนดค่าsystemdเพื่อวางไข่กระบวนการเดียวและเลือกที่จะเริ่มใหม่หากล้มเหลว ถ้าฉันไม่ผิดมันเป็นเช่นนี้โดยปกติสำหรับผู้ใช้คนเดียวหรือโหมดการกู้คืน - มันจะเริ่มเชลล์

คุณจะมี 2 กระบวนการทำงาน ( systemdและโปรแกรมของคุณ) แต่ระบบจะไม่ตื่นตระหนกหากโปรแกรมของคุณออกหรือหยุดทำงาน

พิจารณาด้วยการติดตั้ง Debian ที่มีน้ำหนักเบา - การติดตั้ง "netinst" ไม่ได้ทำงานมากไปกว่าเคอร์เนล, เชลล์และบริการคู่ - หรือพิจารณา OpenWRT / LEDE - มันมีเว็บเซิร์ฟเวอร์สำหรับ Luci ที่ทำงานโดยค่าเริ่มต้นและ บริการอื่น ๆ แต่ถูกปิดใช้งานได้ง่าย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.