Русский
Русский
English
Статистика
Реклама

Линус торвальдс

Перевод 30 лет Линукса. Интервью с Линусом Торвальдсом. Часть 1

04.05.2021 10:05:07 | Автор: admin


Тридцать лет назад Линусу Торвальдсу был 21 год, он был студентом Хельсинского университета. Именно тогда он впервые выпустил ядро Linux.Анонс этого события начинался так: Я делаю (свободную) операционную систему (просто в качестве хобби, большой и профессиональной она не будет). Три десятилетия спустявсе топ-500 суперкомпьютеров в мире работают под Linux, равно как и более 70% всех смартфонов. Linux явно стал и большим, и профессиональным.

В течение тридцати лет Линус Торвальдс руководил разработкой ядра Linux, вдохновив бесчисленное множество других разработчиков и опенсорсных проектов. В 2005 году Линус также создал Git, чтобы было проще управлять процессом разработки ядра, с тех пор Git превратился в популярную систему контроля версий, которой доверяют бесчисленные опенсорсные и проприетарные проекты.

Следующее интервью одна из серии бесед с лидерами опенсорса. Линус Торвальдс ответил на вопросы по электронной почте, поразмышляв о том, что он узнал за годы руководства большим опенсорсным проектом. В первой части акцент сделан на разработке ядра Linux и Git. [Linux] был личным проектом, который вырос не из какой-нибудь большой мечты создать новую операционную систему, объясняет Линус, а в буквальном смысле несколько спонтанно, ведь я изначально просто сам хотел разобраться во входах и выходах моего нового железа для ПК.

Что касается создания Git и его последующей передачи Джунио Хамано для дальнейшей доработки и поддержки, Линус отметил: Не собираюсь утверждать, что программирование это искусство, поскольку на самом деле это большей частью просто хорошая инженерия. Я горячо верю в мантру Томаса Эдисона об одном проценте таланта и девяноста девяти процентах упорного труда: почти все зависит от мелких деталей и ежедневной рутинной работы. Но есть и эта эпизодическая составляющая, называемая талант, этот хороший вкус, который сводится не только к решению какой-либо задачи, но и к стремлению решить ее чисто, аккуратно и да, даже красиво. У Джунио есть как раз такой хороший вкус.

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

Разработка ядра Linux


Джереми Эндрюс: Linux повсюду, он вдохновил целый мир опенсорса. Разумеется, так было не всегда. Вы прославились тем, что выпустили ядро Linux еще в 1991 году, скромно сообщив об этом в Usenet в разделе comp.os.minix. Десять лет спустя вы написали увлекательную и глубоко личную книгу под названием Ради удовольствия: Рассказ нечаянного революционера, где разобрали большую часть этой истории. В августе этого года Linux празднует тридцатилетие! Это захватывающе, поздравляем! В какой момент на вашем пути вы осознали, что Linux это уже гораздо больше, чем просто хобби?

Линус Торвальдс: возможно, прозвучит слегка потешно, но, на самом деле, это произошло очень рано. Уже к концу девяносто первого (и определенно к началу девяносто второго) Linux вырос значительно сильнее, чем я ожидал.


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

Думаю, X11 была портирована на Linux где-то в апреле девяносто второго (не верьте мне на слово, когда я припоминаю даты слиииишком давно дело было), а еще один серьезный шаг свершился, когда у системы вдруг появился GUI и целый новый набор возможностей.

Чтобы дать широкий контекст скажу, что в самом деле не начинал с наполеоновских планов или больших ожиданий. Это был личный проект, который вырос не из какой-нибудь большой мечты создать новую операционную систему, а в буквальном смысле несколько спонтанно, ведь я изначально просто сам хотел разобраться во входах и выходах моего нового железа для ПК.

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

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

Просто пример одного по-настоящему фундаментального аспекта: исходная лицензия на копирайт формулировалась примерно так: допускается распространение в виде исходников, но не за деньги.

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

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

К чему это привело: мало того, что люди стали распространять Linux на собраниях в группах пользователей Unix, но и в считанные месяцы появились первые дистрибутивы для дискет, например, SLS и Slackware.

