Постройте систему Linux на Raspberry Pi трудным способом


ЦЕЛЕВАЯ АУДИТОРИЯ: Любители Raspberry Pi. Разработчики программного обеспечения без опыта работы со встроенными системами.

ВРЕМЯ ПРОЧИТАНИЯ: О 12 минут, исключая упражнения.

ЦЕЛЬ: Инструкции ниже объяснит, как создать среду Linux для Raspberry Pi 3B с нуля, уделяя особое внимание крайнему минимализму. Я буду собирать большинство компонентов из исходного кода и использовать BusyBox как единственное пользовательское приложение на целевом объекте. Основное внимание уделяется минимализму ради обучения. Оптимизация, такая как сетевая загрузка, вторичные загрузчики, сжатые файловые системы и т. Д., Не рассматривается.

  • Требования к оборудованию
  • Разделите SD-карту на разделы
  • Загрузить BLOB-объекты прошивки
  • Создайте инструментальную цепочку на хост-машине
  • Создайте ядро ​​
  • Копирование ядра и DTB в корневой раздел
  • Настроить ядро ​​и загрузчик
  • Создать локальный каталог для корневой файловой системы
  • Установить модули ядра
  • Загрузить BusyBox
  • Настроить BusyBox
  • Сборка BusyBox
  • Корневая файловая система, часть II
  • Включите и изучите приглашение оболочки
  • Следующие шаги
  • Ключевые термины

ЗАГРУЗЧИК ЗАГРУЗКИ : программа для конкретной платформы, которая запускается до загрузки операционной системы. Он отвечает за аппаратную инициализацию и загрузку ядра ОС в память.

BOOT PARTITION : раздел диска, который используется загрузчиком.

BUSYBOX : отдельное приложение Linux, которое имитирует множество общих системных утилит, таких как cp , ls , mv и т. д. Часто используется во встроенных системах.

КОНФИГУРАЦИЯ ЯДРА ПО УМОЛЧАНИЮ : набор параметров по умолчанию, которые применяется к ядру Linux, когда оно скомпилировано разработчиком из исходного кода.

BLOBS ДЕРЕВА УСТРОЙСТВА : двоичный формат, используемый для описания схемы устройства машины. Эта информация используется ядром Linux (и его драйверами устройств) для поддержки оборудования, зависящего от платформы.

НАЛОЖЕНИЕ ДЕРЕВА УСТРОЙСТВ : Фрагменты дерева устройств, которые изменяют большой двоичный объект ДЕРЕВА УСТРОЙСТВ. Обычно они используются для внесения небольших изменений или дополнений в большой двоичный объект ДЕРЕВА УСТРОЙСТВА.

HOST MACHINE : Во встроенных системах HOST MACHINE - это компьютер, используемый для разработки программного обеспечения, который не является конечным продуктом деятельности по разработке программного обеспечения.

МОДУЛИ ЯДРА : Код, который можно загружать и выгружать из ядра во время выполнения. Они добавляют ядру функциональные возможности (часто для управления оборудованием) без необходимости перезагружать систему или изменять само ядро.

LINUX KERNEL : отвечает за управление аппаратным обеспечением и ресурсами системы, а также за предоставление услуг для приложений пользовательского пространства. Загружается ЗАГРУЗЧИКОМ при запуске системы.

INIT : Первая программа, загружаемая ядром Linux при запуске.

КОМАНДНАЯ СТРОКА ЯДРА LINUX. : набор параметров, которые передаются ядру Linux при его загрузке. Он часто содержит информацию о том, как загрузить корневую файловую систему.

ROOT FILESYSTEM : серия каталогов, содержащих основные приложения (например, init и оболочка), а также конфигурацию системы.

ЦЕЛЕВАЯ МАШИНА : Встроенное устройство, которое является конечным продуктом разработки встроенных систем. См. Также: HOST MACHINE.

USB TTL КАБЕЛЬ : Кабель, который позволяет получить доступ к системной оболочке Raspberry Pi без необходимости подключения клавиатуры и монитора. Для этого урока требуется оборудование. Они очень недорогие.

