Як створити систему Linux, яка запускає єдину програму?


17

Я намагаюся запустити додаток Linux, і все, що я хочу запустити, це ця програма з завантаження. Мені потрібна мережа, і це все (без дисплея, периферійних пристроїв тощо). Я не хочу, щоб інші програми працювали, щоб програма, яку я запускаю, мала 100% процесора. Чи можливо це?


Він не зможе захопити 100% процесора, оскільки ваша ОС все ще потребує певних ресурсів.
n0pe

@MaxMackie Очевидно, але я хотів би, щоб ОС взяла на себе тільки від імені програми (наприклад, для мережевих цілей).
dschatz

1
Ви розумієте, що навіть із завантаженим робочим середовищем, але сидячи там простоюючим, він не використовує жодного часу процесорного права? І баран, який він використовує, може бути замінений, якщо цього вимагають інші програми.
psusi

@dschatz Це допоможе, якщо ви включите більше деталей у своє запитання. Як розповісти більше про те, яку програму ви хочете запустити, як ви хочете її виконувати та яке обладнання ви використовуєте.
NN

Якщо можливо, я хотів би знати, чому ви цього хочете. З того, що я розумію, ви хочете видалити все з ОС (включена консоль) просто для запуску програми. Підвищення ефективності буде незначним, тож який сенс мати все це?
nmat

Відповіді:


13

Мінімальна initrd 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"

Це створює файлову систему з нашим привітним світом at /init, який є першою програмою для користувача, яка буде запускати ядро. Ми також могли б додати більше файлів, 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.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параметра, визначеного у вашому завантажувачі.


2
Це досить екстремальне рішення. Заміна сценарію запуску користувальницьким додатком призведе до запуску програми без мереж, без будь-якої файлової системи, крім встановлених rootfs (ніяких sysfs або proc чи tmpfs), і, можливо, деякі вузли пристрою не створюватимуться.
тирса

2
@sawdust: Погоджуюсь. Але питання також було трохи екстремальним ... :-)
Michał Šrajer

2

Це здається, що ви намагаєтесь встановити кіоск . Більшість путівників по Інтернету зосереджуються на такому веб-браузері, як Firefox, як єдиній програмі, яка працює. Погляньте на цей посібник щодо ідей.


2
Хм, я справді просто намагаюся запустити одну програму з мережею. Я не хочу, щоб будь-який X та якомога менше інших програм працювали. Я не бачу, як це обмежує біг усіх непотрібних демонів.
dschatz

чи може програма працювати без X?
Подорожник Geek

2

Ви, звичайно, можете запустити лише одне користувацьке додаток після завантаження ядра. Але це не буде мати 100% процесора, оскільки повинні існувати деякі інші процеси, пов'язані з ядром. Це зазвичай робиться на пристроях із вбудованим Linux, наприклад, бездротовими маршрутизаторами. Я також маю досвід з перших рук, роблячи це для багатопотокової програми.

Після завантаження ядра запускається сценарій ініціалізації або запуску. Читайте про рівень запуску Linux та процес init. У використанні є різні схеми запуску, тому конкретніше неможливо. Але Linux дозволить вам точно налаштувати, які програми та демони виконуватимуть для вашої ситуації. Крім файлу запуску в root, файли, які потребують зміни, знаходяться в / etc , і зокрема /etc/init.d

До речі, якщо ви не суперпрограміст або перед запуском віддаленого сервера GDB, для вашої програми вам знадобиться певна консоль налагодження (або консоль ПК, або послідовний порт). Це дозволить вам отримувати сповіщення про несправності сегмента, помилки шини та збої у твердженнях. Тож плануйте мати ще якийсь "периферійний", окрім "мережевого".


1

Є кілька системних додатків, які потрібно запустити, крім них, звичайно, ви можете присвятити решту комп’ютерних ресурсів цій програмі. Щоб мати мінімальний мінімум, ви можете подивитися на дуже маленькі дистрибутиви Linux, такі як TinyCore Linux тощо.

Також від цього додатка залежатиме і сам додаток, які послуги йому потрібні крім мережі тощо.

Я думаю, якщо ви зможете надати більш конкретну інформацію, ви отримаєте більш детальну відповідь.

Як, що таке додаток тощо


Мій додаток використовує бібліотеку pthread для виконання декількох багатопотокових робочих навантажень (арифметичних операцій) і може бути доручено робити різні обчислення на основі вводу з 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

Якщо ви дійсно не хочете нічого, окрім ядра Linux, мереж та вашої програми, єдиний спосіб зробити це:

  • Вам потрібно буде зробити ваш додаток модулем ядра - переконайтесь, що він налагоджений і добре перевірений. Цей модуль ядра повинен ініціалізувати речі, які зазвичай робляться через користувальницьку область, наприклад, встановити IP-адреси інтерфейсу та все, що добре.
  • Вам потрібно буде завантажити та налаштувати ( make menuconfig) власне власне ядро ​​та видалити всі функції, не пов’язані із запуском системи та мережею. Ви хочете відключити блокування шару, я не знаю, як це зробити на останніх ядрах make menuconfig.
  • Потім потрібно включити ваш модуль до ядра, щоб він включався як частина ядра, а не модуль для завантаження. Ви, ймовірно, відключите завантажувані модулі на кроці вище. Якщо ви знаєте достатньо C / C ++ для створення модуля ядра, це повинно бути для вас просто.
  • Вам потрібно змінити будь-яку частину ядра, яке панікує, якщо цього initне зробити, або бути готовим жити з одним додатковим процесом користувальницького простору.

Я знаю, що можливо, щоб модулі ядра створювали процеси - прості ps auxпоказали б багато в типовій системі (вони всі в дужках). Ви, мабуть, хочете, щоб ваш модуль створив процес ядра. Щоб позбутися від усіх процесів, створених ядром, крім ваших, вам потрібно буде відключити потоки [ kthreadd], управління потужністю [ pm], шар подій [ events] та інші.


Якщо ви хочете більш практичної настройки процесу ядра + 1 в просторі користувача, це можливо.

У Linux є опція командного рядка ядра під назвою init=- це те, що ядро ​​почнеться після завантаження. Програма повинна знаходитись на кореневому пристрої, який вказаний з root=initrd (або завантажений завантажувачем).

Якщо ця програма завершиться, Linux впаде в паніку, тому переконайтеся, що вона ніколи не вийде.

У багатьох сучасних дистрибутивах Linux це налаштовано, тому initпрограма в initrd робить додаткову ініціалізацію простору користувача перед запуском /sbin/initабо /sbin/systemd. Вам доведеться дізнатися, що робить ваш дистрибутив тут (інформація для Debian є тут ) і знайти, де ви можете вказати остаточну програму "handoff", а звідти ви можете сказати їй, щоб запустити свою програму замість initабо systemd.

systemdкерує безліччю основних функціональних можливостей, таких як побудова /dev, встановлення імені хоста та інші речі, тому, якщо ви гнучкі, ви можете замість цього розібратися в налаштуванні systemdдля нерестування одного процесу та, можливо, перезапустити його, якщо він не вдасться. Якщо я не помиляюся, це в основному робить це для однокористувацького або режиму відновлення - він запускає оболонку.

У вас будуть запущені два процеси ( systemdі ваша програма), але система не панікуватиме, якщо програма вийде з ладу або вийде з ладу.

Розглянемо також просто легку установку Debian - установка "netinst" не має нічого іншого, крім ядра, оболонки та декількох служб - або розгляньте OpenWRT / LEDE - у неї є веб-сервер для Luci, який працює за замовчуванням і пару інших послуг, але їх легко відключити.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.