Home    Решения    Услуги    Download    Публикации    Работа    Продукти    Документи
 

 

 
Print this page/Отпечатай тази страница  

Историята на Linux кърнъла
лично от Линус Торвалдс

The story of the Linux kernel

Линус Торвалдс обяснява какво прави Linux кърнъла добър

Резюме
В тази извадка от новата книга, издадена от O'Reilly & Associates "Open Sources: Voices from the Open Source Revolution" Линус Торвалдс изяснява някои ключови решения от архитектурата на Linux, които са довели до днешният вид на ядрото на операционната система.

"Open Sources" е колекция, издавана от O'Reilly Associates, написана от изявени личности в света на свободния софтуер като Eric Raymond, Richard Stallman, Brian Behlendorf, Larry Wall и много други.

Авторските права на откъса, публикуван тук принадлежат на O'Reilly & Associates (1999).

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




Linus Benedict Torvalds Днес Linux има милиони потребители, хиляди разработчици и разрастващ се пазар. Използва се в много отговорни системи - за контрол на роботизирани устройства или в космическите совалки. Бих искал да кажа, че съм знаел, че ще стане така и че всичко това е част от план за световно господство. Но всъщност аз самият съм изненадан. И все повече усещам прехода от един Linux потребител към сто Linux потребителя като преход от стотици Linux потребители до милион.

Linux успя, не защото основната цел бе да бъде широко преносим и широко достъпен, а защото беше изграден на основан на добри принципи за проектиране и на добър модел за развитие. Тази здрава основа направи междуплатформената преносимост и достъпност лесни за изпълнение.

Нека противопоставим за момент Linux и силно комерсиални проекти като Java или Windows NT. Вълнението около Java убеди много хора, че принципът "пиши веднъж, изпълнявай навсякъде" е достойна цел. Нека се прехвърлим във времето, когато все по-разнообразен хардуер се ползва за изчисления - нима тогава този принцип не изглежда важен. Sun обаче не са изобретили идеята "пиши веднъж, изпълнявай навсякъде". Преносимостта от много време е Свещения Граал на компютърната индустрия. Microsoft, например, първоначално се надяваха, че Windows NT ще бъде преносима операционна система и, че веднъж пусната на Intel платформа ще се прехвърли на RISC машините и изобщо в обкръжението на работните станции. Linux нямаше пъроначално толкова амбициозни цели. По ирония на съдбата, обаче именно Linux се оказа прекрасната среда за междуплатформен код.

Първоначално Linux имаше за цел само една архитектура - Intel 386. Днес Linux върви върху всичко от PalmPilots до работните станции Alpha и това е най-широко приетата операционна система в света. Ако напишете програма, която да върви под Linux, тогава за огромен брой машини тази програма ще бъде "написана веднъж и изпълнявана навсякъде". Интересно е да се хвърли поглед на решенията в дизайна на Linux и как усилията по разработването еволюираха така, че Linux успя да стане това, което не бе част от първоначалния замисъл.

Запазване на общата база
Linux е Unix-подобна операционна система, но не е версия на Unix. Това дава на Linux различно наследство в сравнение например с Free BSD. Имам предвид това, че: създателите на Free BSD започват с изходен код на Berkeley Unix и техния кърнъл директно произхожда от този изходен код. Тоест Free BSD е версия на Unix. И си е част родословното дърво на Unix. Linux, от своя страна, се стреми да предлага интерфейс, съвместим с Unix, но ядрото(кърнъла) е започнат от нищото, без използване на Unix сорс. Така Linux не е вариант на Unix, а е съвсем нова операционна система.

Наистна въобще не беше в мислите ми тази нова операционна система да върви и на други платформи в началото. Тогава имах нужда от нещо, което да върви на моето 386.

Сериозните усилия да направя кода на Linux кърнъла преносим започнаха с опитите да пусна Linux върху една Alpha на DEC. Това не беше първата, различна за Linux платформа.

