Ядро Linux: нарушение пользовательского пространства

Я начал думать об этой проблеме в контексте этикета в списке Linux Kernel Mailing. Являясь самым известным в мире и, возможно, самым успешным и важным проектом свободного программного обеспечения, ядро ​​Linux получает множество пресса. И основатель проекта и лидер, Линус Торвальдс, явно не нуждается в представлении здесь.

Линус иногда привлекает споры с его пламенем на LKML. Эти пламена часто, по его собственному признанию, делают с нарушением пространства пользователя. Это подводит меня к моему вопросу.

Могу ли я иметь какую-то историческую перспективу в отношении того, почему нарушение пользовательского пространства такое плохо? Насколько я понимаю, для нарушения пользовательского пространства потребуются исправления на уровне приложения, но неужели это плохо, если он улучшает код ядра?

Насколько я понимаю, политика, изложенная в Linus, заключается в том, что не нарушая пространства пользователя, козыри все остальное, включая качество кода. Почему это так важно, и каковы плюсы и минусы такой политики?

(Очевидно, что некоторые из них придерживаются такой политики, последовательно применяемой, поскольку у Линуса иногда есть «разногласия» с его лучшими лейтенантами на LKML именно по этой теме. Насколько я могу судить, он всегда в этом разбирается.)

3 Solutions collect form web for “Ядро Linux: нарушение пользовательского пространства”

Причина не историческая, а практическая. Существует много многих программ, которые работают поверх ядра Linux; если интерфейс ядра нарушает эти программы, всем потребуется обновить эти программы.

Теперь верно, что большинство программ фактически не зависят напрямую от интерфейсов ядра ( системные вызовы ), а только на интерфейсах стандартной библиотеки C ( обертки C вокруг системных вызовов). О, но какая стандартная библиотека? Glibc? uClibC? Dietlibc? Bionic? MUSL? и т.п.

Но есть также много программ, которые реализуют специфичные для ОС службы и зависят от интерфейсов ядра, которые не отображаются стандартной библиотекой. (В Linux многие из них предлагаются через /proc и /sys .)

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

Даже когда источник доступен, собрать все это может быть боль. Особенно, когда вы обновляете свое ядро, чтобы исправить ошибку с вашим оборудованием. Люди часто обновляют свое ядро ​​независимо от остальной части своей системы, потому что им нужна аппаратная поддержка. По словам Линуса Торвальдса :

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

Он также объясняет, что одной из причин сделать это сильным правилом является избежание аддикции, где вам нужно будет не только обновить другую программу, чтобы получить новое ядро ​​для работы, но также придется обновить еще одну программу, а другую, а другую , потому что все зависит от определенной версии всего.

Вполне нормально иметь четко определенную одностороннюю зависимость. Это печально, но неизбежно. (…) Что НЕ нормально – иметь двунаправленную зависимость. Если код HAL пользовательского пространства зависит от нового ядра, все в порядке, хотя я подозреваю, что пользователи будут надеяться, что это не будет «ядро недели», а скорее «ядро последних нескольких месяцев».

Но если у вас есть зависимость от TWO-WAY, вы ввернуты. Это означает, что вам нужно обновить блокировку, и это просто НЕ ПРИНИМАЕТСЯ. Это ужасно для пользователя, но, что еще важнее, для разработчиков это ужасно, потому что это означает, что вы не можете сказать «ошибка произошла» и делать такие вещи, как попытаться сузить ее с помощью деления пополам или аналогичного.

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

Официально ,

обратная совместимость для [системных вызовов, объявленных стабильными], будет гарантирована не менее 2 лет.

На практике, хотя,

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

Что чаще всего происходит, это интерфейсы, предназначенные только для аппаратных программ, в /sys . ( /proc , с другой стороны, который с момента введения /sys зарезервирован для услуг, не связанных с оборудованием, практически никогда не ломается несовместимыми способами.)

В итоге,

для прерывания пользовательского пространства потребуются исправления на уровне приложения

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

В любых взаимозависимых системах есть в основном два варианта. Абстракция и интеграция. (Я намеренно не использую технические термины). С Abstraction вы говорите, что когда вы звоните в API, который, хотя код API может измениться, результат всегда будет таким же. Например, когда мы вызываем fs.open() нам все равно, будет ли это сетевой диск, SSD или жесткий диск, мы всегда будем иметь открытый файловый дескриптор, с которым мы можем работать. С «интеграцией» цель состоит в том, чтобы обеспечить «лучший» способ сделать что-то, даже если путь изменится. Например, открытие файла может отличаться для общего сетевого ресурса, чем для файла на диске. Оба способа широко используются на современном рабочем столе Linux.