По сравнению с теми первыми, по-настоящему фундаментальными изменениями, все дальнейшие можно считать пошаговыми. Разумеется, некоторые из этих шагов были весьма велики (систему взяла на вооружение IBM, под мою систему портировали Oracle DB, состоялись первичные коммерческие предложения Red Hat, Android расцвел на смартфонах, т.д.), но лично мне эти события все равно казались не столь революционными, как люди, которых я даже не знаю, уже используют Linux.

Дж. А.: Вы когда-нибудь сожалели, что выбрали именно такую лицензию, либо завидовали тому, какие деньги сделали другие люди и компании на вашем детище?


ЛТ: Ничуть.

Во-первых, мне вполне хватает. Я не баснословно богат, но я хорошо оплачиваемый программист, занимаюсь любимым делом, сам составляю себе расписание. Не бедствую.

Но не менее важно, что я на 100% уверен: именно такая лицензия во многом определила успех Linux (и Git, если уж на то пошло). Думаю, всем причастным гораздо приятнее знать, что все в равных правах, и никого такая лицензия не выделяет.

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

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

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

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

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

При таком подходе все честны. Включая меня. Каждый может сделать форк проекта и пойти своим путем, сказать: пока, Линус, у меня есть своя версия Linux, и ее поддержку я беру на себя. Я особенный только потому что и только до тех пор, пока люди доверяют мне за хорошо сделанную работу. Именно так и должно быть.

То, что каждый может поддерживать собственную версию вызывало у некоторых беспокойство по поводу версии GPLv2, но я вижу в этом достоинство, а не недостаток этой лицензии. Несколько парадоксально, но я считаю, что именно это и уберегло Linux от фрагментации: ведь каждый может сделать собственный форк проекта, и это нормально. На самом деле, именно в этом заключается один из ключевых принципов, на основе которых спроектированGit каждый клон репозитория это самостоятельный маленький форк, и люди (а также компании) ответвляют собственные версии, именно так и совершается весь процесс разработки.

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

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

Итак, отвечая на вопрос, я немного ушел в сторону, но считаю, что это важное отступление. Я решительно не жалею о том, какую лицензию выбрал, поскольку действительно считаю, что в GPLv2 заключается огромная часть успешности Linux.

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

Дж.А.: В наши дни, если кто-то выпускает исходный код по лицензии GPLv2, то делает это в основном ради работы с Linux. Как вы нашли лицензию, и сколько времени и сил у вас ушло на изучение других существующих лицензий?


ЛТ: В те времена в сообществе еще бушевали серьезные флеймы по поводу BSD и GPL (думаю, отчасти они разжигались из-за того, что у rms настоящий талант бесить людей), так что я встречал разные дискуссии на тему лицензирования только в разных новостных группах usenet, которые я читал (такие источники, какcomp.arch,comp.os.minixи т.д.).

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

Ласу гораздо активнее участвовал в дискуссиях по лицензированию и т.п., чем я.

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

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

Дж. А.: Каков ваш обычный день? Сколько времени вы тратите на написание кода, по сравнению с ревью кода и чтением/написанием электронной почты? Как вы находите баланс между личной жизнью и разработкой ядра Linux?

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

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

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

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

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

Дж.А.: Какова ваша рабочая обстановка? Например, комфортнее ли вам работать в затемненной комнате, где ничего не отвлекает, либо в комнате с видовым окном? Вы склонны работать в тишине или под музыку? Какое аппаратное обеспечение вы обычно используете? Выполняете ревью кода в vi, в окне терминала или в навороченной IDE? И есть ли такой дистрибутив Linux, который вы предпочитаете для данной работы?


ЛТ: не могу сказать, что у меня в комнате темно, но я действительно прикрываю шторами окно у рабочего места, поскольку яркий солнечный свет мне не нравится (правда, в этот сезон в Орегоне его и так не слишком много;). Так что никаких панорам, только (заваленный) стол с двумя 4k мониторами имощным ПК под столом. И еще пара ноутбуков под рукой, для тестирования и на случай, если какая-то работа прилетит мне в дороге.

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

Вся работа делается в традиционном терминале, хотя, я и не пользуюсь 'vi'. Я работаю с этим убогим micro-emacs, который не имеет ничего общего с emacs от GNU, с той оговоркой, что некоторые привязки клавиш у них похожи. Я привык работать с этим редактором еще в Хельсинском университете, будучи юнцом, и так и не смог от него отучиться, хотя, подозреваю, вскоре мне придется это сделать. Несколько лет я сварганил для него (очень ограниченную) поддержку utf-8, но редактор уже старый, и во всех его аспектах сквозит, что написан он был в 1980-е, а та версия, которой пользуюсь я это форк, не поддерживаемый с середины 90-х.

