Открыть список
Как стать автором
Обновить

Комментарии 77

Интересно, а почему 64-х битное? По идее крошечное ядро надо в основном для маломощных систем.

Я экспериментировал на уже собранной системе, так что надо было быть совместимым.

Цель эксперимента? Уменьшить футпринт по памяти? Или в чем сакральный смысл?


Это в частности приводит к тому, что перекомпиляция ядра превращается в достаточно длительный процесс.

Зачем? Если все «нормальные» люди уже давным давно ядра берут из бинарных deb/rpm?


На моей рабочей машине (i7, 8 cores, 64gb RAM, tmpfs) финальная конфигурация собирается за 1m 16s.

Неплохой результат, поздравляю

Если автор выключил epoll и inotify, но не выключил кучу драйверов сетевух, то я думаю цели вообще нет, просто угарнуть в стиле пикабу.
Удаление сетевых драйверов уменьшает число конфигурационных параметров, но размер ядра остается неизменным:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2020000 Feb  1 14:16 arch/x86/boot/bzImage
566
$

и к освобождению памяти это тоже не приводит:
instance-20210124-1735 ~ # free -h
              total        used        free      shared  buff/cache   available
Mem:          996Mi        17Mi       944Mi          0B        34Mi       965Mi
Swap:            0B          0B          0B
instance-20210124-1735 ~ # 
Тогда еще подумайте, зачем вам в облачной виртуалке следущее (что прям сразу заметил):
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_CPU_SUP_HYGON=y
CONFIG_CPU_SUP_CENTAUR=y
CONFIG_CPU_SUP_ZHAOXIN=y
CONFIG_ACPI_BATTERY=y
CONFIG_ACPI_FAN=y
CONFIG_WIRELESS=y
CONFIG_THERMAL=y
CONFIG_DEBUG_KERNEL=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
Я убрал кое-что относящееся к ACPI, вот результат:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2003616 Feb  2 14:52 arch/x86/boot/bzImage
559
$ diff .config.old .config
358,359c358,359
< CONFIG_ACPI_AC=y
< CONFIG_ACPI_BATTERY=y
---
> # CONFIG_ACPI_AC is not set
> # CONFIG_ACPI_BATTERY is not set
361c361
< CONFIG_ACPI_FAN=y
---
> # CONFIG_ACPI_FAN is not set
363d362
< CONFIG_ACPI_CPU_FREQ_PSS=y
365,368c364
< CONFIG_ACPI_PROCESSOR_IDLE=y
< CONFIG_ACPI_PROCESSOR=y
< # CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
< CONFIG_ACPI_THERMAL=y
---
> # CONFIG_ACPI_PROCESSOR is not set
$

Убрать CONFIG_CPU_SUP_* не получается, make возвращает их в .config.
Скорее всего потому, что драйвера собираются как модули и не подгружаются, т.к. нет подходящих устройств.
Это ядро собирается без модулей, все вкомпилировано в ядро.
все драйверы поместились в 4k-выравнивание?
Это столько лишних приседаний и ты выиграл 4Мб памяти? )) 22 против 18 использованной. Ну ппц ты парень жжёшь. Это от 1Гб, что у тебя на машине стоит, 0.4%
Задача была не сэкономить память, а уменшить время компиляции.
просто угарнуть в стиле пикабу.
Извиняюсь за оффтопик, но наблюдаю стойкую тенденцию — сначало на пикабу было вообще моветон ссылаться, а тут уже даже комплимент почти:)
Цель эксперимента? Уменьшить футпринт по памяти? Или в чем сакральный смысл?

Пршу прощения, я в самом начале поста указал, что машина маломощная, хотелось ускорить перекомпиляцию. Это gentoo, так что конкретно в этом случае компиляция из исходников является штатным способом обновления.

ОКей, а какова цель замены убунту на генту? Просто "угарнуть в стиле пикабу."?


что машина маломощная, хотелось ускорить перекомпиляцию

ну, пацаны же знают про кросс-компиляцию на других машинах ))) И Вы же сами про это пишете…

gentoo поставил потому, что было интересно поиграть плюс хотелось выжать максимум из маломощной машины.

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

Можно попробовать какой-ньть spotinst на амазоне поднимать по надобности. Или же вам надо собирать ядра много раз в день?

