Почему API модуля Linux не имеет обратной совместимости? Я разочарован, обнаружив обновленные драйверы после обновления ядра Linux.

У меня есть беспроводной адаптер, для которого нужен проприетарный драйвер, но производитель снял это устройство с производства около 7 лет назад. Поскольку код очень старый и был написан для Linux 2.6.0.0, он не компилируется с последними ядрами Linux. Я использовал много дистрибутивов Linux, но везде одна и та же проблема. Хотя с ядром Linux распространяется драйвер с открытым исходным кодом, он не работает. Некоторые люди пытаются изменить старый проприетарный код, чтобы сделать его совместимым с последними ядрами Linux, но когда выпускается новое ядро ​​Linux, требуются месяцы, чтобы сделать код совместимым с ним. За это время выпускается еще одна новая версия. По этой причине я не могу перейти на новое ядро ​​Linux; иногда я даже не могу обновить свой дистрибутив.

2
Jeff Schaller 19 Авг 2020 в 17:54

2 ответа

Лучший ответ

Грег Кроа-Хартман написал на эту тему здесь: https://www.kernel.org/doc/html/v4.10/process/stable-api-nonsense.html

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


Ядро Linux всегда находится в стадии разработки. Это происходит по многим причинам:

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

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

Почему старые интерфейсы не поддерживаются?

Для обеспечения обратной совместимости потребуется поддерживать старые (часто «сломанные» и небезопасные) интерфейсы. Конечно, теоретически это возможно, за исключением того, что это сопряжено со значительными затратами.

Грег Кроа-Хартман пишет

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

Несмотря на то, что Linux является открытым исходным кодом, время разработчиков на его поддержку ограничено. Так что рабочую силу все же можно обсуждать с точки зрения «стоимости». Разработчики должны выбрать, как они проводят свое время:

  • Тратить много времени на поддержку старых/сломанных/медленных/небезопасных интерфейсов. Иногда это может удвоить или утроить время, необходимое для написания интерфейса в первом экземпляре.
  • Выбросьте старые интерфейсы и ожидайте, что другие специалисты по сопровождению программного обеспечения будут [выполнять свою работу и] поддерживать собственное программное обеспечение.

В конечном счете объединение интерфейсов действительно экономически выгодно (для разработчиков ядра). Если вы хотите знать, почему разработчики не тратят месяцы и годы своей жизни на спасение других от платит 10 долларов за новый адаптер Wi-Fi... вот причина. Помните, что это экономия времени и средств для разработчиков ядра, но не обязательно рентабельность для вас или производителей.

6
Philip Couling 25 Фев 2021 в 01:29
3
Комментарии не для расширенного обсуждения; этот разговор был перенесено в чат.
 – 
Jeff Schaller
19 Авг 2020 в 16:28

Хотя я внес несколько (очень незначительных) исправлений в ядро ​​Linux, я не считаю себя разработчиком ядра. Однако вот что я знаю:


Драйвер, написанный для ядра версии 2.6.0.0, предшествовал устранению Big Kernel Lock (BKL), которое произошло в версия ядра 2.6.39.

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

На современных компьютерах, которые могут иметь двузначное количество ядер на обычных настольных компьютерах и мощных ноутбуках, не говоря уже о серверах, API-интерфейс модуля ядра с обратной совместимостью 2.6.0 также должен будет реализовать BKL.

Если устаревший модуль говорит: «Я хочу взять BKL», остальная часть ядра не имеет ни малейшего представления о том, что модуль планирует с ним делать, и поэтому механизм обратной совместимости должен будет взять все блокировки, которые заменили BKL. просто чтобы охватить все возможности. Это было бы большим хитом производительности. И новые методы без блокировки также должны будут проверять устаревшую блокировку, что в первую очередь лишает смысла быть без блокировки. Таким образом, само существование механизма обратной совместимости ухудшит производительность системы, даже если на самом деле не будут загружены никакие устаревшие модули.


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

Всего две недели назад я устранял неполадки на старом сервере, который требовал ручного включения и выключения, когда обновления безопасности применялись автоматически. Это случалось несколько раз до этого и было воспроизводимо. Я обнаружил, что у него была очень старая версия проприетарного драйвера хранилища megasr, выпущенная до патчей Spectre/Meltdown, которая не была включена в автоматические обновления. После обновления драйвера до актуальной версии проблема ушла. Кстати, это было в простой системе RHEL 6.10.