С точки зрения разработчиков это вопрос «работает с любой версией» или «работает с определенной версией». Отличным примером этого является OpenGL. Большинство игр настроены на работу с определенной версией OpenGL. Неважно, если вы компилируете из источника. Если игра была написана для использования OpenGL 1.1, и вы пытаетесь запустить ее на 3.x, вы не будете хорошо проводить время. На другом конце спектра некоторые вызовы, как ожидается, будут работать независимо от того, что. Например, я хочу вызвать fs.open() Я не хочу заботиться о том, какая версия ядра я fs.open() . Мне просто нужен файловый дескриптор.

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

С точки зрения сообщества, без действительно действительно веской причины, абстракция всегда лучше в сложной системе. Например, представьте, если fs.open() работал по-разному в зависимости от версии ядра. Тогда простая библиотека взаимодействия с файловой системой должна поддерживать несколько сотен различных методов «открытого файла» (или, вероятно, блоков). Когда выйдет новая версия ядра, вы не сможете «обновить», вам придется протестировать каждую отдельную программу, которую вы использовали. Ядро 6.2.2 (подделка) может просто сломать ваш текстовый редактор.

Для некоторых примеров реального мира OSX обычно не заботится о нарушении пользовательского пространства. Они чаще стремятся к «интеграции» над «абстракцией». И при каждом крупном обновлении ОС все происходит. Это не значит, что один способ лучше, чем другой. Это выбор и дизайнерское решение.

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

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

Итак, дизайнерское решение было принято для абстрактных системных вызовов, так что когда я делаю fs.open() он просто работает. Это означает, что поддержка fs.open долгое время после fs.open2() завоевала популярность.

Исторически это цель POSIX-систем в целом. «Вот набор вызовов и ожидаемых значений возврата, вы выясните середину». Опять же по причинам мобильности. Почему Линус выбирает использовать эту методологию, является внутренней для его мозга, и вы должны попросить его точно знать, почему. Если бы это был я, я бы выбрал абстракцию над интеграцией в сложной системе.

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

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

Недостатком является то, что ядро ​​должно хранить старый код и старые syscalls и т. Д. Навсегда (или, по крайней мере, в течение длительного времени после их использования).

  • Используется ли Unix бухгалтерами и другими не-программистами в AT & T в 70-х и 80-х годах?
  • Будущее OpenSolaris
  • Автозаполнение имен хостов при использовании SSH в файле истории
  • Как проект Linux Kernel отслеживал ошибки в ранние дни?
  • Почему resolv.conf записано без «e»?
  • Является ли Linux Unix?
  • Bash: Расширение истории внутри одинарных кавычек после двойной кавычки внутри одной строки
  • Строковые артефакты из истории в командной строке
  • как записать команду, выполняющую программу suid
  • Почему JFS так неясна?
  • Как узнать IP-адрес, с которого вошел пользователь?
  • Interesting Posts

    Создание USB-накопителя NON-UEFI 21 (или DVD)

    Записывать транскрипцию программы с перенаправленным вводом и выводом

    Группа ACPI / действие undefined: процессор / LNXCPU

    Не удается запустить NFS в Centos 7: не удалось вызвать вызов метода: нет такого файла или каталога

    Создание жестких ссылок – Разрешения?

    Centos – фоновые процессы

    Как заблокировать раскладку клавиатуры на экране входа в Gnome

    Postfix использует псевдоним интерфейса вместо основного интерфейса

    Добавить пользовательскую комбинацию клавиш (не работает)

    Как я могу перейти на gnome-shell 3.6 из 3.2?

    Можно ли показывать текущий номер строки истории при выполнении обратного поиска в bash?

    Могу ли я читать и писать в тот же файл в Linux, не перезаписывая его?

    Как подсчитать, сколько файлов принадлежит каждой комбинации пользователей / групп?

    Как вы можете вставлять рисунки с разным размером?

    Как отображать символы ширины юникода в gnome-терминале и т.д.

    Linux и Unix - лучшая ОС в мире.