В Хельсинском университете этот редактор использовался, поскольку он работал под DOS, VAX/VMSиUnix, почему и мне довелось с ним познакомиться. А теперь он просто вшит мне в пальцы. На самом деле, давно пора переключиться на какую-то альтернативу, которая исправно поддерживается и как следует воспринимает utf-8. Пожалуй, попробую 'nano'. Мой же наспех слепленный антикварный мусор работает на том уровне вполне приемлемо, что у меня не возникало острой нужды переучивать мои старые пальцы на новые фокусы.

Итак, моя настольная рабочая среда весьма безыскусна: открыто несколько текстовых терминалов, еще браузер с почтой (плюс еще несколько вкладок, в основном с техническими и новостными сайтами). Я хочу, чтобы значительная часть рабочего стола была свободна, поскольку привык работать с достаточно большими окнами терминалов (100x40 можно сказать, таков у меня исходный размер окна по умолчанию), и у меня бок о бок открыто несколько окон терминала. Поэтому работаю с двумя мониторами по 4k.

На всех моих машинах я использую Fedora, не потому, что этот дистрибутив для меня однозначно предпочтителен, а потому, что я к нему привык. Меня не особо волнует выбор дистрибутива, я расцениваю дистрибутив в основном как вариант установки Linux на машине, как среду, в которой настроены все мои инструменты, так, чтобы я мог просто заменить ядро и сосредоточиться на работе с ним.

Дж. А.: Публичное обсуждение разработки ядра происходит впочтовой рассылке по ядру Linux, и трафик там запредельный. Как вы успеваете разгребать столько почты? Вы исследовали другие решения для совместной работы и коммуникации вне почтовой рассылки, либо простая почтовая рассылка чем-то идеально подходит для той работы, которую вы делаете?

ЛТ: О, я не читаю саму рассылку, посвященную разработке ядра, годами не читал. Там слишком много всего.

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

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

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

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

Причем, модель с почтовой рассылкой (и сопровождающими ее инструментами) в самом деле работает очень хорошо. Я не о том, что люди не пользуются иными средствами коммуникации кроме электронной почты (имею в виду и личные переговоры, и участие в почтовых рассылках): многим очень нравятся различные чаты в режиме реального времени (традиционный вариант IRC). Причем, хотя это и никогда не было моим коньком, очевидно, что многим нравится метод мозгового штурма. Но модель с списком рассылки, используемым в качестве архива работает очень хорошо, и бесшовно сшивается как с рассылкой патчей от разработчика к разработчику в электронных сообщениях, так и с отправкой отчетов по проблемам в виде электронной почты.

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


Дж.А.: Я пристально следил за разработкой ядра на протяжении примерно десяти лет,вел на эту тему блог в KernelTrap и писал о новых возможностях по мере их развития. Бросил заниматься этим примерно к моменту выхода версии ядра 3.0, выпущенной спустя 8 лет, когда выходили версии с номерами 2.6.x. Можете ли резюмировать, какие наиболее интересные события произошли с ядром после релиза версии 3.0?

ЛТ: Эх. Это было так давно, что я даже не знаю, с чего начать резюмировать. Прошло уже десять лет с момента выхода версии 3.0, и за это десятилетие мы успели внести много технических изменений. Архитектура ARM выросла, и ARM64 стала одной из наших основных архитектур. Много-много новых драйверов и новая базовая функциональность.

В любом случае, что самое интересное за последнее десятилетие как нам удалось удержать действующую модель разработки по-настоящему ровной, и что в ней не изменилось.

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

Мы затеяли всю историю с привязкой релизов ко времени и с окном по сведению патчей (merge window) во времена 2.6.x, поэтому сама эта инициатива не нова. Но именно в 3.0 последние реликты у номера есть значение были выброшены на свалку.

У нас была и случайная схема нумерации (в основном до версии 1.0), у нас была целая модель нечетные минорные номера соответствует версии ядра, которая находится в разработке, четные означают стабильное ядро, готовое к продакшену, после чего в версиях 2.6.x мы перешли к модели с привязкой релизов по времени. Но у людей по-прежнему оставался вопрос Что должно произойти, чтобы увеличился мажорный номер. И в версии 3.0 было официально объявлено, что четный мажорный номер версии не несет никакой семантики, и что мы всего лишь стараемся придерживаться простой нумерации, с которой было бы удобно обращаться, и которая бы чрезмерно не разрасталась.

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

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

