Тонкая настройка и компиляция ядра Linux

Старое железо  /  Linux Ubuntu  




Есть у двух операционных систем Windows и Linux, два недостатка, которые при перекрестном сравнении, оказываются очень даже достоинствами, хотя чаще всего все же недостатками: универсальность.

Когда-то давным давно, мы все сталкивались с необходимостью переустанавливать Windows, после смены всего лишь материнской платы. Кто-то не заморачивался и переустанавливал, кто-то лез в дебри и узнавал, что во всем виноват контроллер жесткого диска, и можно было всего лишь переустанавливать драйверы. С тех времен (2001 г., Windows XP) мало что поменялось - 2015 г., Windows 10 ведет себя так же само. Установленная на одном ПК Windows, отказывается работать на другом ПК.

С Линуксом таких проблем нет. Установленный один раз, на флешку, на жесткий диск, он будет работать примерно одинаково на любом компьютере, где будет стоять эта флешка или жесткий диск. Смена видеокарты - не помеха, смена материнской платы - тоже. Линукс будет работать везде.

Это происходит потому что, ядро Линукса (и необходимые для работы устройств модули) - УЖЕ содержит в себе все необходимые драйверы. Их реально много. И они реально работают.

Платой за подобную гибкость, является скорость работы. Windows будет грузиться быстрее, будет работать быстрее, меньше будет потреблять ресурсов, именно за счет того, что драйверы устанавливаются по мере необходимости, и ОС нет нужны тащить за собой целый зоопарк. Линукс в этом случае проигрывает в плане скорости, особенно это заметно на более менее старых машинах, в более менее требовательных задачах, таких как просмотр видео, игры, и прочее.

Однако есть средство, способное неплохо ускорить работу систем Linux - перекомпиляция и оптимизация ядра под свои нужды.

По сути, этот процесс представляет собой весьма долгое и упорное конфигурирование настроек под нужды именно своего компьютера, с только используемым оборудованием и настройками, специфичными только для одного компьютера. Его мы и рассмотрим подробнее, на примере ОС на базе Debian, такими как Ubuntu, Mint и прочий зоопарк. С остальными Линуксами процесс сборки ядра может немного различаться, хотя скомпилированное под одной ОС ядро, вы запросто можете использовать в других своих ОС. Но суть не в этом.

Итак, для начала сборки ядра, нам нужно поставить несколько дополнительных программ. В Debian-based это делается так:

sudo apt-get install kernel-package libssl-dev libncurses5-dev patch

После чего, нам нужно найти исходники нашего будущего ядра. Проще всего, их скачать с сайта https://www.kernel.org/, они представляют собой один файл в формате tar.xz. После скачивания, нам нужно открыть консоль, и распаковать архив командой 

tar -xvf <имя архива>

У нас будет новая папка с именем ядра, где будут распакованы наши исходники. Кстати на данный момент, советую качать ядро по ссылке https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.3.4.tar.xz поскольку оно самое стабильное, и под него выпущено некоторое количество полезных патчей, речь о которых пойдет ниже.

В любой многозадачной ОС, существует так называемый планировщик задач. В общих чертах, это маленькая программа, которая передает управление каждой из запущенных задач в очень короткие промежутки времени, в зависимости от настроек системы. Например, у нас запущен медиаплеер, торрент-клиент, и браузер. Цель планировщика, дать каждой из этих трех программ (в реальности их намного больше) некоторое количество ресурсов процессорного времени, чтобы эта программа выполнила какое-то действие, затем эти ресурсы забрать, и передать по очереди другой программе. Визуально это выглядит как одновременная работа браузера, торрента и медиаплеера.

Планировщики задач планируют время по разным алгоритмам. Например, каждая из трех программ, может получать одинаковое число процессорного времени. Например по 200мс. Реализация такого алгоритма весьма простая, однако на практике может приводить как к простою, так и к дефициту ресурсов. Ведь программе может потребоваться не 200мс, а 10мс, и тогда оставшиеся 190мс процессор будет зря работать, а остальные две программы будут ждать. Планировщик задач может отдавать процессорное время в зависимости от аппетитов приложения. Этот алгоритм чуть сложнее в реализации, работает чуть получше, однако в этом случае недостаток из плоскости "что если мало" перейдет в плоскость "что если много". Понятным языком, если какой-то программе захочется слишком много времени, то остальные программы просто зависнут.

Чтобы этого избежать, планировщики задач используют более изощренные алгоритмы, позволяющие перекладывать по одной задаче на ядро процессора, лимитировать процессорное время, забирать его насильно, отдавать больше времени, если высокий приоритет, и так далее. Волею судеб происходит так, что официальные разработчики линуксячьего ядра, не слишком-то оптимизируют планировщик задач, из-за чего, при работе в ОС Linux кажется, что она не отзывчива. Нажали вкладку на браузере, прошло пол-секунды, прежде чем вкладка сменилась. Это есть результат работы стандартного планировщика задач.

К счастью, система разработки (в частности, это C++) поддерживает систему патчей. Это значит, что при помощи одного маленького файлика, мы можем улучшить (или поломать) огромный исходный год. В нашем с вами случае, мы будем патчить планировщик задач.

Поскольку мы с вами скачали исходники ядра 4.3, то и патч нам подойдет только для ядра 4.3. Скачать его можно здесь: http://ck.kolivas.org/patches/bfs/4.0/4.3/4.3-sched-bfs-467.patch и положить в папку с исходными кодами ядра. После чего, находясь в этой самой папке, выполнить команду

patch -p1 -i 4.3-sched-bfs-467.patch

На этом патчинг ядра улучшенным планировщиком задач, закончен 