Пионерите бяха една група програмисти, които пуснаха ядрото на Linux за Motorola 68K серията, който беше чипа на първите Sun, Apple, и Amiga компютри. Програмистите, които стояха зад този проект искаха да направят нещо наистина от ниско ниво, защото в Европа има страшно много хора, каквито са и обществото на потребителите на Amiga, които са особено разочаровани от идеята да използват DOS или Windows.

Докато Amiga потребителите могат да получат система вървяща на 68K, аз не мисля, че това именно е успешен дял за Linux. Те използваха същия подход, който използвах и аз, в първите дни на Linux: пишеха код от нaчало, опитвайки се да наподобят интерфейса. И получиха първата преносима за 68K Linux-подобна операционна система.

На пръв поглед това първо 68K Linux-ядро не помага с нищо при създаването на преносим между платформите Linux, но всъщност не е така. Когато започнах да мисля върху проблема за пускане на Linux върху Alpha аз трябваше да имам предвид това 68К ядро. Защото ако бях подходил пак по същия начин с Alpha-та щяхме да имаме трети различен вид Linux, който щеше да се нуждае от своя си собствена поддръжка. И дори това да е осъществимо от гледна точка на програмирането, то не е така по отношение на управлението му. Абсурдно е да си помисля, че бих могъл да координирам развитието на Linux ако това означава да следя дирите на всяка нова софтуерна база, която ще се генерира всеки път, когато някой поиска да пусне Linux върху нова архитектура. Вместо това поисках да направя система на обща база имайки вече Alpha, 68K и x86 базите.

И така основите на ядрото бяха пренаписани по това време. Но това пренаписване вече бе мотивирано от идеята как да се увеличи обществото от разработчици на Linux.

Микрокърнъли (микроядра)
Когато започнах да пиша Linux кърнъла трябваше да се науча как да напиша преносима, междуплатформена система. Конвенционалната мъдрост бе това, което ми подсказа идеята за архитектурата на база микроядра.

С монополитично ядро, каквото е Linux кърнъла, паметта се поделя на пространство за потребителя и пространство на ядрото. Пространството за ядрото всъщност е зареденият кърнъл-код плюс пространството заделено за операциите извършвани от него. Кърнъл-операциите включват разписания, управление на процеси, управление чрез сигнали, входно-изходни устройства, страниране и суапинг. Тъй като кърнъл-кода включва взаимодействия от ниско ниво с хардуера, монополистичния кърнъл се явява специфичен за конкретната архитектура.

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

Когато започвах работата по Linux през 1991 се считаше че преносимост ще се постигне чрез подхода с използването на микроядрата. Определено това би било любима тема за изследване от компютърните науки. Но аз съм прагматична персона и чувствах, че: 1) те са експиримент; 2) очевидно са по-сложни от монополистичните ядра; и 3) се изпълняват чувствително по-бавно. Скоростта е от значение в реалния свят на операционните системи и биха отишли доста долари и време за изследвния и оптимизиране на микроядрата така, че да са сравними по бързина с нормалния кърнъл. А най-забавното от всичко бе, че (ако сте чели някои статии по въпроса) докато изследователите правеха техните оптимизиращи еквилибристики за микрокърнъла, всъщност много от тях много по-лесно се прилагаха и върху нормалният кърнъл като го правеха още по-бърз.

Всъщност това ме кара да си мисля, че разработките за микрокърнъла бяха доста нечестен подход за получаване на повече долари за изследвания. Не искам да кажа, че непременно тези учени са нечестни. Може би те бяха просто глупави. Или заблудени. Казвам го съвсем от душа. Нечестността идва от интензивния натиск, който беше оказан върху изследователите да се занимават именно с темата - микрокърнъл. В изследователски лаборатории по компютърни науки се изучаваха микроядра, без да се изучава кърнъла по принцип. И всички бяха притискани да се занимават с това - дори хората, които правеха Windows NT. Когато тимът на NT разбра, че в крайна сметка нещата няма да станат с микроядра те трябваше да пият една студена вода заради тази си идея.