Дж.А.: На настоящий момент последний релиз 5.12-rc5. Как стандартизирован процесс релизов? Например, изменения какого рода попадают в -rc1, по сравнению с -rc2 и так далее? И в какой момент вы решаете, что очередной релиз готов к официальному выходу? Что происходит, если вы ошиблись, и после финального релиза приходится серьезно отойти назад, и как часто это случается? Как этот процесс развивался с годами?

ЛТ: Выше я на это уже указывал: сам процесс в самом деле хорошо стандартизирован, и остается таким на протяжении последнего десятилетия. Перед этим произошло несколько серьезных потрясений, но с 3.0 он работает практически как часы (на самом деле, это началось еще на несколько лет ранее во многих отношениях переход на Git положил начало современным процессам, и потребовалось время, прежде, чем все к этому привыкли).

Поэтому у нас была такая каденция с двухнедельным окном по сведению патчей, за которым следует примерно 6-8 недель, затрачиваемых на изучение кандидатов для релиза; думаю, такие циклы поддерживаются уже на протяжении примерно 15 лет.

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

Затем цикл повторяется поэтому релизы у нас происходят примерно с десятинедельным интервалом.

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

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

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

Дж.А.: В прошлом ноябре, по вашим словам, вас впечатлили новые чипсеты ARM64 от Apple, поставленные в некоторых из их новых компьютеров. Вы следите за этими разработками, чтобы поддерживать их под Linux? Вижу, workбыладобавлена в for-next. Вероятно ли, что Linux будет грузиться на оборудовании Apple MacBook уже с появлением готовящегося ядра 5.13? Станете ли вы одним из ранних пользователей? Насколько велика для вас важность ARM64?

ЛТ: я очень эпизодически проверяю, как с этим дела, но пока там все на очень раннем этапе. Как вы правильно отметили, самый ранний вариант поддержки, вероятно, будет добавлен в ядро 5.13, но учитывайте пожалуйста, что мы в самом начале пути, и аппаратное обеспечение Apple пока еще не годится дляполезной работыпод Linux.

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

Но улучшилось не только аппаратное обеспечение Apple сама инфраструктура для arm64 значительно выросла, и ядра процессора изменились от ни о чем до вполне конкурентоспособной альтернативы для серверного пространства. Еще не так давно серверное пространство arm64 представляло собой весьма унылое зрелище, но процессоры Graviton2 от Amazon и Altra от Ampere оба основаны на значительно улучшенной версии ARM Neoverse IP гораздо лучше альтернатив, имевшихся на рынке несколько лет назад.

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

На самом деле могу сказать, что хотел машину с ARM гораздо дольше, еще в подростковые годы, причем, по-настоящему желанна была Acorn Archimedes, но из соображений цены и доступности пришлось удовлетвориться Sinclair QL (процессор M68008), а затем, конечно же, через несколько лет я сменил ее на i386 PC.

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

Дж.А.: есть ли в ядре какие-то аспекты, которые сделаны не лучшим образом, но, чтобы поправить их как следует, пришлось бы полностью переписывать код? Иными словами, ядру 30 лет, и за эти 30 лет значительно изменились наши знания, языки программирования аппаратное обеспечение. Если бы сейчас вы переписывали ядро с нуля, то что бы вы в нем изменили?

ЛТ: на самом деле, намвесьмахорошо удавалось даже целиком переписывать некоторые вещи, если была такая необходимость, поэтому все детали, которые казались необезвреженными бомбами, давным-давно переписаны.

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

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

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

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

Дж.А.: Как насчет хотя бы частично переписать ядро на Rust, языке, который разрабатывался именно с прицелом на производительность и безопасность? Есть ли пространство для улучшения в таком ключе? Как вы считаете, возможно ли, чтобы другой язык, например, Rust, заменил C в ядре?


ЛТ: Увидим. Не думаю, что Rustзакрепится в самой основе ядра, но писать на нем отдельные драйверы (или, может быть, целые подсистемы драйверов) не скажу, что это совершенно невероятно. Может быть, он и для файловых систем подойдет. Поэтому, скорее не заменить C, а дополнить наш код на C там, где это целесообразно .

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

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