По заголовку статьи почему-то подумал, что речь именно о размере бинарника ядра, но в тексте не увидел ни одного размера. От этого путь постепенной комплиции, конечно, не перестал быть интересным.
Я привожу размер скомпилированного ядра и количества параметров для каждого шага. Вот копи-паста из статьи для финального ядра:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2020000 Jan 31 19:13 arch/x86/boot/bzImage
647
$

Мммм… grep | grep -c?
А если просто к первому -c добавить и не считать вывод ll ?

Вы правы, можно считать вот так:
grep -c "^[^#]" .config
Зачем? Если все «нормальные» люди уже давным давно ядра берут из бинарных deb/rpm?

ну вопервых генту и deb/rpm живут в разных мирах


а во вторых в генту есть "пакет" с бинарным ядром который можно просто поставить а не компилять


а вот почему автор топика не оставил ссылку на имя и пример конфига сервера сборки загадка, если он вручную занимался перекидываниями то ему ещё есть чему поучится

Простите, что вы имеет в виду под «конфигом сервера сборки»? Это машина под ubuntu 20.04 где я собирал ванильное ядро. Сссылку на конфиг, на котором я остановился, я привел.

Я уже пару лет как с генты ушёл
Но выглядело это так: emerge запускаю на своей тачке, а сборка работает на vps где-то далеко доставшемся мне бесплатно, там вроде тоже Убунта была, непомню

Спасибо за пояснение и наводку. Так я еще не настраивал, но определенно попробую.

Емнип я тогда нагуглил это как emerge remote build server

ну вопервых генту и deb/rpm живут в разных мирах

да эт понятно ) Мы тоже очень долго использовали генту, но потом в какой-то момент решили, что весь гемор с ней не стоит потраченных усилий. И катнулись на убунту. /это был один известный российский веб-хостинг/

А как изменился
free -h
в "минимальной" системе и "из коробки"? Что изменилось по существу, насколько изменилось? Может, что-то ещё, кроме занятой памяти изменилось?

Минимальная система:
instance-20210124-1735 ~ # free -h
              total        used        free      shared  buff/cache   available
Mem:          996Mi        17Mi       944Mi          0B        34Mi       965Mi
Swap:            0B          0B          0B
instance-20210124-1735 ~ # 

Система после конвертирования из ubuntu 20.04, 1285 параметров в .config:
instance-20210111-0918 ~ # free -h
              total        used        free      shared  buff/cache   available
Mem:          986Mi        22Mi       921Mi       0.0Ki        43Mi       872Mi
Swap:            0B          0B          0B
instance-20210111-0918 ~ #

Эм, я что-то в этой жизни не понимаю, но общей видимой памяти во втором варианте стало меньше на 10MB. А Used даже стал больше. Итого — available меньше на ~70MB (WAT?)

Скорее всего total стал меньше, тк bios(UEFI) зарезервировал часть памяти для устройств.

см buff/cache. Это память, которая использована для кэша файловой системы, предзагруженных бинарников, смапенных файлов и тд.
Она, разумеется, уменьшает размер «available», но если ты попросишь больше, чем есть available, то все буферы и кэши выгрузятся почти до нуля. Смотреть нужно на «used» + «shared».

да я уже понял, что не туда посмотрел, спасиб, потому что автор не четко написал где какое ядро )
В общем — по ходу "оптимизированное" ядро видит на 10МБ памяти больше (колонка total). При этом "used" меньше на 5 МБ. Разница по available, внезапно, может быть из-за разных опций кэширования в разных ядрах и конфигах

Я не стал заниматься перфекционизмом и вычищать абсолютно все, что не нужно.

Исходя из заголовка я ждал именно этого, а 2мб… вау эффекта нет. Если бы мне гентушник сказал «А у меня ядро всего 2мб и полностью рабочее» я бы ему даже поверил, потомучто в убунте ядро 4.15 8мб занимает, всего в 4 раза больше.
Я достаточно минимизировал ядро и существенно сократил время компиляции. Дальнейшие улучшения потребуют непропорционально много времени и дадут малый выигрыш по сравнению с тем, что есть.
Сорян что влез в вашу беседу, хотел рассказать о своем опыте тоже, но на Debian.
Размер ядра самого может и реально буквально там 4-5 мегабайт, но вот пакет с ядром 250 мегабайт, в него видимо входят всякие initrd и подобное на все случаи жизни. Я ставил опыты на виртуалках Hyper-V, хотелось минимальный образ виртуалки собрать для своих целей и 250 мегабайт ощутимый размер, после пересборки с командами типа
make localmodconfig && make localyesconfig