За щастие лично върху мен не бе осъществяван натиск да се занимавам с темата микрокърнъл. Университета в Хелзинки е работил върху темата операционни системи още от края на 60-те и хората там не гледаха на изследванията върху кърнъла като на нещо, което да си струва да се изследва повече. И бяха прави в едно - че след като основите на операционните системи (в частност и основите на Linux кърнъла) са добре известни още в началото на 70-те то тогава да правиш още нещо в тази област е оправдано само за упражнения за собствено удоволствие.

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

Разбира се, че моята работа е много близка до тази с изследвания с микрокърнъла, но основната страна на проблема е различната цел. Целите на изследванията на микрокърнъла бяха да се проектира теоретичен модел, който да бъде максимално преносим между всички възможни архитектури. С Linux аз нямах наум толкова възвишена цел. Аз се интересувах от преносимостта между реално съществуващите системи на днешния свят, а не на теоритичните такива.

Нормалност и преносимост
Проектът с Alpha започна през 1993 и ми отне година за да го завърша. Не всичко беше изцяло направено след тази година, но основите бяха готови. И докато това бе трудно, защото бе за първи път, то принципите , които се установяваха с тази работа, и които Linux следва оттогава насам, направиха същото нещо сега да е далеч по-лесно.

Linux ядрото не е написано така, че да върви на всяка архитектура. Аз реших, че ако архитектурата, която трябва да се ползва е в основата си достатъчно нормална и следва някои основни правила, то Linux безпроблемно би поддържала тази архитектура. Например, управлението на паметта може да е страшно различно на една машина и на друга. Четейки документацията за управлението на паметта на 68K, Sparc, Alpha и на PowerPC открих, че въпреки различята в детайлите има много общо в разделянето паметта на страници, кеширането и т.н. Управлението на паметта в Linux кърнъла може да бъде написано като общ знаменател между тези архитектури и тогава няма да е толкова трудно да се модифицира кода за това управление в специфичните за конкретната архитектура детайли.

Няколко допускания опростяват проблема като цяло. Например, ако кажем, че централния процесор трябва да ползва страниране на паметта, тогава е необходимо разширение - някакъв вид TLB (translation lookup buffer), който да казва на процесора как да планира виртуалната памет за ползване от самия него. Разбира се подобен TLB изглежда несигурна работа, но всъщност всичко, което се нуждаете да знаете е как да го напълните и как да го четете, когато трябва. Така в тази нормална архитектура трябва да се знаят само няколко машинно-зависими части на кърнъла, но повечето от кода е базиран на общи механизми чрез, които неща като TLB работят.

Често, когато архитектурата се отклонява от семплия дизайн в някои от детайлите това е обикновено именно заради лошо проектиране. Т.е. същите принципи, които те карат да заобикаляш спецификите за да постигнеш архитектурна независимост също те карат да заобикаляш проявленията на лошото проектиране и да се придържаш към оптимизиран общ дизайн. Накратко, аз се опитах да постигна златната среда между смесването на най-доброто от теорията и реалните факти от съвременните компютърни архитектури.

Кърнъла трябва да се пази здрав
С монополитичен кърнъл, какъвто е този на Linux, е важно да бъдем много предпазливи, когато допускаме нов код и нови свойства в кърнъла. Такова решение може да създаде проблеми в последствие.

Първото основно правило е да се избягват интерфейсите. Ако някой иска да добави нещо, което добавя нови системни интерфейси трябва да бъдем особено предпазливи. Давайки веднъж интерфейс на потребителите те ще започнат да програмират върху него, а започне ли някой да програмира върху него вие вече сте обвързан. Иска ли ви се да поддържате точно този интерфейс през целия живот на вашата система?

Друг тип код не създава толкова проблеми. Ако това не е интерфейс, а примерно дисков драйвер, няма какво толкова да му мислите. Можете просто да си добавите драйвера почти без риск. Ако linux не е имал този драйвер преди, добавянето му не само, че няма да навреди на тези, които ползват Linux, а и ще отвори Linux към нови потребители.