Дж.А.: Есть ли в ядре какие-либо конкретные элементы, которыми вы лично особенно гордитесь?

ЛТ: выдающиеся части, которые мне хочется лишний раз подчеркнуть это уровень VFS (виртуальная файловая система) (и поиск имени пути в частности) и наш код виртуальной машины. Первое просто потому, что в Linux некоторые из этих фундаментальных вещей (поиск имени файла по-настоящему базовая функциональность в операционной системе) выполнимы намного лучше, чем во многих других ОС. А второе в основном потому, что мы поддерживаем более 20 архитектур, и по-прежнему делаем это при помощи в основном унифицированного уровня виртуальной машины, что, на мой взгляд, весьма впечатляет.

Но, в то же время, все это во многом проистекает из какая из частей ядра вам наиболее интересна. Ядро достаточно велико, чтобы разные разработчики (и разные пользователи) просто придерживались разных мнений по поводу того, что в нем наиболее важно. Некоторым кажется, что планирование задач наиболее захватывающая функция ядра. Другим нравится вникать в тонкости драйверов устройств (а у нас таких много). Лично я сильнее вовлечен в работу над VM и VFS, поэтому, естественно, указываю на них.

Дж.А.: Я нашел вот такое описание поиска имени пути, и он сложнее, чем я ожидал. Почему реализация этой функции в Linux настолько лучше, чем в любых других операционных системах? И что для вас означает лучше?

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

Но на самом деле очень сложно добиться, чтобы это работало как следует. Именно потому, что поиск имени пути все время происходит буквально везде, и поэтому данная задача критически сказывается на производительности; кроме того, это именно та область, в которой требуется хорошо масштабироваться при работе в средах SMP, блокировки при выполнении таких задач сопряжены с немалой сложностью. А вы хотите свести к минимуму какие-либо операции ввода/вывода, поэтому кэширование это очень важно. На самом деле, поиск имени пути настолько важен, что его нельзя выполнять на низком уровне файловой системы, ведь у нас более 20 различных файловых систем, и реализация в каждой из них собственных механизмов кэширования и блокировок стала бы подлинной катастрофой.

Итак, одна из основных задач, решаемых на уровне VFS это обработка всего кэширования и всех блокировок, связанных с компонентами имени пути, а также с обработкой всех операций, касающихся сериализации и обхода точек монтирования, причем, все это делается в основном при помощи неблокирующих алгоритмов (RCU), а также с применением весьма умных сущностей, напоминающих блокировки (блокировка lockref, предусмотренная в Linux это очень особенная спин-блокировка с подсчетом ссылок, буквально предназначенная для кэширования dcache, и, в принципе, это специализированный механизм подсчета ссылок, учитывающий блокировки, который в определенных типичных ситуациях может выполнять исключение блокировок).

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

Причем, в этом Linux успешнее, чем какая-либо другая операционная система, и это не мешает ему хорошо масштабироваться даже на машинах с тысячами CPU. Даже когда этим машинам приходится обращаться к одним и тем же каталогам (скажем, к корневому каталогу или домашнему каталогу проекта приходится одновременно обращаться даже в приложениях с сильно развитой многопоточностью, а такое по-поточное поведение не поддается какому-либо распределению).

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

Дж.А.: Прошлый год тяжело дался всему миру. Как пандемия COVID-19 повлияла на процесс разработки ядра Linux?

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

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

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



Облачные серверы от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Перевод 30 лет Линукса. Интервью с Линусом Торвальдсом. Часть 2

06.05.2021 14:05:14 | Автор: admin


Первая часть интервью.

Распределенная система контроля версий Git


Дж.А.: Linux только первая из ваших работ, глобально повлиявших на мир опенсорса. В 2005 году вы также создали Git, исключительно популярную распределенную систему контроля версий. Вы быстро перенесли дерево исходников ядра Linux из проприетарного хранилища Bitkeeper в новоиспеченный Git, который сделали опенсорсным, и в том же году передали поддержку Git Джунио Хамано. История этих событий увлекательна, расскажите, что побудило вас передать этот проект так быстро, и как вы нашли и выбрали Джунио?

ЛТ: Итак, ответ на этот вопрос состоит из двух частей.


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