Я также видел сбои серверов при загрузке проприетарных драйверов мониторинга оборудования до Spectre/Meltdown с ядром после Spectre/Meltdown. Основываясь на этом опыте, я полностью убежден, что исправления Spectre/Meltdown нужно рассматривать как переломное событие: ядро ​​и модули должны быть либо все версии до исправлений, либо все версии после исправлений; смешивание и сопоставление приведут только к огорчению и полуночным будильникам для дежурного системного администратора.

А поскольку Spectre был проблемой на уровне дизайна процессора, это «подарок, который не перестаёт дарить»: некоторые люди найдут новые способы использования слабых мест, а затем разработчикам ядра придётся найти способы блокировать эксплойты.


Это всего лишь две большие проблемы, которые необходимо решить устаревшему API модуля ядра, совместимому с версией 2.6.0.0. Я уверен, что есть много других.


И еще есть более философская сторона. Подумайте об этом: что делает Linux возможным?

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

Разработчики ядра Linux склонны верить в модель с открытым исходным кодом. Вот почему они сделали свой выбор дизайна и разработки таким образом, что предпочтительный способ участия производителя оборудования — открыть исходный код драйвера, объединить его с основным дистрибутивом исходного кода ядра, а затем (и только тогда< /strong>) вы получите выгоду от всего сообщества разработчиков ядра в его поддержке.

Это дает разработчикам и производителям аппаратного обеспечения некоторый стимул сделать это возможным. Если у вас есть что-то, что вы хотите сохранить в секрете, постарайтесь инкапсулировать это в ASIC или, если необходимо, в подписанную прошивку. (Если вы сделаете последнее, дайте другим разрешение на распространение пакета встроенного ПО.)

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

На самом деле дополнительные проблемы, вызванные проприетарными двоичными драйверами при отладке ядра, являются стимулом для разработчиков ядра не заботиться о разработке проприетарных драйверов: «Они усложняют мою работу, почему я должен делать что-то конкретное? чтобы облегчить их?»

Итак, разработчики ядра обычно делают то, что наиболее выгодно им как группе/сообществу. Если это включает в себя некоторые изменения API модуля, пусть будет так. Сторонние драйверы даже не входят в уравнение.

8
telcoM 19 Авг 2020 в 20:35
Спасибо за исторические лакомые кусочки, но вы описываете отдельные основные изменения API ядра, когда на самом деле незначительные изменения API, нарушающие совместимость, вносятся много раз в год, и вы на самом деле не отвечаете на вопрос, почему они так часты и разрушительны. Нет ничего невозможного в том, чтобы поддерживать совместимость API драйверов в течение как минимум трех-пяти лет, как это делается в проприетарных ОС. С точки зрения пользовательского пространства это еще более удручающе: большинство 32-битных приложений из Windows 95 все еще работают в Windows 2010 спустя 25 лет после их написания. Линукс далеко не тот уровень.
 – 
Artem S. Tashkinov
19 Авг 2020 в 17:29
@ArtemS.Tashkinov Вы правы. Linux API слишком часто меняется.
 – 
Akib Azmain
19 Авг 2020 в 17:56
1
О, и это тоже не ответ. Это исторический взгляд на некоторые изменения. Тем временем Microsoft удалось добавить в свои ядра средства защиты от временных уязвимостей ЦП, при сохранении API/ABI драйверов в Windows 7/8/10, что означает, что это не невозможно. О, и Google сделал то же самое для форка ядра Android Linux. О, и даже RedHat сделал то же самое.
 – 
Artem S. Tashkinov
19 Авг 2020 в 18:00
1
@ArtemS.Tashkinov: При чем здесь пространство пользователя? Я думал Линус отказывается ломать использование пространства, т.е. программное обеспечение, скомпилированное для Linux еще в 1991 году (которое не зависит от пользовательских библиотек), все еще должно работать. И разве ядро ​​2.6 не намного старше 3-5 лет?
 – 
Oskar Skog
19 Авг 2020 в 20:48
3
+1 Что мне нравится в этом ответе, так это то, как он практически показывает, почему изменение внутренней модели в конечном итоге заставит API измениться независимо от желаний разработчиков. Это также подчеркивает тот факт, что самая большая проблема в изменениях API с открытым исходным кодом — это трения между открытым исходным кодом и закрытым проприетарным кодом.
 – 
Philip Couling
19 Авг 2020 в 22:51