Вам понадобятся:

  • Микро SD-карта размером более 2 гигабайт
  • Устройство для чтения карт micro SD
  • Raspberry Pi 3b («целевая машина»)
  • X 95 - настольный компьютер на базе Ubuntu ( «Хост-машина»)
  • A Последовательный кабель USB TTL

В этом разделе потребуется создать два раздела на пустой SD-карте:

  1. ЖИР 20 загрузочный раздел не менее 54 МБ
  2. An E Раздел корневой файловой системы XT4 размером не менее 1 ГБ

Загрузочный раздел со временем будет содержать большие двоичные объекты встроенного ПО, капли дерева устройств, ядро ​​Linux и два файла конфигурации.

корневая файловая система будет содержать модули ядра и программы пользовательского пространства (такие как ls , кот и т. д.).

Я рекомендую использовать gparted для разбиения. Вот небольшой скринкаст, объясняющий, как выполнить это действие в GParted:

Наша цель - построить всю систему Linux. Прежде чем мы сможем загрузить ядро, необходимо инициализировать оборудование. За инициализацию оборудования отвечает «загрузчик» - специфичный для платформы код, который запускается до того, как ядро ​​Linux будет загружено в память. Каждая платформа обрабатывает процесс загрузки по-разному. В Raspberry Pi 3b мы должны загрузить три файла и поместить их в загрузочный раздел (FAT 27) SD-карты. Эти файлы не являются открытыми, поэтому мы не можем скомпилировать их самостоятельно.

Все файлы доступны в репозиторий прошивок Raspberry Pi . Я не буду подробно обсуждать тему загрузчиков. Вы можете прочитать больше о конфигурации загрузки в официальной документации .

Прежде чем продолжить, добавьте следующие файлы в FAT 27 (загрузочный) раздел вашей SD-карты:

На этом этапе у вас должна быть SD-карта с разделом EXT4 и FAT 27 загрузочный раздел. Загрузочный раздел должен содержать три проприетарных BLOB-объекта, перечисленных в предыдущем разделе.

Установив загрузчик, мы готовы скомпилировать Linux. ядро из исходного кода. Для компиляции ядра Linux требуется GCC, компилятор языка C . Также требуются двоичные утилиты («binutils») для работы с файлами языка ассемблера .