Итог: я занимаюсь Linux более 30 лет (до годовщины первого релизаеще остается пара месяцев, но работать над тем, что впоследствии превратилось в Linux, я стал уже более 30 лет назад), и все это время занимаюсь его поддержкой. Но Git? Я даже не думал о том, чтобы поддерживать его в долгосрочной перспективе. Он мне определенно нравится, и я, конечно, считаю, что это наилучшая из имеющихся систем управления исходниками, но она не является моей большой любовью и увлечением, если вы понимаете, о чем я.

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

Таков контекст.

Что касается Джунио на самом деле, он один из первых, кто реально занялся разработкой Git. Первые изменения от него пришли мне в пределах нескольких дней после того, как я выложил в общий доступ самую первую (и весьма сырую) версию Git. Поэтому Джунио причастен к этому проекту, можно сказать, с самых первых дней Git.

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

Не хочу заявлять, что программирование это искусство, поскольку на самом деле программирование это в основном хорошая инженерия. Я глубоко верю в мантру Томаса Эдисона про один процент таланта и девяносто девять процентов усердия; практически вся суть успеха заключается в мелких деталях и ежедневной рутинной работе. Но, все-таки, иногда приходится проявить вдохновение и тот самый хороший вкус, то есть, не просто решить задачу, а решить ее чисто, аккуратно и да, даже красиво.

Вот у Джунио такой хороший вкус нашелся.

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

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

Дж.А.: Доводилось ли вам когда-либо делегировать кому-то поддержку, а потом понять, что это решение было ошибочным?

ЛТ: структура нашей работы по поддержке никогда не была настолько черно-белой или негибкой, чтобы это доставляло нам какие-либо проблемы. На самом деле, маловероятно, что мы даже когда-нибудь попытаемся тщательно документировать процедуру поддержки. Да, у нас есть файл MAINTAINERS, но он создан для того, чтобы можно былонайтинужных людей, это в самом деле не знак какого-то исключительного обладания.

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

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

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

Поскольку во многих других проектах использовались такие инструменты как CVS или SVN фундаментально некоторые люди действительно становятся особенными и пользуются обладанием, которое приходит вместе с этим статусом. В мире BSD этот феномен называется бит подтверждения (commit bit): это разряд, обладатель которого имеет право фиксировать код в центральном репозитории (или, как минимум, некоторых его частях).

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

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

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

Дж.А.: Впечатляли ли вас когда-нибудь новые возможности Git, включали ли вы их в свои рабочие процессы? Можете ли назвать такие фичи, которых, на ваш взгляд, в Git до сих пор не хватает?

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

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

Итак, для меня Git всегда был хорош, но со временем стал только лучше.

Значительныеулучшения связаны с тем, насколько удобнее стало регулярным пользователям работать с Git. Во многом благодаря тому, что люди разобрались, как в Git устроен поток задач, и просто привыкли к нему (оноченьотличается от CVS и других аналогов, к которым люди привыкли ранее), но и сам Git стал гораздо приятнее в использовании.



Облачные серверы от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Перевод Связные списки, трюки с указателями и хороший вкус

09.12.2020 00:05:51 | Автор: admin
В интервью на TED 2016 (14:10) Линус Торвальдс рассказывает о хорошем стиле программирования. В качестве примера приводит два варианта удаления элементов из односвязных списков (см. ниже). В первом варианте есть специальный случай, а в другом нет. Линус предпочитает второй.

Его комментарий:

[...] Не надо размышлять, почему здесь нет оператора if. Важно посмотреть на задачу с другой стороны и переписать её так, чтобы особый случай исчез и стал обычным случаем, и это хороший код. Л.Торвальдс

В качестве примера Линус показывает достаточно простой псевдокод в стиле Си. Но не даёт концептуального объяснения. Поэтому не сразу понятно, как работает косвенный указатель.

Подробно разберём это решение и его преимущества. В качестве бонуса показано не только удаление, но и вставка элемента через косвенную адресацию.

Код


Базовая структура данных для односвязного списка целых чисел показана на рис.1.


Рис. 1. Односвязный список из целых чисел

Числа это произвольно выбранные целочисленные значения, а стрелки соответствуют указателям: head это указатель типа IntListItem*, все блоки являются экземплярами структуры IntListItem, каждый со своей переменной (nextв коде) типа IntListItem*, которая указывает на следующий элемент.

Реализация структуры данных на Си:

struct IntListItem {    int value;    struct IntListItem* next;};typedef struct IntListItem IntListItem;struct IntList {    IntListItem* head;};typedef struct IntList IntList;

Также (минимальный) API:

/* The textbook version */void remove_cs101(IntList* l, IntListItem* target);/* A more elegant solution */void remove_elegant(IntList* l, IntListItem* target);

Теперь рассмотрим реализации remove_cs101() и remove_elegant(). Код примеров не противоречит псевдокоду из примера Линуса, но компилируется и запускается.

Базовая версия



Рис. 2. Концептуальная модель структуры данных списка в базовом алгоритме

void remove_cs101(IntList *l, IntListItem *target){    IntListItem *cur = l->head, *prev = NULL;    while (cur != target) {        prev = cur;        cur = cur->next;    }    if (prev) {        prev->next = cur->next;    } else {        l->head = cur->next;    }}

В стандартном подходе два указателя обхода cur и prev, которые отмечают текущую и предыдущую позицию обхода в списке соответственно. cur начинает с головы списка head и продвигается вперёд, пока цель не будет найдена. В свою очередь, prev начинается с NULL и впоследствии обновляется на предыдущее значение cur при каждом следующем продвижении вперёд. Когда цель найдена, алгоритм проверяет, не равен ли prev нулю. Если так, то cur указывает на первый элемент в списке, и в этом случае удаление означает перемещение головы списка вперёд.

Более элегантное решение


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

void remove_elegant(IntList *l, IntListItem *target){    IntListItem **p = &l->head;    while ((*p) != target) {        p = &(*p)->next;    }    *p = target->next;}

В коде применяется косвенный указатель p, содержащий адрес указателя на элемент списка, начиная с адреса head. В каждой итерации этот указатель расширяется, чтобы включить адрес указателя на следующий элемент списка, то есть адрес элемента next в текущем IntListItem. Когда указатель на элемент списка (*p) равен target, мы выходим из цикла поиска и удаляем элемент из списка.

Как это работает?


Косвенный указатель p даёт два концептуальных преимущества:

  1. Позволяет интерпретировать связный список таким образом, что указатель head становится неотъемлемой частью структуры данных. Это устраняет необходимость в специальном случае для удаления первого элемента.
  2. Также позволяет оценить состояние цикла while без необходимости отпускать указатель, указывающий на target. Это позволяет изменять указатель на target и обходиться одним итератором, в отличие от prev и cur.

Рассмотрим каждый пункт по очереди.

Интеграция указателя head


Стандартная модель интерпретирует связный список как последовательность экземпляров IntListItem. Начало последовательности можно получить с помощью указателя head. Это приводит к концептуальной модели, показанной выше на рис.2. Указатель head просто рассматривается как дескриптор для доступа к началу списка. prev и cur являются указателями типа IntListItem* и всегда указывают на элемент или NULL.

Элегантная реализация использует схему косвенной адресации, которая даёт другое представление о структуре данных:


Рис. 3. Концептуальная модель структуры данных списка в более элегантном решении

Здесь p представляет тип IntListItem** и содержит адрес указателя на текущий элемент списка. Когда указатель продвигается вперёд, его адрес меняется на следующий элемент.

В коде это выглядит как p = &(*p)->next:

  1. (*p): разыменовать адрес указателя на текущий элемент списка.
  2. ->next: снова разыменовать этот указатель и выбрать поле с адресом следующего элемента.
  3. &: взять адрес этого поля (то есть получить указатель на него).

Это соответствует интерпретации структуры данных, где список представляет собой последовательность указателей на элементы IntListItem (рис.3).

Последний штрих


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

Если p содержит адрес указателя на элемент списка, сравнение в цикле поиска становится таким:

while ((*p) != target) {    ...}

Цикл поиска завершится, если (*p) равно target, и как только это произойдёт, мы всё равно сможем изменить (*p), так как удерживаем его адрес p. Таким образом, несмотря на итерацию цикла до конца, сохраняется дескриптор (адрес поля next или указатель head), который можно использовать для непосредственного изменения указателя на элемент.

Вот почему мы можем изменить входящий указатель на элемент, чтобы он указывал на другое место, используя *p = target->next, и поэтому нам не нужны указатели обхода prev и cur для удаления элемента.

Новое применение