Казано с други думи трябва да се балансира. Добър ли е този инструмент? Наистина ли добавяме добри свойства? Понякога дори отговорите да са положителни, например заради лош интерфейс може да се окаже, че всичко се е оплело и нищо не може да се направи, нито сега, нито в бъдеще.

Например, приемете, че това е някакъв интерфейс за някава глупава файлова система, която не према имената на файловете да са по дълги от 14 символа. Това, което ви се иска да избегнете е това ограничение. В противен случай, когато поискате да разширите файловата система ще трябва да търпите това ограничение. По-лошото е, че програма, която поиска име на файл вероятно ще се срива, ако и дадете по-дълго име.

В момента единственият производител, който прави такова глупвао нещо е Microsoft. Всъшност за да прочетете DOS/Windows файл вие трябва да имате този нелеп интерфейс с единадесет символа, осем плюс три. С NT, която поддържа дълги имена, те трябваше да добавят цял завършен набор процедури, които да правят същите неща, които правят и другите процедури, които обаче не се справят с дългите имена. Ето пример за лош интерфейс, който създава проблеми в бъдеще.

Друг пример е това, което се случи с операционната система Plan 9. Те имаха наистина добра система за по-добро разделяне на процесите (простичък начин за разделяне на две и изпълнение по двата клона. Това разклонение, което Plan 9 нарича R-разклонение (SGI по-късно го назовава S-Proc) създава две отделни процесни пространства, които си поделят адресното пространство.

Linux прави същото с клонирането на системните повиквания , но те се прилагат подходящо. SGI и Plan9 решават, че програмите с два клона могат да поделят едно и също адресно пространство, но ползват отделни стекове. Нормално, когато се ползват еднакви адреси това означава едно място в паметта, но ако имаш стек-сегмент, който е отделен можеш да ползваш стек-базирани адреси, което всъщност е друга част от паметта и можеш да поделяш стек пойнтера без опасност от препълване на другия стек.

Тази хитрина обаче има лоша страна - главоболията с управлението на стековете. Толкова ужасни, че на практика излиза глупаво да се правят въобще. Те твърде късно се усетиха, че производителността отива по дяволите. Така се получи, че имаха програми, които ползваха интерфейс, който не можеше да бъде подобрен.

Докато нормалният производител може да си позволи да остави проектирането да плува по течението около самата архитектура, в случая с Linux аз не можех да си го позволя.

Това е друг случай, където насоките на развитието на Linux и правенето му бяха диктувани от един и същ подход. От рационална гледна точка, аз не бих могъл да насочвам множество разработчици внасящи интерфейси в ядрото. Не бих бил способен да запазя контрола върху кърнъла. Но от проектантска гледна точка това е правилно: да пазя кърнъла относително малък, както и броя на интерфейсите и другите придатъци минимален.

Разбира се Linux не е съвсем изчистен в това отношение. Linux има в наследство известен брой ужасни интерфейси от предишни варианти на UNIX. Така, че в някои случаи бих бил по-щастлив ако не трябваше да поддържам Unix-овия интерфейс. Но Linux е толкова изчистен, колкото може да бъде една операционна система започната от нищото. И ако искате да имате привилегията да сте в състояние да стартирате Unix приложение, трябва да се примирите с малко багаж повече. А и именно това бе жизнено важно за популярността на Linux тъй, че цената вероятно си струва.

GCC
Unix сам по себе си е страшно успялата приказка на правилата на преносимостта. Unix кърнъла, като много кърнъли е базиран на съществуването на C, който дава нужната преносимост. Същото е и с Linux. За Unix широко разпространите C компилатори на различни архитектури правят възможно използването на Unix върху тях.

Всички други проекти
на GNU групата за Linux
изглеждат незначителни в
сравнение с GCC. Той е това,
което истински ме
интересува.

Ето колко важни са компилаторите. Значението на компилаторите бе една от причините да реша да лицензирам Linux под GNU Public License (GPL). GPL е лиценза за GCC компилатора. Мисля, че всички други проекти на GNU групата за Linux изглеждат незначими в сравнение с GCC. Toй е това, което истински ме интересува. Голям брой от тях дори мразя страстно: Emacs-редактора е ужасен, например.

Накратко компилаторите са основна необходимост.

Сега, когато Linux кърнъла следва общо взето машинно-независима идеология, най-малкото за основните архитектури, преносимостта ще е възможна доколкото има добър компилатор на разположение. За новоизлюпените чипове не се притеснявам много по отношение на преносимостта между архитектурите. Тревожа се за компилаторите. Intel-ския 64-битов чип Merced, е очевиден пример, защото Merced е много различен откъм компилатор.

Преносимостта на Linux е много обвързана с факта, че GCC върви върху основните чип-архитектури.

Размисли за модулността
С Linix кърнъла стана ясно много бързо, че искаме система, която е колкото се може по-модулна. Модела на open-source разработките наистина го изискват, защото е невъзможно множество хора да работят в паралел. Много е болезнено да имаш хора, които работят по една и съща задача и да не си подхождат.

Без модулността аз трябва да преглеждам всеки файл след всяка промяна за да съм сигурен, че тази промяна няма да се отрази някъде другаде. Сега с модулността, когато някой ми изпрати patch за работа с някаква нова файлова система и аз не се доверявам на тези пачове, то мога да се облегна на факта, че доколкото никой не ползва тази файлова система, то това няма да се отрази на нищо друго.

С 2.0 кърнъла Linux наистина израстна много. Това бе момента, в който добавихме зареждаемите модули. Програмистите могат да работят по различни модули без риск от "интерференция". Аз мога да удържам контрола върху това, което се пише в кърнъла. И отново да управляваш хората или да управляваш кода води до едни и същи проектантски решения. За да запазим координацията между хората, работещи върху Linux се нуждаем именно от модулността. И от дизайнерска гледна точка това е правилното.

Тест за GPL
Другата страна на модулността е по-малко очевидна и по-проблематична. Това е run-time loading частта, която всички определят като нещо добро, но води до нови проблеми. Първият проблем е технически, но техническите проблеми са (почти) винаги най-лесни за решаване. По-важните проблеми са не-техническите. Например, в кой момент модул писан за Linux, следва да е под GPL.

Когато първият модулен интерфейс бе написан имаше хора, написали драйвери за SCO, чийто изходни кодове не искаха да разпространяват, както изисква GPL, но те нямаха нищо против да прекомпилират тези драйвери за Linux. От такава позиция по морални причини аз реших да не приемам GPL при подобни ситуации.

GPL изисква работа, произхождаща от проект под GPL, да бъде лицензирана също под GPL. За нещастие какво да се счита за произхождащ труд е много мъгливо понятие. В момента, в който напишеш един ред код като производен проект се явява проблема - част от какво е този ред код.

Реши се (или май аз постанових) обръщенията към системата да не бъдат разглеждани обвързано с кърнъла. Така всяка програма за Linux не е задължена да е под GPL. Това решение бе взето доста отдавна и аз дори добавих специално read-me за да съм сигурен, че всеки ще разбере. Заради това комерсиалните производители могат да пишат програми за Linux без да се тревожат за GPL.

Силата на Linux
е в обществото зад
него толкова, колкото
и в самият код.

Силата на Linux е в обществото зад него толкова, колкото и в самият код. Ако Linux бъде ограбена - ако някой направи и разпространява собственическа версия - привлекателността на Linux ще бъде загубена за тази собственическа версия.

Преносимостта днес
Linux днес постигна много от целите, които хората очакваха, че са достижими само чрез архитектурата на микрокърнъла.

Чрез конструиране на общия модел на кърнъла от общи елементи на различни архитектури, Linux-кърнъла получи премосимостта, която изискваше реализация на абстрактно ниво, без да плаща налог на микрокърнълите.

Благодарение на модулността, хардуерно-специфичния код може да се затвори в модул, запазвайки чисто ядрото на кърнъла, следователно и междуплатформено. Драйверите за устройствата са добър пример за това как кърнъл-модулите затварят хардуерните специфики в себе си. Това е златната среда между слагането на хардуерните специфики в ядрото, което води до много бърз, но не-междуплатформен кърнъл или пък оставянето им в областта на потребителите, което пък би довело до бавна и/или нестабилна система.

Бъдещето на Linux
Сигурен съм, че взехме правилното решение правейки кърнъла колкото се може по-малък. В този момент чистата истина е, че не си представям генерални обновявания на кърнъла. Успешният софтуерен проект трябва да постигне зрялост по някое време, след което стъпките на промените се забавят. Няма вече глобално нови неща, които да се добавят. По-важен е въпроса с разпространението на Linux към други нови системи.

Symmetric Multi-Processing (SMP) е една област, която ще се разработва. Версия 2.2 на Linux кърнъла ще подържа без проблем четири процесора и ще работим по подръжката на до 8 или 16 процесора. Поддръжката на повече от четири процесора е вече тук, но не съвсем. Да имаш повече от четири процесора сега е като да си дал пари за умрял кон. Затова това е нещо, което тепърва ще се усъвършенства.

Но ако някой иска да използва 64-процесорна машина той ще трябва да ползва специална версия на кърнъла, защото да добавя такава поддръжка в редовния кърнъл означава да намаля производителността на обикновените потребители.

Някои специфични за дадена област приложения ще продължат да провокират развитието на кърнъла. Web-сървърите са интересен проблем, защото това е един пример, който истински натоварва кърнъла. Дори опасен за мен, защото получавам толкова много обратна поща от хора, използващи Linux като web-сървър, че мога лесно да се заблудя и да оптимизирам кърнъла само за web-сървър. Трябва да не забравям, че това е важно приложение, но не е единствено.

Разбира се Linux не се използва с пълния му потенциал дори и от днешните web сървъри. Apache например не прави правилните стъпки в някои моменти.

Този вид оптимизация се забавя от ограниченията, които в мрежовата честотна лента. В момента можете да наситите десет мегабитова мрежа толкова лесно, че няма причини за оптимизация. Има начини да не насищате мрежата ако имате много CGI скриптове, които да вършат наистина здрава работа, но кърнъла с нищо не може да помогне. Това, което евентуално може да направи е директно да отговаря на запитвания на статични страници и да оставя по-сложните заявки на Apache.

Поуката от всички тези възможни бъдещи направления са, че аз искам Linux да бъде на ръба и дори мъничко оттатък, защото това, което е мъничко оттатък днес, е това, което ще е на десктопа ни утре.

Но най-вълнуващото развитие при Linux ще се случва не толкова около кърнъла, а около приложенията при потребителите. Промените в кърнъла изглеждат дребни сравнени с това, което предстои да се случва извън системата. От тази гледна точка колко интересен ще е Linux кърнъла в сравнение с това, което ще включва Red Hat 17.5 например или какво ще може Wine (Windows емулатор) след няколко години.

След петнадесетина години очаквам да се появи някой и да каже: хей, аз мога да правя всичко, което може и Linux, аз ще бъда стар и посредствен, а те ще кажат, че Linux беше направена за 386 и новите процесори имат нужда от нещо друго, интересно и различно. Дайте да изхвърлим тези стари Linux боклуци. Това казах и аз, когато направих Linux. И тогава в бъдещето те ще имат възможността да погледнат нашите сорсове, да ползват нашите интерфейси, да предагат съвместимост и ако това се случи аз ще бъда щастлив.

За автора:
Линус Торвалдс е създателят на Linux. Той работи в CA's Transmeta Corp. в Санта Клара по проект, който по неговите думи е "много готин". Женен е. Има две деца и един патент - Memory Controller for a Microprocessor for Detecting a Failure of Speculation on the Physical Nature of a Component being Addressed

Материалът е преведен и публикуван с незначителни съкращения.