Портирование Linux на другую платформу требований [закрыто]


28

Я знаю, что Linux доступен и был портирован для многих различных платформ, таких как X86, ARM, PowerPC и т. Д.

Однако с точки зрения портирования, что именно требуется?

Насколько я понимаю, Linux - это программное обеспечение, написанное на C. Поэтому при переносе Linux с X86 на ARM или другие, например, это не просто вопрос повторной компиляции кода с помощью компилятора для конкретной целевой архитектуры?

Если оставить в стороне драйверы устройств для различных периферийных устройств, что еще нужно будет сделать при переносе Linux на новую архитектуру. Разве компилятор не заботится обо всем за нас?


11
Можем ли мы предположить, что вы просматривали исходные тексты ядра для конкретной архитектуры? git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/…
Кусалананда

Ответы:


57

Несмотря на то, что большая часть кода ядра Linux написана на C, все еще есть много частей этого кода, которые очень специфичны для платформы, на которой он выполняется, и должны учитывать это.

Одним конкретным примером этого является виртуальная память, которая работает аналогичным образом на большинстве архитектур (иерархия таблиц страниц), но содержит конкретные детали для каждой архитектуры (например, количество уровней в каждой архитектуре, и эта цифра возрастала даже в x86 с введение новых более крупных чипов.) В коде ядра Linux представлены макросы для обработки этих иерархий, которые могут быть исключены компилятором на архитектурах, которые имеют меньше уровней таблиц страниц (так что код написан на C, но принимает детали архитектуры в рассмотрение.)

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

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

  • Системные вызовы . Механизм, с помощью которого код пользовательского пространства может инициировать системный вызов, обычно зависит от архитектуры (а иногда даже от конкретной модели процессора, например, Intel и AMD вводили разные инструкции для этого, более старые процессоры могут не иметь этих инструкций, поэтому подробнее для тех, кто все еще будет уникальным.)

  • Обработчики прерываний . Сведения о том, как обрабатывать прерывания (аппаратные прерывания), обычно зависят от платформы и обычно требуют некоторого клея на уровне сборки для обработки конкретных соглашений о вызовах, используемых для платформы. Кроме того, примитивы для включения / отключения прерываний обычно зависят от платформы и также требуют кода сборки.

  • Инициализация : детали того, как должна происходить инициализация, также обычно включают детали, специфичные для платформы и часто требующие некоторого кода сборки для обработки точки входа в ядро. На платформах с несколькими процессорами (SMP) сведения о том, как подключить другие процессоры к сети, обычно также зависят от платформы.

  • Блокирующие примитивы . Реализация блокирующих примитивов (таких как спин-блокировки) обычно также включает в себя специфичные для платформы детали, поскольку некоторые архитектуры предоставляют (или предпочитают) разные инструкции ЦП для их эффективной реализации. Некоторые будут реализовывать атомарные операции, некоторые предоставят cmpxchg, который может атомарно протестировать / обновить (но потерпит неудачу, если другой писатель вошел первым), другие будут включать модификатор «lock» для инструкций процессора. Они также часто включают написание ассемблерного кода.

Вероятно, существуют другие области, в которых для ядра (или, в частности, для ядра Linux) необходим специфичный для платформы или архитектуры код. Если посмотреть на дерево исходных текстов ядра, то под arch/и под ним есть специфичные для архитектуры поддеревья, include/arch/где вы можете найти больше примеры этого.

Некоторые из них на самом деле удивляют, например, вы увидите, что число системных вызовов, доступных в каждой архитектуре, различно, и некоторые системные вызовы будут существовать в некоторых архитектурах, а не в других. (Даже на x86 список системных вызовов различается для 32-битного и 64-битного ядра.)

Короче говоря, есть много случаев, когда ядро ​​должно знать, что специфично для платформы. Ядро Linux пытается абстрагировать большинство из них, поэтому алгоритмы более высокого уровня (например, как работают управление памятью и планирование) могут быть реализованы в C и работать одинаково (или в основном одинаково) на всех архитектурах.


7
Очень хорошая рецензия! Различия в количестве системных вызовов в основном связаны с историей: новые порты включают действительные системные вызовы во время порта, они не беспокоятся об историческом багаже, присутствующем в старых портах, поэтому устаревшие системные вызовы обычно отсутствуют в портах. новее, чем амортизация. (Это не охватывает все сценарии ...)
Стивен Китт

10

В дополнение к портированию ядра Linux вам потребуется определить двоичный интерфейс приложения (ABI) для программ «пользовательского пространства» и портировать нижние уровни стека программного обеспечения пользовательского пространства. Linux обычно используется с низкоуровневыми компонентами пространства пользователя из проекта GNU, из которых наиболее важными являются:

  • Компилятор C, ассемблер и компоновщик: GCC и GNU Binutils . Для совершенно новой архитектуры ЦП вам необходимо портировать это программное обеспечение еще до того, как вы начнете портировать ядро, поскольку само ядро ​​является программой на Си и должно быть скомпилировано. Если уже есть «бэкэнд» поддержка ЦП вашей платформы, но только не с Linux в качестве ядра ОС, у вас значительно меньше работы, и вы сможете отложить большую часть работы, пока ядро ​​не заработает и Бег.
  • Библиотека времени выполнения C: " GNU libc ". Эта библиотека включает в себя код, который выполняет системные вызовы и иным образом напрямую взаимодействует с ядром.
  • Библиотека «интерфейса внешних функций», libffi , которая является важным компонентом многих высокоуровневых языковых интерпретаторов и выполняет одну из немногих оставшихся задач, требующих небольшого количества рукописного языка ассемблера.

Многие другие части программного обеспечения имеют дополнительные компоненты, зависящие от платформы; например, просмотр веб-страниц будет значительно быстрее, если вы напишите оптимизированные вручную криптографические примитивы для NSS и OpenSSL для вашей новой архитектуры ЦП, а также серверные компоненты для своевременной компиляции для IonMonkey и V8 . Но это не обязательно для создания новой платформы.


1

Вы должны сообщить ядру об оборудовании, на которое вы портируете. Работа ядра состоит в том, чтобы напрямую взаимодействовать с оборудованием, поэтому для его правильной работы ядру необходимо знать о процессоре, генераторах (тактовых генераторах) и любых периферийных устройствах, таких как различные виды последовательных портов (SPI, CAN, I2C и т. Д.).

В старые времена вы делали это, написав код для конкретной платформы, который затем использовали бы драйверы для работы. В наши дни это делается путем написания определения дерева устройств .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.