Возможно, на вашем хост-компьютере уже установлены GCC и Binutils, но есть проблема - компилятор на хост-машине выдает x 315 двоичные файлы. Raspberry Pi использует совершенно другой набор инструкций ARM. Чтобы создать двоичный файл, который может выполнять RPi, нам нужен компилятор, который выдает инструкции ARM, а не x 315. Несомненно, мы могли бы установить Raspberry Pi OS (https://www.raspberrypi.org/software program/) и выполнить компиляцию ядра на целевом устройстве. Однако это был бы длительный процесс. Для сравнения у меня 14 Ноутбук Core i7 поколения с 8 физическими ядрами, 8 ГБ ОЗУ и твердотельным накопителем. Компиляция ядра Linux заняла примерно 32 минут на этом компьютере , что по-прежнему довольно много времени. Компиляция на Raspberry Pi займет еще больше времени.

Лучший способ скомпилировать ядро ​​Raspberry Pi Linux - это «кросс-компиляция» через «Кросс-компилятор». Кросс-компилятор - это компилятор, который работает с одним набором инструкций, но выводит исходный код в совершенно другом наборе инструкций, чем целевой. В нашем случае нам нужен компилятор, работающий на x 315 машина, но которая выдает ARM инструкции, понятные RPi.

  
 # Устанавливает компилятор `arm-linux-gnueabihf- *`, компоновщик, так далее..  sudo  apt  установить  bc bison crossbuild-essential-armhf flex git libc6-dev libncurses5-dev libssl-dev  

После запуска выше, наша машина будет иметь новый набор инструментов:

Эквивалент кросс-компилятора Компилятор

gcc

arm-Linux-gnueabihf-gcc

Вы видите узор? На следующем шаге мы установим переменную среды CROSS_COMPILE , чтобы приложения будет компилироваться через arm-Linux-gnueabihf-gcc , а не через собственный gcc . Обычно кросс-компилятор предлагает весь собственный компилятор и исполняемые файлы Binutils, такие как gcc и ld . Однако он будет делать это с префиксом, обозначающим целевую архитектуру. В нашем случае префикс arm-Linux-gnueabihf - .

Если вы хотите создать собственный набор инструментов или создать набор инструментов из исходного кода, посмотрите на

Какие? Родной инструмент

Линкер ld

arm-Linux-gnueabihf-ld

Ассемблер в виде arm-Linux-gnueabihf-as

Crosstool-NG . Это более продвинутый способ создания кросс-компиляторов.

Теперь, когда у нас есть рабочий набор инструментов, нам нужно найти последний исходный код ядра Linux и скомпилируйте его.

Прежде чем продолжить, нам нужно установить некоторые переменные среды. Вы должны экспортировать эти переменные при выполнении всех шагов.

 # ==== ПОЛЬЗОВАТЕЛИ BASH:   # Установите архитектуру на ARM:  
 экспорт   АРКА   знак равно рука  # Мы хотим использовать ARM v7:  
 экспорт  
 ЯДРО   знак равно  kernel7 
 # Установите префикс кросс-компилятора (объяснено в предыдущий раздел):   экспорт  
 CROSS_COMPILE  знак равно  arm-linux-gnueabihf-  # ==== ПОЛЬЗОВАТЕЛИ РЫБЫ:   # установить -x ЯДРО kernel7  
 # set -x ARCH arm   # set -x CROSS_COMPILE arm-linux-gnueabihf - 
  

Raspberry Pi фонд управляет

собственная версия ядра . Мы будем клонировать исходный код с помощью Git:

  
 # Клонировать ядро ​​Raspberry Pi Linux  git clone --глубина знак равно  1 https://github.com/raspberrypi/linux CD  linux  

Затем мы должны применить конфигурацию по умолчанию для системы сборки на основе целевого устройства (RPi3b, который использует BCM 56075 чипсет):

  
 # Применить конфигурацию по умолчанию для RPi3  сделать bcm 2710 _ defconfig  

Некоторые пользователи захотят изменить значение по умолчанию. конфигурация ядра. Вы можете сделать это с помощью make menuconfig , хотя в нашем вариант использования.

Мы готовы скомпилировать ядро, но нам нужно определить, сколько ядер ЦП имеет наш хост-компьютер, прежде чем мы это сделаем. Эта информация необходима нам для включения параллельной компиляции, которая может существенно сократить время компиляции. Выполните следующие шаги:

  1. Определите количество ядер ЦП на вашем компьютере по сравнению с lscpu .
  2. Умножьте число из шага 1 на 1,5.
  3. Передайте этот номер в - j на следующем шаге.

Обратите внимание, что я использовал - j 20 в примере ниже. Вашему аппарату может потребоваться другое - j значение!

   # Скомпилируйте собственное ядро, модули, DTB   # Принимает ~ 32 минут на современном i7 с SSD  делать  - j 14  zImage модули dtbs   

Сейчас отличное время, чтобы сделать перерыв. Компиляция ядра занимает некоторое время.

На предыдущем шаге было создано несколько необходимых файлов:

  • zImage - сжатое двоичное ядро ​​Linux.
  • BLOB-объекты дерева устройств ( DTBs) - метаданные, необходимые Linux для поиска физического оборудования
  • Device Tree Overlays - модификации и дополнения к ядру DTBs

Нам нужно переместить эти типы файлов в жир20 загрузочный раздел, ранее созданный в определенном

Сначала найдите расположение загрузочного раздела (FAT 27) созданный ранее. На моей машине путь / media / rick / rpi_boot . На вашем устройстве все будет иначе. Он будет находиться в том же месте, что и bootcode.bin , fixup.dat , start.elf файлы, которые мы скачали ранее.

В загрузочном разделе создайте новую папку с именем overlays / в корневой уровень:

mkdir / media / rick / rpi_boot / overlays

Затем запустите следующее в linux / исходный каталог предыдущего раздела:

cp arch / arm / boot / zImage / media / rick / rpi_boot cp arch / рука / загрузка / dts / bcm 115200 - rpi-3-b.dtb / media / rick / rpi_boot cp arch / arm / boot / dts / overlays / disable-bt.dtbo / media / rick / rpi_boot / overlays

Raspberry Pi использует config.txt файл для настройки загрузчика.

Ты можешь подробнее о вариантах читайте здесь

Создайте файл config.txt в загрузочном (FAT 27) следующим образом:

 # Используйте ядро ​​Linux, которое мы скомпилировали ранее.   ядро ​​ ( знак равно  zImage  # Включите UART, чтобы мы могли использовать кабель TTL.  
 enable_uart   =  1 
 # Используйте соответствующий DTB для нашего устройства.   дерево_устройств   знак равно  млрд куб. м 56075 - rpi-3-b.dtb 
 # Отключить Bluetooth через наложение дерева устройств.   # Это сложное объяснение, которое вы   # можно прочитать здесь: https://youtu.be/95 jbiuf 33 AY? T = 2009  
 # ЕСЛИ ВЫ пропустите этот шаг, ваше последовательное соединение будет нет  # работают правильно.   dtoverlay   =  отключить -bt   

Далее нам нужно отредактировать командная строка Linux .

Raspberry Pi получит командную строку ядра. из cmdline.txt. Как и config.txt, он находится в загрузочном разделе (FAT 27):

Создайте cmdline.txt следующим образом и сохраните его в загрузочном разделе:

  console = tty1 console = serial0, 536592 root = / dev / mmcblk0p2 rootfstype = ext4 rootwait   

Теперь, когда ядро ​​Linux построено и загрузчик настроен, нам нужно переключить наше внимание на создание корневой файловой системы. В корневой файловой системе Linux ожидает найти исполняемые файлы, модули ядра, системные файлы и многое другое. Макет указан как Стандарт иерархии файловой системы Linux

Мы создадим корневую файловую систему в каталоге на нашей хост-машине. Позже мы скопируем окончательную структуру каталогов в раздел EXT4, который мы создали в начале руководства.

Я назову этот каталог root_fs :

Используйте pwd , чтобы определить абсолютный путь к этому каталог. Держите эту информацию под рукой; он понадобится нам в несколько этапов.

Первое, что мы поместим в корневую файловую систему, - это модули ядра, которые были скомпилированы вместе с ядром Linux. на предыдущем шаге.

cd обратно в каталог, где находится Linux исходный код был, но оставьте абсолютный путь к вашему root_fs удобный каталог.

Нам нужно установить УСТАНОВИТЬ MOD Переменная среды PATH к абсолютному пути из root_fs :

   экспорт  
 INSTALL_MOD_PATH   знак равно   / home / rick / linux_root  # Пользователи Fish Shell:   # set -x I  NSTALL_MOD_PATH / home / rick / linux_root   

После этого, cd в исходный каталог Linux и запустите:

   # Может потребоваться `sudo`:  make modules_install  

После этого шага вы найдете множество *. Ko файлы, установленные в вашем root_fs / каталог.

Теперь модули установлены в корневой файловой системе. Однако модулей недостаточно для работы системы Linux. Нам нужны все обычные инструменты, имеющиеся в системе Linux, например ls , CD, cp и друзья.

Вместо компилируйте каждый инструмент индивидуально, мы статически скомпилируем BusyBox . BusyBox позиционирует себя как «швейцарский армейский нож для встраиваемого Linux». Это один исполняемый файл, который выполняет несколько функций в зависимости от того, как загружен исполняемый файл. Например, мы можем создать символическую ссылку из BusyBox на / bin / echo . Когда мы выполняем

/ bin / echo , BusyBox отметит символическое имя ссылки. и запустите, как ожидалось, команду echo . BusyBox реализует все основные утилиты командной строки Linux, такие как cd и ls . Он также поставляется с дополнительными функциями, такими как облегченный HTTP-сервер и текстовый редактор.

Давайте клонируем локальную копию BusyBox и проверяем версию 1. 61. 0:

  git clone git: //busybox.internet/busybox.git --branch = 1_ 68 _ 0 --depth = 1 cd BusyBox   

Как только у нас будет исходный код на нашем хост-машине, нам нужно настроить некоторые параметры из menuconfig :

Установите следующие параметры:

Местоположение настройки Настройки -> Префикс кросс-компилятора arm-Linux-gnueabihf -

То же, что и INSTALL_MOD_PATH из шага модулей ядра

Мы готовы скомпилировать BusyBox.

   # Ваше значение -j будет другим.   # Обычно я использую в 1,5 раза больше физических ядер ЦП.  делать  - j 16 делать установить  

BusyBox теперь установлен в ../ root_fs . Вы должны увидеть много символических ссылок в bin / , sbin / и usr / каталог вашей корневой файловой системы ( $ INSTALL_MOD_PATH ).

BusyBox недостаточно для загрузки системы Linux. Нам еще нужно добавить:

Запустите фол команды вывода в / root_fs :

  # Создайте каталоги для монтирования вещей: mkdir proc mkdir sys mkdir dev mkdir и т. Д. # Создать каталог конфигурации: mkdir and many others / init.d # Создать пустой файл `rcS`.  коснитесь and many others / init.d / rcS  

Сделать rcS исполняемым файлом (Linux выполнит этот сценарий во время загрузки):

Добавьте следующие записи в и т.д. / init.d / rcS :

   #! / bin / sh  mount  - т  proc none / proc mount  - t  sysfs none / sys  эхо  / sbin / mdev 
>  / proc / sys / kernel / hotplug mdev 
 - s   

Приведенные выше записи будут монтировать sysfs и procfs во время загрузки.

Мы готовы к загрузке системы.

Не используйте монитор - требуется кабель USB TTL! Если у вас нет такого монитора. кабель, вы можете купить его за несколько долларов на Amazon. Это изменит вашу жизнь как энтузиаста Raspberry Pi, поверьте мне.

После включения вы должны увидеть, как несколько сообщений ядра прокручиваются и, в конце концов, приглашение оболочки.

# ... Для ясности сокращено ... usb 1-1.1: новое высокоскоростное USB-устройство номер 3 с использованием dwc_otg [ 4.666906] usb 1-1.1: найдено новое USB-устройство, idVendor = 560, idProduct = ec 10, bcdDevice = 2. 10 [ 4.680733] usb 1-1.1: Новые строки USB-устройства: Mfr = 0, Product = 0, SerialNumber = 0 [ 4.693829] smsc 431 xx v1.0.6 [ 4.791032] smsc 0424 xx 1-1.1: 1.0 eth0: register 'smsc 0424 xx 'на usb-3f

. usb-1.1, smsc 0424 xx USB 2.0 Ethernet, b8: 54: eb: 61: 86: ef Нажмите Enter, чтобы активировать эту консоль. / # echo "Привет, мир Linux." Привет, мир Linux.

Теперь у нас есть рабочий корневой раздел Linux и загрузочный раздел. Скопируйте каталог root_fs / на SD-карту и попытайтесь загрузить устройство. .

Система Linux, представленная в этой статье, не очень полезна, но, надеюсь, она дает вам лучшее представление о том, как дистрибутивы Linux и встроенный Linux системы построены. Не стесняйтесь обращаться ко мне на Reddit или Lobste.rs с отзывами.

Leave a comment

Your email address will not be published. Required fields are marked *

10 − two =

Значение настройки
Настройки -> Создать статический двоичный файл (без общих библиотек) Давать возможность
Настройки -> Путь назначения для 'make set up'