Получился пакет ядра буквально там мегабайт на 10.
Аналогичный профит получал еще в году 2009, когда на атомном нетбуке патчил ядро (контроллер sata фризил), если просто пропатчить и собрать с параметрами стандартными от дистрибутива, то компилировалось на ноуте часов 10 (да, компа не было, только нетбук), но когда минимизировал конфиг сборки, то буквально за полчаса собралось.

А автору статьи хочу сказать чтобы сравнивал размеры не ядра, а модулей, которые не вкомпилированы в ядро, но тоже собираются.
В моем случае модули не собираются, все вкомпилировано в ядро.
… потомучто в убунте ядро 4.15 8мб ...

Вы уверены?.. Или initrd (initramfs) уже за kernel не считается? (ну попробуйте удалить… если никакие дрова или модули ядра на стадии бута не нужны, может и взлетит).


Не убунту, но тоже дебиан — (v.4.19) 48MB со всем барахлом (притом упакованным):


$ du -hc /boot/*-$(uname -r)
203K    /boot/config-4.19.0-13-amd64
39M     /boot/initrd.img-4.19.0-13-amd64
3.3M    /boot/System.map-4.19.0-13-amd64
5.1M    /boot/vmlinuz-4.19.0-13-amd64
48M     total
$ file /boot/initrd.img-$(uname -r)
/boot/initrd.img-4.19.0-13-amd64: gzip compressed data, ..., original size 136074240

kt97679, я без понятия как оно для gentoo там (если всё собирается одним куском в ядро), но… strip случайно не забыли? :)

Так это же для модулей, я у меня все вкомпилировано в ядро.
Картофель, картошка. Суть в том, что в заголовке «щас мы будем создавать минимальное рабочее ядро» а в статье «Ну я тут кое чего выключил и уменьшил размер». Не берусь судить о составе инитрд, но там же помимо модулей ядра и куча другого барахла, это ведь полноценная файловая система линукса запакованная в файл.
Простите, но initrd ни в коем случае не является частью ядра. Даже на х86, можно все драйвера скомпилировать в ядро и оно замечательно запустится на целевой машине. А вот, если надо поддерживать много разных машин одним бинарником, а засорять память лишними дровами не хочется, тогда и используют initrd
Даже на х86, можно все драйвера скомпилировать в ядро и оно замечательно запустится на целевой машине.

Конечно можно, я не спорю… только это не так в той "убунте, с ядром 4.15 8мб", где оно всё лежит и в initrd в том числе.
Автор же собрал ядро без модулей (со статически слинковаными дровами)…
Поэтому я и написал как написал.

Вдохновил меня сделать что-то подобное с целью уменьшить attack surface в виртуальной машине. User space я уже минимизировал, а вот ядро оставил. Надо бы его тоже порезать, в частности выпилить поддержку модулей.

В статье не хватает размеров файла ядра до оптимизации и после.

Сравнивать сложно, так как при конвертации я использовал конфиг убунтовского ядра, которое сжимается lz4, а в новом ядре по умолчанию стоит xz. Размер старого ядра 14727552 (это то, у которого в конфиге 1285 параметров). Но xz жмет лучше lz4, так что повторюсь, сравнение не корректное.
Хорошо, размер старого ядра вы сказали. Ну а новое-то какого размера вышло?
Я привожу размер скомпилированного ядра и количества параметров для каждого шага. Вот копи-паста из статьи для финального ядра:
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2020000 Jan 31 19:13 arch/x86/boot/bzImage
647
$

По-русски в выводах к статье нельзя было написать — до оптимизации бинарник ядра занимал столько-то мегабайт, после оптимизации стал занимать столько-то?

Вот когда мы занимались впихиванием OpenWRT с относительно свежим ядром и OpenVPN в Linksys WRT54GL у которого всего 4МБ флеша — это был челлендж.


А то что в статье… даже не знаю зачем, особенно если автор даже поленился отключить руками тонны ненужных дров.


Кому интересны крайности — может смотреть в сторону Firecracker и оптимизированных под него ядер. ВМ там грузятся за миллисекунды...

Выше я уже ответил, что удаление, к примеру, драйверов сетевых адаптеров, не привело к уменьшению размеров ядра. Да и цели именно сэкономить каждый байт у меня не было. В первую очередь мне хотелось уменьшить время компиляции.

Firecracker идеологически мне тоже очень нравится, но oracle cloud использует kvm, так что приходится ориентироваться на него.
Выше я уже ответил, что удаление, к примеру, драйверов сетевых адаптеров, не привело к уменьшению размеров ядра.

Ну вы же понимаете что так быть не может. Все драйвера, как и прочие модули, компилируются в объектные файлы и линкуются в единый бинарник, который потом сжимается каким-нибудь LZMA или что там выбрано в конфиге. И исключение пары десятков ненужных сетевух и тех же storage контроллеров (всё кроме virtio) сильно уменьшает результат.


В первую очередь мне хотелось уменьшить время компиляции.

А зачем вообще в наше время заниматься сборкой ядер? Если это конечно не embedded...

Наверное, что бы обновлять ядра было не больно. Это же генту, там с сырцов обновляется :)

Генту, как и всякие (B)LFS, хороши для тех, кто хочет изучить внутреннее устройство ОС. Или для задротов, которые хотят выжать лишние пол-процента производительности через emerge world + CFLAGS='-march=native -O3'


Для всех остальных это зло, в серьезном продакшене использовать очень тяжело и бессмысленно. Если нужна производительность — проще пересобрать нужные пакеты с правильными флагами и залить в локальную репу.

Ну не всегда.
Я некоторое время назад поменял Fedora на Gentoo, потому что несколько устал бороться с дефолтными конфигами и страным поведением системы в моих кейсах, связанных в основном с виртуализацией, несколькими видео- и звуковыми картами (pulse почему-то крайней нестабильно работал и вел себя странно, причем апдейт версии в рамках релиза федоры не помогал, возможно что-то с конфигами дефолтными было не так...), использованием Enlightenment в роли WM и отсутствия необходимости в полном пакете софта из гнома или kde и т.д. Ubuntu как вариант не рассматривал, она норм конечно, но я боюсь еще одна починка поломавшегося об цикличесую зависимость apt меня просто добьет. Случается это конечно весьма не часто (пожалуй раза 3 всего было за те 14 лет, что я ей пользовался так или иначе), но сама возможность такой ситуации меня несколько нервирует. Я если что лучше ручками поправлю или соберу, чем буду бороться с dependency cycling или подобным.
Но в прод да, я бы пожалуй ее не потащил, слишком много гемороя и мало смысла. Да и в большинстве случаев там все равно все в контейнерах, эксплуатационные расходы не окупят всей суеты.

Ну, десктоп я даже не рассматривал, автор про ВМ в облаках речь ведёт...


Я, конечно, когда-то жил на десктопе с гентой, когда был сильно моложе и времени было много чтобы подождать пока файрфокс или опенофис соберутся :)


Но, по-моему, Linux как 20 лет назад не был готов к десктопу, так и сейчас не готов. Понятное дело что жить можно если заниматься только, допустим, разработкой. Но отсутствие большого количества коммерческого софта напрягает.


Но это уже оффтопик :)

времени было много чтобы подождать пока файрфокс или опенофис соберутся

Офтопик конечно, но я тут проапгрейдился до 5950x со старенького Xeon и в общем-то сборка совершенно перестала напрягать. Всякая мелочевка собирается вообще мгновенно, apt индексы дольше пересчитывал, Firefox ~ за 9 минут от запуска emerge, а вот Chromium да, хром тот еще тормоз.
На счет готовности — ну очевидно я на нем не играю (в виртуалке играю, куда видюха проброшена), но вот в плане поработать все-таки удобнее, не смотря на WSL в винде. А мак просто выйдет безумно дорого в серьезной конфигурации. За коммерческий софт — да, пожалуй, но каждый выбирает инструмент под свои потребности:)
Это проект, которым я занимаюсь в свое свободное время для удовольствия. О продакшене в данном случае речь не идет :).

Firecracker тоже использует KVM. Он замена qemu.

Я думаю, что скорее речь про то, что там внутри — MicroVMM и все прочее. Именно само ядро виртуалки с минимальным footprint — и это справедливо, т.к. в виртуальных средах оборудование стандартизовано

Ну там впринципе обычное ядро линукса урезанное, поэтому опции можно подглядеть. Только чую я, судя по коду, что там используется virtio + mmio, а не PCI. Поэтому да, в Oracle Cloud такое ядро не запустишь.

Содержание статьи не ответило на вопрос заголовка. Я конфигурировал для проекта ядро 3.хх на x86 размером 620кБ, включая модули и это не предел.
А если рассматривать скорость компиляции как вид спорта, то я бы еще с настройками компилятора поигрался, отключив проверки и оптимизацию. Всё окружение сборки можно скопировать в tmpfs. Написать скрипт по удалению каталогов, которые не требуют сборки.
Эта виртуалка из always free tier, так что памяти там всего 1gb, tmpfs использовать не получится. Но я забыл упомянуть, что для сборки минимального ядра мне не понадобился своп, в отличие от ядра собранного по мотивам того, что было в исходной убунту.
Можно наложить overlayFS и использовать память для записи результатов. Можно записать в tmpfs kernel headers. Можно почистить ядро и оставить только то, что нужно собирать, размер не должен превышать 100Мб. А без этого вы уменьшили конфиг и стало быстрее собираться и меньше требовать памяти — ничего нового.
копирование в tmpfs малополезно, так как после первой компиляции всё нужное закэшируется в те же самые буфера кэша VM из которых и состоит tmpfs
В теории — да, особенно с современными SSD, на практике, как минимум, на записи кэши будут писаться на диск и может быть выигрыш от первого чтения файлов. В любом случае, это полезный эксперимент.
На загрузочную дискету не влезет. Если её стандартно форматировать, на 80 дорожек, 18 секторов.
В 1999 у меня была дискета загрузочная Debian с сетью, GUI и браузером. И это имело практический смысл.
А когда речь не идёт о дискете — незачем и экономить.
А почему размер ядра НАСТОЛЬКО вырос?

Очевидный ответ — потому что выросла кодовая база?
Появилось 100500 новых типов устройств, которые надо поддерживать.
Вырос функционал.
В ядро линукса стали внедрять функционал безопасности…

Тема интересная. Может кто подготовит статью с более экстремальными результатами и подробным описанием, что получилось в итоге.
Интересная статья. Очень актуально для разного рода микроконтроллеров и встраиваемых систем.

Вообще жор ресурсов современных ОС просто поражает. Помню в 2012 году мне для моего веб-проекта вполне хватало впс-ки с 128 мегабайтами памяти. Там была freebsd (вроде 8), php 5.3, nginx, mysql и ejabberd. Потом для отбивания ддоса пришлось расширить память до 192 мегабайт. И этого блин хватало чтобы даже ддос отбивать! А что сейчас? Сейчас впс-ка с гигом памяти кое как шевелится и помирает от малейшей нагрузки.
время загрузки сравнивалось?
В пределах погрешности время загрузки не изменилось.
эхпечаль… была статья про амазоновские сервисы, якобы им удалось значительно сократить время загрузки ядра, выкинув все ненужное. очень полезно для масс-отладки in-kernel разработки.
Microsoft вот тоже оптимизировал скорость загрузки для WSL2. Но скорость загрузки в большинстве случаев это не приоритетная фича.

Как-то, учась в институте, собирал ядро 2.6, rootfs и вот это все под отладочную плату с процом AT9260, где было 4 Мб флэша. Помню, я даже не смог туда засунуть libc++, только libc. Возможно, можно было ужать сильнее, но это было мое практически первое знакомство с линуксом.

12 лет назад делал узкоспециализированную систему, состоящую из ядра 2.6.27 и юзерспейсной программы размером в 308КБ. Ядро умело грузиться на обычном PC, поддерживало работу с USB-клавиатурой, дисками и видеокартой. Юзерспейс рисовал GUI на framebuffer.
Размер ядра вместе со вшитым в initramfs юзерспейсом — 1054576 байт.
Конфиг: pastebin.pl/view/ed53ec7b
В получении образа такого размера не было какой-либо особой сложности.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.