Кроме планировщика процессорного времени, существует так же планировщик для ввода-вывода. Его задачи сходны с планировщиком CPU, однако направлены на оптимизацию операций чтениязаписи. Давным давно, умные люди поняли, что нет смысла гонять жесткий диск каждый раз для чтениязаписи нескольких байтов. Гораздо логичнее эти операции поставить в очередь, и по прошествии какого-либо времени пакетно выполнить все и сразу. Буферизация, типа. Планировщик ввода-вывода, компонует такие задачи, в зависимости от требований приложений, скорости диска, вспышек на Солнце, и так же само как и планировщик процессорного времени, может работать по разным алгоритмам, начиная от примитивных, и заканчивая навороченными. По умолчанию, Линукс использует примитивный планировщик, который раздает каждому процессу, равные промежутки времени для записи. Это хорошо. Но только если у вас одна задача, например торрент-клиент. Если же задач больше, то каждый процесс чтениязаписи, будет требовать и процессорное время, что на практике оборачивается лагами, заиканиями звука, и просто снижением скорости чтениязаписи.

Аналогично планировщику процессорного времени, существует патч для планировщика IO. BFQ.

Скачивать его придется тремя частями, в ту же самую папку с ядром:

http://algo.ing.unimo.it/people/paolo/disk_sched/patches/4.3.0-v7r8/0001-block-cgroups-kconfig-build-bits-for-BFQ-v7r8-4.3.patch

http://algo.ing.unimo.it/people/paolo/disk_sched/patches/4.3.0-v7r8/0002-block-introduce-the-BFQ-v7r8-I-O-sched-for-4.3.patch

http://algo.ing.unimo.it/people/paolo/disk_sched/patches/4.3.0-v7r8/0003-block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r8-for-4.3.0.patch

Патчить по аналогии с предыдущим:


patch -p1 -i 0001-block-cgroups-kconfig-build-bits-for-BFQ-v7r8-4.3.patch
patch -p1 -i 0002-block-introduce-the-BFQ-v7r8-I-O-sched-for-4.3.patch
patch -p1 -i 0003-block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r8-for-4.3.0.patch

На этом патчинг закончен, можно переходить к преконфигурации. Система поддерживает преконфигурацию нескольких видов:

1) На основе текущей конфигурации ядра. То есть, все что активировано в вашем текущем ядре (включая весь мусор), будет активировано и в новом ядре. Нам это как бы не нужно.

2) На основе загруженных на данный момент модулей, которые будут скомпилированы как модули.

3) На основе загруженных на данный момент модулей, которые будут вшиты в ядро.

Последние два пункта различаются только результирующим размером ядра и количеством отдельно находящихся драйверов. Оба эти метода имеют свои недостатки, которые впрочем настолько мизерны, что ими можно пренебречь: если модули будут вкомпилированы в ядро, оно будет больше в размерах, будет чуть дольше грузиться при старте системы, однако система будет меньше обращаться к файлам, и в теории будет загружаться на секунду быстрее в зависимости от скорости линейного чтения вашего диска. Однако, если модули будут находиться отдельно, ядро быстрее загрузится, а модули будут вызваны только те, которые необходимы и как результат больше ресурсов будет свободно. Например модуль драйвера вебкамеры может быть загружен только тогда, когда камера подключена. В случае вкомпилирования в ядро, он будет просто висеть в памяти. Решать вам.

Итак, для преконфигурации, нам необходимо выполнить одну из команд:


1) make oldconfig
2) make localmodconfig
3) make localyesconfig


Система задаст вам несколько вопросов, на которые можно ответить Y,N, а просто нажатие Ентера, ответит по умолчанию.


Затем можно перейти непосредственно к тонкой настройке ядра, набрав команду


make menuconfig


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



С этого момента, лирично-сюсюкающий тон пропадает, начинается сугубо технический язык.


[*] 64-bit kernel - используется, если в результате мы хотим получить 64-битное ядро, которое будет поддерживать больше 4 Гб памяти.

General setup  --->

 [*] BFS cpu scheduler - процессорный шедулер, который мы патчили выше. Выбираем.

 Kernel compression mode (XZ)  ---> Советую выбрать XZ-алгоритм, ибо он чуть быстрее, чем Gzip

 Timers subsystem  --->

  Снимаем чекбоксы со всего, что видим, а Timer tick handling устанавливаем в Periodic timer ticks (constant rate, no dynticks), это позволит шедулеру   BFS самому распоряжаться процессорным временем.

 <*> Kernel .config support 

 [*]   Enable access to .config through /proc/config.gz - пригодится, для быстрого доступа к конфигурации нового загруженного ядра.

 [ ] Checkpoint/restore support - снимаем чекбокс

 [*] Optimize for size - ставим чекбокс, это немного сократит результирующий размер ядра

  [*] Configure standard kernel features (expert users)  --->

[ ]   Enable PC-Speaker support - снимаем чекбокс, этим мы сократим немного размер ядра и сэкономим на поддержке того, что нам не нужно

[ ] Enable AIO support - снимаем чекбокс, эта фича нужна для тяжелых приложений, которые должны быть заточены под ее использование

[ ] Enable madvise/fadvise syscalls - снимаем чекбокс. Этот параметр позволяет ядру реагировать заранее на предупреждения программ о том, сколько они памяти будут использовать.

[ ] Profiling support

[ ] Kprobes - ловит вызовы ядра, и адреса этих вызовов, во время дебаггинга..

Stack Protector buffer overflow detection (None)  --->















... продолжение следует




Метки текста:


https://minidevices.top/images/ava.png
https://minidevices.top/images/ava.png
2016-01-27 14:28
root
 27 января 2016 в 14:28 
  0  

4458
2016-01-27 14:28
guest     15 января 2017 в 13:16 Ответить
А продолжение где? плиз...