- 6 шагов загрузки Linux на пальцах
- 1. BIOS
- 2. MBR
- 3. GRUB
- 4. Ядро или Kernel
- 5. Init
- 6. Уровень выполнения программ (Runlevel)
- Дополнения, исправления, уточнения
- Google Plus прекращает работу. И что?
- accounts и userID
- Возьмём пример поглощения внешнего сервиса компанией Google
- proof of concept
- Как эта дыра возможность связана с закрытием G+? Выводы
- Embedded Linux в двух словах. Первое
- Das U-Boot
- ARM Toolchain
- Ядро Linux
- Корневая файловая система. BusyBox
6 шагов загрузки Linux на пальцах
Нажмите кнопку включения питания на вашем системнике, и спустя несколько секунд вы увидите окно входа в систему.
Посмею предположить, что каждого интересовало хоть когда-либо то, что происходит за занавесом заставок и загрузочных экранов с момента включения питания компьютера к моменту, когда предлагается войти в систему.
Я предлагаю вам познакомиться со следующими уровнями типичной загрузки Linux:
1. BIOS
2. MBR
3. GRUB
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.18-194.el5PAE)
root (hd0,0)
kernel /boot/vmlinuz-2.6.18-194.el5PAE ro root=LABEL=/
initrd /boot/initrd-2.6.18-194.el5PAE.img
4. Ядро или Kernel
5. Init
6. Уровень выполнения программ (Runlevel)
- Когда Линукс выполняет свою загрузку, вы можете наблюдать загрузку различных служб. К примеру, это могут быть сообщения типа «starting Postfix … OK» (запускается Postfix). Эти службы — и называются программами уровня выполнения, выполняемые из директории, которая соответствует нужному уровню выполнения.
- Исходя из настроек по умолчанию, система будет выполнять файлы в соответствии с нижеприведенными директориями.
- Выполнение уровня 0 – /etc/rc.d/rc0.d/
- Выполнение уровня 1 – /etc/rc.d/rc1.d/
- Выполнение уровня 2 – /etc/rc.d/rc2.d/
- Выполнение уровня 3 – /etc/rc.d/rc3.d/
- Выполнение уровня 4 – /etc/rc.d/rc4.d/
- Выполнение уровня 5 – /etc/rc.d/rc5.d/
- Выполнение уровня 6 – /etc/rc.d/rc6.d/
- Но имейте ввиду, что еще в каталоге /etc могут быть символические ссылки. Например, /etc/rc0.d залинкован на /etc/rc.d/rc0.d.
- В каталогах /etc/rc.d/rc*.d/ вы можете увидеть список программ, имя которых начинается из букв S и K.
- Программы, начинающиеся на S используются для запуска. S, потому что startup.
- Программы, которые начинаются с литеры K используются — правильно — для завершения работы. K, потому что kill.
- Еще есть номера рядом с буквами S и K в именах программ. Эти номера используются для определения порядка запуска этих программ.
- К примеру, S12syslog предназначен для запуска демона syslog, его порядковый номер 12. S80sendmail — для запуска демона sendmail, имеющего порядковый номер 80. Таким образом, программа syslog будет запущена перед sendmail.
Вот и все. Возможно, некоторым из вас это не ново и особого интереса не было при чтении статью, поскольку она более ориентирована на начально-средний уровень знакомства з Линуксом.
В таком случае могу лишь сказать, что «повторение — мать учения» (с).
Дополнения, исправления, уточнения
В комментариях неоднократно было апеллировано к тексту статьи, поэтому, думаю, стоит учесть некоторые важные комментарии хабрасообщества. (спасибо artemlight, 3al, Tishka17, HhyperH, Next_Alex, Ilya_Shmelykh, Aux, soomrack, Xpeh )
- artemlight:: «Ну скажем прямо — так грузятся далеко не все дистры». С ним согласилось большинство, отмечая и bsd-style init, u-boot, и хоть initrd в статье пропущен, стоить заметить, что он нужен ядру не во всех дистрибутивах. Также отмечено, что в slackware поддержка rc.d осуществляется только в качестве совместимости, а встраиваемые системы грузятся иначе. На декстопах иногда бывает EFI, а кроме того Linux популярен в мире embedded и там ещё куча разных платформ. Линукс в телефоне вообще иначе грузится.
- soomrack, ссылая на википедию: Еще хочется сделать замечание по поводу MBR, первого сектора и пр. Все несколько усложнилось за последние годы. Сейчас уместней говорить о EFI.
Источник
Google Plus прекращает работу. И что?
Google объявила о закрытии социальной сети Google+. Трудно найти техническое издание, которое бы не упомянуло хотя бы вскользь о конце амбиций Google в области социальных сетей. Но, увы, вниманием обходится высокая связность сервисов компании добра. В этой статье я хотел бы выразить свои размышления на тему того, как взаимодействуют сервисы гугла внутри и что может означать закрытие G+ для пользователей API сервисов Google.
Для конечного пользователя переход от Gmail в Photos, а оттуда в Docs должен быть максимально бесшовным — с первого взгляда сервисы независимы и объединены единым, отполированным до блеска сервисом-точкой входа Single Sign-On accounts.google.com. Но мы как разработчики знаем, что слова «закрыть», «поглотить», «интегрировать» несут за собой больше смысла (и больше работы) для людей, которые занимаются разработкой продукта, чем может показаться на первый взгляд. Разберём поверхностно, как устроен процесс поглощения гуглом одного из внешних сервисов и что происходит с API сервиса и API Google.
accounts и userID
Помимо пользователей, которые пользуются Gmail и иногда догадывались о существовании Google Plus, есть ещё и огромное количество API для разработчиков, которые пронизаны насквозь такими понятиями, как идентификатор аккаунта, пресловутый userID. userID — это внутренний идентификатор Google, именно та вещь, которая даёт сервисам Google понять, кто есть кто, и является тем самым, что связывает все внутренние сервисы между собой. Он появляется во многих API, и мы видим, что он неизменен от сервиса к сервису.
Возьмём пример поглощения внешнего сервиса компанией Google
Очевидно, что для имплементации SSO в только что поглощённом сервисе нельзя просто взять и перенести аккаунты из старой базы в новую «базу аккаунтов Google» — думаю, просто не существует такого понятия, — есть множество переплетённых между собой сервисов, уровней взаимодействия, цепочек ответственности, сервисов по управлению сервисами. Серьёзно, если задуматься, то должно быть много, много, очень много уровней связей между сервисами Google для того, чтобы всё работало.
Но дальше всё идёт не так гладко — в стремлении к популяризации G+ она использовала userID пользователей, которые являются частью глобального SSO сервиса.
Вернёмся к тезису. Возникает потребность внести правки в существующий API со стороны как поглощаемой стороны API, так и со стороны других сервисов, которые теперь могут начать работать с новым сервисом. Казалось бы, ничего сверхсложного — адаптировать существующую базу пользователей сервиса к «общегугловским» сервисам, создать точки взаимодействия с другими сервисами, чтобы они могли использовать новый сервис для своих целей. Но речь идёт не о маленьких проектах — корпорация добра не мелочится и поглощает многомиллионные компании, у которых, вполне вероятно, уже налажена инфраструктура — иначе они не смогли бы вырасти до своих масштабов. Значит, имеет смысл оставить его кодовую базу, вернее, ядро сервиса, и переделать input-output каналы связей сервиса, чтобы они стали совместимыми с гугловскими.
Далее сервис становится сервисом Google. Допустим, что на этот момент он уже оттестирован и считается достаточно благонадёжным людьми из Google, отвечающими за интеграцию. Начинается самое интересное — сервис можно интегрировать в другие сервисы и/или переносить из сервиса в сервис.
В целом это не было бы страшно, если бы не тенденция гугла менять прописку сервисов.
Возьмём к примеру фотографии.
Picasa десктоп приложение (2002) => Picasa Web Albums — Google приобретает Picasa (2004) => Google Plus инкорпорирует Picasa (2011) => Google Photos отделяется от G+ (2015) => .
Учитывая инертность процессов интеграции, в большинстве продуктов Google до сих пор поддерживает весьма старые API. На момент публикации статьи до сих пор работает API Picasa с тех времён, когда Picasa была отдельным продуктом. То есть мы приходим к выводу, что, когда Google интегрировала Picasa с очередным своим сервисом, она «создавала branch» от оригинала и оставляла на произвол судьбы старый «бранч», но не закрывала его API.
И тут самое время вспомнить о причине закрытия G+. Заявлено о проблемах с безопасностью, на самом же деле вероятных проблем с безопасностью может быть ещё больше, в связи с неконсистентностью разных API.
proof of concept
К примеру, когда-то был сервис PicasaWeb, такой себе предок современных Google Photos. Его выключили ещё в 2016-м году. Но согласно приписке в конце поста — API сервиса продолжило свою работу аж до сих пор. Уже есть конечная дата работы этого API — 15 марта 2019. Этот сервис примечателен тем, что позволял получить соответствие емейла и внутреннего userID. Как нам это может быть полезно?
Например, мы сервис верификации емейлов. В этом случае это API для нас просто манна небесная. Мы, зная Google Account ID из G+, можем получить имя пользователя, фотографию и часто разнообразную дополнительную информацию. Вопрос в том, что обычно узнать userID человека невозможно, если он, к примеру, не залогинится у нас на сайте.
Но в старом PicasaWebAlbums люди могли публиковать фото в веб-альбомах, которые привязывались к емейлу. Собственно, из этого следует вывод, что старое API позволяет получить профиль человека по userID или email пользователя.
Давайте проверим:
https://picasaweb.google.com/data/feed/api/user/nosov@nodeart.io?deprecation-extension=true
— https://picasaweb.google.com/data/feed/api/user/ — собственно ендпоинт, на котором живёт API;
— nosov@nodeart.io — емейл пользователя для проверки, как мы видим, не обязательно тут должен быть gmail. Профили есть у пользователей Google Apps (что делает подобную проверку очень полезной для лидогенерации), а так же у людей, которые создали себе профиль в Google+, привязав к нему персональный ящик третьего сервиса, к примеру, Yandex.ru;
— deprecation-extension=true — указание о том что мы знаем о скором конце API.
Если мы попробуем передать несуществующий емейл, то получим вполне ясно интерпретируемый ответ Unable to find user with email noname@nodeart.io, из которого однозначно можно прийти к выводу, что такого емейла нет. И даже более — если мы попробуем отправить в API адрес группы рассылки, то ответ изменится на Unknown user. Таким образом можно отличить персональные ящики в G Suite от корпоративных ящиков пересыльщиков.
Нельзя сказать, что так можно вытащить персональную информацию человека, если он явно её не опубликовал, но для массовой валидации списков рассылки такое API было очень даже уместно
Как эта дыра возможность связана с закрытием G+? Выводы
Google называет основной причиной закрытия G+ проблемы безопасности, точнее, возможность сторонним сервисам получать информацию из G+ путями, не совсем предназначенными и запланированными изначально самим Google.
Сейчас, кроме закрытия G+, происходит частичное закрытие разных API. Например, для доступа к gmail.api теперь нужно проходить платный аудит стоимостью от 15 до 75к USD, что делает это API недоступным для большинства разработчиков. Цитата:
The assessment fee is paid by the developer and may range from $15,000 to $75,000 (or more) depending on the size and complexity of the application.
По факту, это даёт нам повод подумать, что Google запутался в системе взаимодействия между сервисами, раз для того, чтобы те действия, которые раньше было можно совершать, просто получив нужный scope, теперь требуют ручной валидации за 15–75k USD и ручного включения в whitelist. Остаётся только догадываться, что ещё можно делать, используя недокументированные фичи более чем богатой на сервисы экосистемы Google и сервиса SSO в частности.
Для того, чтобы качественно валидировать списки рассылки, нам по прежнему нужно будет искать новые нестандартные применения публичных API, поэтому мы продолжим изучать API Google\Facebook и других сервисов. (Кстати, у Facebook до недавнего времени был схожий способ валидации емейлов.)
Источник
Embedded Linux в двух словах. Первое
В этой небольшой серии статей я попытаюсь пролить свет на тему построения Embedded Linux устройств, начиная от сборки загрузчика и до написания драйвера под отдельно разработанный внешний модуль с автоматизацией всех промежуточных процессов.
Платформой послужит плата BeagleBone Black с процессором производства Техасских Инструментов AM3358 и ядром Arm Cortex-A8, и, чтобы не плодить мигающие светодиодами мануалы, основной задачей устройства будет отправка смайлов в топовый чат, широко известного в узких кругах, сайта, в соответствии с командами от смайл-пульта. Впрочем, без мигания светодиодами тоже не обошлось.
Итак, на столе лежит чистая, т.е. без каких-либо предустановленных дистрибутивов, плата BeagleBone Black, блок питания, переходник USB-UART. Для общения с платой, переходник нужно подключить к 6-ти выводному разъему, где первый вывод обозначен точкой — это GND, выводы 4/5 — RX/TX соответственно. После установки скорости в какой-либо терминальной программе, например putty, на 115200, можно взаимодействовать с платой, о подключении подробнее и с картинками здесь.
Топовые чаты, пульты и светодиоды будут позже, а сейчас на плату подается питание и плата отвечает CCCCCCCCCCC
В переводе с бутлоадерского это означает, что первичному загрузчику, зашитому в ROM процессора, нечего загружать. Ситуацию проясняет Reference Manual, где на странице 5025 в разделе 26.1.5 описана процедура начальной загрузки. Процедура такая: первичный загрузчик проводит некоторую инициализацию: тактирование процессора, необходимой периферии, того же UART, и, в зависимости от логических уровней на выводах SYSBOOT, строит приоритетный список источников где можно взять следующий загрузчик, т.е. посмотреть сначала на MMC карте, SPI-EEPROM или сразу ждать данных по Ethernet.
Я использую способ загрузки с помощью SD карты, вот что говорит об этом раздел RM 26.1.8.5.5 на странице 5057: первичный загрузчик сначала проверяет несколько адресов 0x0/ 0x20000/ 0x40000/ 0x60000 на наличие так называемой TOC структуры, по которой он может определить загрузочный код, если так код не найти, то первичный загрузчик, предполагая на SD карте наличие файловой системы FAT, будет искать там файл с названием MLO, как это расшифровывается в RM не сказано, но многие склоняются что Master LOader. Возникает резонный вопрос, где же взять этот MLO?
Das U-Boot
Das U-Boot или просто U-Boot — Universal Boot Loader, один из самых, если не самый, распространенный загрузчик для встроенных систем, именно с его помощью можно создать требуемый вторичный загрузчик (MLO), который будет загружать третичный загрузчик (сам U-Boot), который будет загружать ядро Linux.
Перед скачиванием U-Boot, стоит сходить в репозиторий и найти тег последней версии, далее
U-Boot содержит больше тысячи конфигураций, в том числе нужную:
Это конфигурация платы AM335x evaluation module, этот модуль лежит в основе других плат, в том числе BeagleBone Black, что можно видеть, к примеру, по Device Tree, но о нем позже. Настраивается и собирается U-Boot с помощью Kconfig, то же, что используется и при сборке ядра Linux.
Установка нужного конфига:
Можно, к примеру, убрать, установленную по умолчанию, 2-х секундную задержку при загрузке платы с U-Boot
Boot options —> Autoboot options —> (0) delay in seconds before automatically booting
В вышеуказанных командах, используется компилятор по умолчанию, если таковой в системе установлен, и, скорее всего, он не подходит для ARM процессоров, и здесь пора упомянуть о кросскомпиляции.
ARM Toolchain
Один из видов кросскомпиляции это сборка на одной архитектуре, как правило x86-64, именуемой HOST, исходного кода для другой, именуемой TARGET. Например, для TARGET архитектуры ARMv7-A, ядра ARM CortexA-8 процессора AM3358, платы BeagleBone Black. К слову, чтобы не запутаться в ARM’ах, даже есть свой справочник, так их много и разных.
Сама сборка осуществляется набором инструментов — компилятор, компоновщик, runtime библиотеки, заголовочные файлы ядра; так называемый Toolchain. Toolchain можно собрать самостоятельно либо с помощью crosstool-NG, а можно взять готовый от компании Linaro, или самой ARM. Здесь я буду использовать Toolchain от ARM “GNU Toolchain for the A-profile Architecture Version 10.2-2020.11, x86_64 Linux hosted cross compilers, AArch32 target with hard float (arm-linux-none-gnueabihf)», если не вдаваться в излишние подробности, то это все означает, что набор инструментов будет работать на десктопной машине с Linux и собирать программы для 32-х битной ARM платформы с аппаратной поддержкой операций с плавающей запятой.
Теперь для успешной сборки U-Boot, нужно указать в переменных ARCH и CROSS_COMPILE требуемые архитектуру и путь к кросскомпилятору соответственно, например так
Либо использовать export ARCH/CROSS_COMPILE , чтобы каждый раз не набирать все это. Я, для наглядности, буду каждый раз набирать все это.
После сборки U-Boot, в папке появятся необходимые файлы, а именно
MLO — вторичный загрузчик (напомню, первичный зашит в самом процессоре)
u-boot.img — третичный загрузчик, собственно U-Boot
Для успешной загрузки с SD карты, нужно ее некоторым образом разметить. Карта должна содержать минимум два раздела, первый, отмеченный как BOOT, с файловой системой FAT, второй раздел с ext4. Разметить карту можно, к примеру, программой fdisk.
Теперь нужно просто скопировать результаты сборки U-Boot в FAT раздел, вставить карту в BeagleBone Black и в терминале наблюдать уже более осознанный ответ платы
В ответе платы есть такие строки
Failed to load ‘boot.scr’
Failed to load ‘uEnv.txt’
U-Boot, во время загрузки, смотрит наличие дополнительных команд, сначала в файле boot.scr, при его наличии, затем, если boot.scr не нашлось, в uEnv.txt. Эти файлы, помимо очередности при поиске, отличаются тем, что в файле uEnv.txt, дополнительные команды представлены в текстовом виде, т.е. он проще для восприятия и редактирования. U-Boot не создает файлы с дополнительными командами, делать это нужно самостоятельно.
Здесь происходят некоторые манипуляции в результате которых U-Boot загружает из SD карты в RAM по адресу [loadaddr] — образ ядра [zImage], и по адресу [fdtaddr] — дерево устройств [Flattened Device Tree]. Формируются аргументы, передаваемые ядру Linux, это параметры консоли, к которой подключен переходник USB-UART [console=ttyS0,115200n8], место размещения корневой файловой системы [bootpartition=mmcblk0p2], параметры разрешения на чтение/запись корневой файловой системы [rw], ее тип [ext4] и ожидание появления корневой файловой системы [rootwait]. Чтобы раскрутить всю цепочку действий U-Boot, можно, после того как U-Boot прекратит попытки найти что бы загрузить и выдаст приглашение на работу в виде =>, ввести команду printenv , она покажет значения всех переменных, которыми располагает U-Boot.
В завершении своей работы U-Boot, командой bootz , вместе с вышеуказанными аргументами и адресом дерева устройств, передает управление ядру Linux.
Ядро Linux
Прежде чем приступать к любым действиям с ядром, стоит заглянуть сюда и убедится в наличии необходимых пакетов. Следующим шагом нужно определиться с тем, какую версию ядра использовать. Здесь я использую версию 5.4.92 и вот по каким соображениям. Одной из основных причин того, что не стоит брать просто последнюю версию ядра, доступную на данный момент, наряду с наличием драйверов, является невозможность быстро протестировать это ядро на всем разнообразии платформ поддерживаемых Linux, а значит можно потратить кучу сил и времени на исправление неполадок, если что-то пойдет не так, и не факт что это вообще получится сделать. BeagleBone Black имеет официальный репозиторий, где можно найти версию ядра, протестированную на данной платформе, и long term версия 5.4.92 была последней на тот момент.
Нужный конфиг, расположенный в /arch/arm/configs, называется omap2plus_defconfig, OMAP — это название линейки процессоров, продолжением которых является AM3358, впринципе, подойдет и более общий multi_v7_defconfig.
Сам конфиг пока остается без изменений, поэтому можно просто его установить и запустить компиляцию ядра(zImage), модулей(modules) и дерева устройств(dtbs)
Проходит некоторое время.
Результат сборки, в виде zImage, находится в /arch/arm/boot, там же в папке /dts находится скомпилированное дерево устройств am335x-boneblack.dtb, оба отправляются на SD карту к файлам загрузчика. На этом FAT раздел SD карты можно считать скомплектованным. Итого, там присутствуют:
MLO — вторичный загрузчик
u-boot.img — третичный загрузчик
uEnv.txt — дополнительные команды загрузчика
zImage — образ ядра Linux
am335x-boneblack.dtb — скомпилированное дерево устройств платы
Еще при сборке ядра заказывались модули ядра, но они уже относятся к корневой файловой системе.
Корневая файловая система. BusyBox
Ядро получает корневую файловую систему путем монтирования блочного устройства, заданного в, переданном при запуске ядра, аргументе root=, и далее, первым делом, исполняет оттуда программу под названием init.
Если запустить BeagleBone Black, имея только вышеуказанные файлы для FAT раздела, то ядро будет паниковать по причине отсутствия init и, в целом, по причине пустой rootfs, т.е. корневой файловой системы.
Можно шаг за шагом создать все минимально необходимые компоненты корневой файловой системы, такие как оболочка, различные демоны запускаемые init, сам init, конфигурационные файлы, узлы устройств, псевдофайловые системы /proc и /sys и просто системные приложения. Для желающих совершать подобные подвиги, существует проект Linux From Scratch, здесь же я воспользуюсь швейцарским ножом встроенных систем с Linux, утилитой BusyBox.
Скачивание последней, на тот момент, версии:
Настройка конфигурации по умолчанию:
Чтобы не думать сейчас о разделяемых библиотеках, стоит установить статическую сборку BusyBox:
Settings —> Build static binary (no shared libs)
Установка в папку по умолчанию _install:
Теперь в папке _install можно видеть будущую корневую файловую систему, в которую нужно добавить некоторые вещи.
Папки, помимо созданных BusyBox:
Стартовый скрипт. Дело в том, что, запускаемая в первую очередь, программа init, делает много полезного, например, выводит в консоль приглашение, но до выдачи приглашения, init проверяет наличие стартового скрипта /etc/init.d/rcS, и, при наличии, запускает его.
Этот скрипт монтирует псевдофайловые системы proc и sysfs, и ничего не мешает ему запускать, к примеру, пользовательскую программу, отвечающую за функционал устройства, но лучше будет делать это в отдельных скриптах, скомпонованных по функциональному назначению.
Стоит сказать, что работа init, на самом деле, начинается с чтения конфигурационного файла /etc/inittab, но BusyBox’овская init включает таблицу inittab по умолчанию, если таковой не окажется в корневой файловой системе.
Теперь пора вспомнить про модули ядра. Их также нужно разместить в корневой файловой системе в /lib/modules/5.4.92/, но сейчас они разбросаны по всей папке в которой собиралось ядро. Чтобы собрать модули в кучу, нужно в папке с ядром выполнить
Где в INSTALL_MOD_PATH указать путь к папке с корневой файловой системой, кросскомпилятор указывать не нужно, т.к. здесь модули ядра просто копируются по месту назначения. В результате папка /lib корневой файловой системы пополнится разделом /lib/mudules/5.4.92/ содержащим модули ядра, полученные при компиляции ядра.
Осталось скопировать все содержимое папки _install во второй раздел SD карты, тот который с ext4, и поменять владельца всего содержимого на root.
После запуска BeagleBone Black с корневой файловой системой, через 1.910315 секунды после старта ядра, система предложит активировать консоль и начать работу.
Но начать работу в такой системе, скорее всего не получится, т.к. в ней нет ничего кроме системных утилит BusyBox и моей небольшой программы, нарисовавшей приветствие, зато, эта система поможет получить общее представление о том, какая магия происходит внутри подобных устройств. Именно общее, т.к. в реальных устройствах, из-за необходимости минимизации времени загрузки, ограниченности ресурсов, заточенности под конкретную задачу, различий между ARM процессорами, построение системы может сильно отличаться. Например, на малинке, вообще сначала стартует графический процессор, который затем запускает все остальное.
По поводу же заявленных в начале драйверов, взаимодействия с внешними устройствами, автоматизации сборки и некоторого полезного функционала, пойдет рассказ в следующей статье.
Источник