Оказывается, ту же идею можно применить для крайне лаконичной реализации ещё одной функции в связных списках: insert_before(), то есть вставки данного элемента перед другим.

Вставка перед существующим элементом


Во-первых, добавим следующую декларацию в list.h:

void insert_before(IntList *l, IntListItem *before, IntListItem *item);

Функция возьмёт указатель на список l, указатель перед элементом в этом списке и указатель на новый элемент списка, который функция вставит перед ним.

Быстрый рефакторинг


Прежде чем двигаться дальше, оформим цикл поиска в отдельную функцию:

static inline IntListItem **find_indirect(IntList *l, IntListItem *target){    IntListItem **p = &l->head;    while ((*p) && (*p) != target) {        p = &(*p)->next;    }    return p;}

и используем её в remove_elegant():

void remove_elegant(IntList *l, IntListItem *target){    IntListItem **p = find_indirect(l, target);    *p = target->next;}

Реализация insert_before()


Используя find_indirect(), легко реализовать insert_before():

void insert_before(IntList *l, IntListItem *before, IntListItem *item){    IntListItem **p = find_indirect(l, before);    *p = item;    item->next = before;}

Особенно радует цельная семантика для крайних случаев: если before указывает на заголовок списка, новый элемент будет вставлен в начало, если before является нулевым или недействительным (то есть не существует в l), новый элемент будет добавлен в конце.

Заключение


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

Итак, возвращаясь к первоначальному замечанию Линуса: это показатель хорошего вкуса? Трудно сказать. Но явно налицо творческое и очень элегантное решение хорошо известной задачи.
Подробнее..

Линус Торвальдс остался недоволен рядом моментов в использовании Rust для Linux

15.04.2021 14:13:15 | Автор: admin

В прошлом году разработчики ядра Linux предложили использовать Rust для нового встроенного кода. В марте 2021 года эта идея была частично реализована в состав ветки linux-next, на которой будет базироваться Linux 5.13, включили начальный набор компонентов для разработки драйверов устройств на Rust.

Тогда же была опубликована документация по использованию Rust в ядре Linux с практическими примерами. Изначально Торвальдс не выступал резко против нововведений (не делает этого он и сейчас). Заявил лишь, что нужно проверить, как все эти новинки работают на практике. Сейчас Линус Торвальдс провел рецензирование патчей с реализацией возможности создания драйверов на Rust для Linux и высказал ряд критических замечаний.

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

Вторая проблема, по словам Торвальдса использование вычислений с плавающей запятой или 128-битными типами, что не является допустимым для таких окружений, как ядро Linux. Это даже более критично, чем предыдущий момент, поскольку базовая библиотека Rust представляет собой один большой blob в ней нельзя запросить лишь избранные возможности, оставив остальные без внимания. Использовать приходится все подряд, так что предотвратить использование той либо иной проблемной функциональности не получится. Решить можно и эту проблему, но лишь путем внесения изменения в компиляторе rust и сопутствующие библиотеки, притом, что у команды нет четкой стратегии по реализации модульности библиотек языка.

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

Как бы там ни было, но Rust-у в Linux явно быть. Так, корпорация Google уже заявила о намерении принять участие в инициативе по продвижению поддержки Rust в ядро Linux. Компания привела примеры целесообразности внедрения Rust для борьбы с проблемами, которые возникают из-за ошибок при работе с памятью. Представители компании также считают, что Rust вполне готов присоединиться к C, став еще одним языком разработки компонентов ядра Linux.

Компания подготовила начальный прототип написанного на Rust драйвера для механизма межпроцессного взаимодействия Binder. Он, по мнению авторов этого проекта, даст возможность провести детальное сравнение производительности и безопасности реализаций Binder на C и Rust. Эта работа еще не завершена, но уже подготовлены прослойки для использования базовых абстракций функциональности ядра, которые нужны для работы Binder.

Ну и еще один шаг со стороны Google признание Rust в качестве списка языка разработки Android. Его добавили в список языков разработки Android для усиления защищенности последнего, плюс для продвижения приемов безопасного программирования и повышения выявления проблем при работе с памятью в Android. Около 70% из всех опасных уязвимостей, которые выявлены в Android, вызваны ошибками при работе с памятью. Использование Rust дает возможность снизить риск появления уязвимостей, которые вызваны ошибками при работе с памятью, включая обращение к области памяти после ее освобождения и выход за границы буфера.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru