C, PHP, VB, .NET

Дневникът на Филип Петров


* Исторически аспект за формирането на понятието „Операционна система“

Публикувано на 12 април 2018 в раздел Информатика.

При първите компютри за решаването на всеки нов проблем се е изисквала фундаментална промяна на цялата система. При механичните компютри това е означавало реално да се създаде нов хардуер. След 1924 г. започва все по-честа употреба на „бананови връзки“ (промяна на окабеляването и съответно програмната логика чрез преместването електрически кабел от една връзка в друга чрез жак). Въпреки тези улеснения, нуждата от физическа промяна в системата е била основна спирачка за високо бързодействие на компютри, които трябва да изпълняват повече от една програма. След въвеждането на регенеративна оперативна памет от Джон Атанасов (1937 – 1942 г.) започва да се появява теоретична възможност за цифрово програмиране на компютритe, т.е. да могат да решават различни задачи без да има нужда от промяна в хардуера им.

Първият цифрово програмируем компютър е Колосус, който започва да работи по дешифрирането на военни съобщения през 1944 г.  Може би най-фундаменталният труд от теоретична гледна точка е архитектурата на Джон Фон Нойман през 1945 г., която дава практическа реализация на идеите на Алан Тюринг от 1936 г. за компютърна програма, която се запазва в паметта на самия компютър. Първият компютър, който работи по архитектурата на Нойман е експерименталният „Manchester Baby” от 1948 г., който прераства в практически приложим проект Manchester Mark I през 1949 г. По-популярен за историята обаче остава проекта EDSAC от 1949 г. на университета в Кембридж.

Файлова система

Освен за обработка на информацията, важна функция на повечето компютри е и нейното запазване. Още от зората на компютрите са се използвали различни подходи докато постепенно се формира понятието „файлова система“. Преди 1961 г. то се е използвало основно за „организиране и запазване на текстови документи“ (обикновено подредени в папки). Използвайки това като аналогия, подобна организация се пренася и при дигиналните носители на информация, като например магнитните ленти. Много бързо се въвеждат стандарти за складиране на информацията на дигитален носител, което е модерното разбиране за „файлова система“ (днес популярни са например UFS, FAT, FAT32, NTFS, EXT3 и др.). Използването на подобни стандарти прави възможно пренасянето на данни от един компютър към друг – достатъчно е компютъра, който чете файловете от носителя на информация, да разполага със софтуер, който работи по дадения стандарт.

Драйвери за работа с различни периферни устройства

Отделно от това, постепенното натрупване на компютърен хардуер в практиката довежда до още един основен проблем – неговото унифициране. Естествено е при създаване на нова компютърна система инженерите да се стремят да преизползват опит, готови схеми и части от предишна такава. Проблем обаче има при различни екипи от различни инженери. Първоначално е било невъзможно например печатащата част от една компютърна архитектура (един вид компютър) да бъде пренесено на друга. Причината за това е, че комуникацията между централния процесор и периферното устройство е ставала по строго специфични за конкретната архитектура правила. Желанието за осъществяване на по-добра преносимост на елементи от една компютърна конфигурация в друга довежда до идеята за създаване на абстртракция вътре в архитектурите и формирането на т.нар. „интерфейси“ – унифицирани правила за комуникация през системната шина между основната част на компютъра (централен процесор и оперативна памет) и неговата периферия. Така постепенно започва да става възможно едно периферно устройство да бъде пренесено от една компютърна система на друга – достатъчно е само новата система да се снабди с програмен код, който преработва изхода от програмите в достъпен за периферното устройство формат (и обратно) – нещо, което днес наричаме „драйвер“. Именно колекцията от драйвери за различни устройства при различни компютърни архитектури и постепенното им обединяване във все по-унифициран програмен продукт е важна и основна функция на всяка съвременна ОС. Идеята е програмистите да не пишат нов програмен код за всяко различно устройство – достатъчно е да напишат код, който е стандартен за операционната система, под която работят, и да оставят ОС „да преведе“ техните команди на езика на съответното устройство. Процесът на унификация на периферни устройства и тяхното типизиране започва още от зората на компютрите и продължава до днес. Основната причина да е постоянен проблем е децентрализацията на пазара и липсата на централен планиращ орган – нещо, което от друга страна е огромно икономическо предимство, довело до бурното развитие на компютърната техника през годините.

Batch processing

Първите цифрово препрограмируеми компютри са били еднозадачни. При тях задачите се подават линейно една след друга (например чрез т.нар. „перфокарти“ или магнитни ленти). След прочитане на поредица от логически свързани последователности от команди (програма) се отчита краен резултат от изчисленията, машината се „нулира“ (връща в изходна позиция) и става възможно зареждането на нова поредица от команди (зареждане на нова програма). Този постоянен цикъл от дейности „зареждане на програма -> нулиране на настройките“ се е повтарял многократно, което по естествен път породило нуждата от неговото автоматизиране. Именно тази автоматизация, която се нарича “batch processing”, е първият път, когато може да се заговори за въвеждане на елемент от „Операционна Система“ (ОС). Колкото и просто да звучи, дори само автоматичното нулиране на машината след успешното завършване на компютърна програма е процес, който поставя програмите в контролирана среда и именно тя е първата и най-основна функция на ОС. За първи път понятието се въвежда официално при компютърната система Michigan Terminal System (MTS) чак през 1967 г., но подобни компютри е имало и преди него, като например IBM 704 от 1957 г. в MIT. Добре е да се отбележи, че желанието за осъществяване на “batch processing” е било налично много преди създаването на компютърна техника в днешния си модерен смисъл – повечето фабрики през 19-ти век са имали някаква форма на автоматизация на производствения процес, което по същество е същата идея, но реализирана по различен начин и в различен контекст. IBM дава огромни финансови средства за разпаботката на OS/360, която започва през 1964 г. и дава голям тласък в развитието на batch processing.

Page file

Количеството на бърза оперативна памет е проблем и за съвременните компютри, но е бил особено остър в зората на компютрите, когато обема на паметите е бил изключително малък. В проекта за първия „суперкомпютър“ Атлас от 1962 г., който е съвместен между университета в Манчестър и две частни компании, се реализира идея да бъде използвано и дисковото устройство в случаите, когато оперативната памет е недостатъчна. То разбира се е много по-бавно от оперативната памет и прави значително забавяне на работата на програмата, но все пак позволява на програмата да продължи своята работа.

Характерното при page file е, че програмата реално не знае дали пише в оперативната памет или на друг носител. Тя подава инструкции за записване в паметта към ОС и ОС взима решение къде точно да се запази информацията. При поискване на същата информация обратно, ОС поглежда в регистър и извежда обратно информацията от съответния носител. Това е била допълнителна стъпка към осъществяването на „виртуална памет“ – техника, за която ще споменем по-долу. В съвременните системи тази техника се използва от Windows чрез специален файл с име “pagefile.sys“ (може да има повече от един на повече от един диск/дял), а в Linux/BSD/Unix се нарича “swap” и най-често се реализира като отделен дял на диск.

Превенция на грешки и многозадачност

След все по-масовото въвеждане на batch processing се поражда и нуждата от разпределение на времето за различни задачи. Компютрите през 50-те и 60-те години са били основно в специализирани изчислителни центрове, но както може да се досетите са предизвиквали все по-голям и по-голям интерес в редица учени, което пък довежда до създаването на „опашки“ за изпълнение на програми. Нерядко за изпълнението на една компютърна програма са се изисквали не просто часове, а понякога и по няколко дни. Достъпът до компютър е ставал по график, а допускането на неволна грешка в кода компютърна програма е проваляла експерименти, защото за поправянето ѝ се е изисквало изчакване на дълго време. Затова през ноември 1961 г. в MIT се въвежда за първи път т.нар. Compatible Time-Sharing System (CTSS) – реализиране на идея на Джон Бакус от 1954 г., която е да може много потребители да работят с една и съща система по едно и също време.

Първата важна крачка била да направят така, че ОС да може да засича евентуални грешки в програмния код и съответно изпълнението на програмата да се прекратява преждевременно с някакъв специфичен код за грешка, с което да не се налага да се изчаква изпълнението на поредици от вече безсмислени операции. Това усъвършенстване на „компилаторите“ на компютърни програми се приема много бързо при създаването на всички по-нови компютърни системи. През 1968 г. IBM разработва операционната система CP/CMS за своята нова mainframe System/360 линия, в която се демонстрират тези нововъведения – по-късно се пренасят и върху проекта им OS/360. По-популярен пример за пионер в усъвършенстването на тази функционалност е системата Multics от 1969 г. – предшественика на популярната и до днес операционна система UNIX, чието създаване започва през същата година от хора от същия екип.

Multics въвежда и още едно фундаментално нововъведение – многозадачност. Идеята за подобно нещо не е била нова – Луиджи Федерико Менабреа я дава още през 1842 г., но именно развитието на препрограмируемите компютри го прави широко приложимо. Под многозадачност се разбира да бъде възможно един компютър да изпълнява две или повече програми едновременно. Един очевиден вариант да се осъществи подобно нещо е да се използват два или повече централни процесора (които да изпълняват свои собствени последователности от несвързани помежду си задачи), които да споделят обща оперативна памет и да комуникират по една и съща шина с едни и същи периферни устройства. Друг още по-ефективен вариант е един процесор да може да изпълнява две или повече програми едновременно, като „превключва“ от една на друга през определен интервал от време.

Тази идея довежда до огромно количество от нововъведения в операционните системи и файловите системи в частност. ОС започва да поема задачата за организиране на паралелен достъп до ресурсите на системата – формира се т.нар. „паралелно програмиране“. За реализирането на варианта „един процесор – много програми“ се появява функционалността, с която ОС спира изпълнението на дадена програма и запазва текущото ѝ състояние в паметта така, че да може нейната работа да бъде възстановена от същата позиция в бъдеще.

Многопотребителски системи

Многозадачността на компютърните системи, освен за пестене на оперативна памет и периферни устройства, първоначално е била предимно в интерес на разрешаване на чисто битовите спорове от типа „чия програма да се изпълни първа“, когато два научни екипа са искали достъп до изчислителни ресурси по едно и също време. В края на 60-те и началото на 70-те години на 20 век обаче се зараждат и компютърните мрежи – първият по-сериозен опит e ARPANET от 1969 г. Именно те дават реална възможност за едновременно зареждане на компютърни програми през т.нар. „терминали“ и това дава дава още едно бурно развитие на ОС в посока на усъвършенстване на функционалността им за многозадачност. Тогава се създават т.нар. „виртуални машини“ под формата на „jail“ – една операционна система създава няколко свои копия, които тя самата управлява, и ги свързва с IP адреси за достъп. Зараждат се нови понятия свързани с „междупроцесна комуникация“ (начини за това една програма да обменя информация с друга).

Виртуална памет

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

С масовото навлизане на многопотребителски системи започва да се мисли в посока на практическата реализация на породилата се през 1956 г. теория на Фриц-Рудолф Гюнтч за „виртуална памет“. Въпреки, че през годините е имало частични примери за имплементация, като например B5000 от 1961 г., за първи път реална виртуализация на паметта от страна на ОС е представена в норвежкия компютър NORD-1 през 1969 г., а IBM я реализира в своята mainframe серия IBM System/370 от 1970 нататък, с което постепенно става стандартна и задължителна част от всяка ОС.

Преди виртуализацията, всяка програма е „виждала“ цялата оперативна памет на системата и е можела да чете и пише на всеки адрес в нея. Синхронизацията на това една програма да не пречи на друга е отнемала много ресурси, защото различните екипи е трябвало да внимават на кои адреси в паметта пишат техните програми – реално различните програми зависели една от друга. Идеята на виртуализацията е ОС да направи абстракция, като задели определен свободен блок от физическата памет и го представи като цялата „видима“ налична оперативна памет за дадена програма. Така програмата „ще си мисли“, че работи съвсем свободно с оперативната памет, която ѝ е представена (с адреси започващи от 0 до големината на блока, а не с истинските, където физически се складира информацията) и съответно различните програми ще могат работят безпроблемно без да се интересуват на кой точно физически адрес са разположени техните данни.

Колкото до файловите системи – въвеждат се ограничители за достъп до файл. Вече програмите не изпращат командите си директно до контролера на дисковото устройство, а ги изпращат на ОС. ОС от своя страна следи дали този файл не е бил отворен от друга програма, която го е „заключила“ – ако това е така, тя изчаква с изпълнението на новопостъпилата задача докато другата програма не свърши своята работа с файла и съответно той стане отново „отключен“. Организацията на подобна опашка за чакане за достъп до ресурси е основна функция на всяка съвременна ОС.

Тази най-проста форма на виртуализация обаче бързо се усъвършенства, като се добавят и възможности за „междупроцесна комуникация“ – да бъде възможно една програма да обменя информация с други. Най-простата форма на такава комуникация разбира се е чрез файловата система, но този процес е бавен. Затова бързо се поражда и идеята за „споделена оперативна памет“ – в най-простия си вариант това е част от виртуалната памет да бъде физически блок, който е общ за всички програми. Постепенно започват да се въвеждат и нови по-сигурни стандарти като “Socket” (1971 г. в Unix) и “Pipe” (1973 г. отново в Unix), с които комуникацията между различни програми вътре в компютъра започва да става подобна и дори еднаква с комуникацията между различни компютри по компютърна мрежа.

Защита на паметта и файловата система

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

Така постепенно се зараждат маса подобрения и нововъведения във виртуализацията на паметта. Освен “paging” (споменатата вече абстракция, с която всяка програма работи в свой собствен блок) се появяват и:

  • Memory protection key – всяка програма получава уникален номер (ключ), който се записва във всеки блок от паметта, който е предназначен за нея. При достъп ключовете се сравняват и ако не съвпадат, операцията не се изпълнява. За първи път това се реализира при System/360 на IBM. В по-новите системи се явяват редица подобрения на идеята, като например много ключове на един процес, и др.;
  • Симулирана сегментация – преди изпълнението на даден код се прави симулация на част от неговите команди и така ОС става сигурна, че изпълнението му няма да доведе до повреди в паметта. Това отнема много процесорно време и съответно се използва предимно за debug, а не в реална работна среда;
  • Capability-based processing – вместо директно боравене с паметта чрез указатели, програмите използват специални защитени от ОС обекти, наречени “capabilities”. По този начин вместо програмата да контролира къде да се разполагат нейните данни, това прави ОС. Въпреки, че не намира широко приложение при операционните системи, тази идея е послужила за база при създаване на някои съвременни виртуални машини, като например Java;
  • Динамични маркери (dynamic tainting) – поставяне на специални числа (маркери) на всеки указател. Когато програма достъпва директно паметта чрез указател, неговия маркер се сравнява с маркера, който е записан на мястото, където той сочи. Ако стойностите не съвпадат, ОС докладва проблем с адреса на указателя. Някои SPARC процесори въвеждат тази техника.

Постепенно се въвеждат и допълнителни защити вътре в блоковете на всяка отделна програма, така че тя самата да не може да бъде „счупена“ (хакната) – например канарчета, address space randomization (ASLR), и др. техники за защита от препълване на буфери (записване на информация извън границите на масив от данни с фиксирана дължина).

Значителни подобрения получават и файловите системи. В някои от тях – например значимо при UNIX системите – се въвеждат допълнителни характеристики като собственик (owner), група (group) и съответни права за достъп (четене, запис, изпълнение на програмен код). Така става възможно ОС да откаже достъп до дадена директория/файл ако съответната програма, която го изисква, няма нужните права за достъп. С навлизането на персоналните компютри, за които първоначално се е считало, че няма особена нужда от многопотребителски достъп, започва едно разделение в света на операционните системи – еднопотребителски, като например DOS и ранните версии на Windows, които работят с файлови системи без права за достъп (FAT, FAT32), и многопотребителски като UNIX, Windows NT и др., които първоначално са били предимно за изчислителни центрове и сървъри, но постепенно навлизат и заменят ОС и на персоналните компютри.

Разделяне на ОС на ядро, обвивка и сервизни програми

Операционните системи постепенно станали сложен микс от основните функционалности, за които разказахме по-горе, и редица набор от сервизни програми, които е задължително да ги има, за да може ОС да бъде управлявана от потребителя (например командния редза входно-изходни операции или по-късно графичния потребителски интерфейс). Същото важи и за други сервизни програми, които може да са незадължителни за работата на компютъра, но поради честата им употреба се включват като част от операционната система. Общото название на операционната система и всички допълнителни сервизни програми, които идват с нея, се нарича „системен софтуер“.

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

В крайна сметка при RC 4000 Multiprogramming System през 1969 г. се появява концепцията за отделяне на „микроядро“ така, че то да може да бъде надграждано за създаване на други ОС. Ядрото управлява паметта и файловата система, т.е. ръководи управлението на приложните програми, осъществява междупроцесната комуникация, ръководи комуникацията с периферните устройства чрез драйверите. Тази част от сервизните програми, която е задължителна и без която няма как да се осъществи каквато и да е последваща работа с компютъра, получава наименованието „обвивка на ОС“. Тази концепция за разделяне на ОС на ядро, обвивка и сервизни програми е доминираща на пазара и до днес.

Ядрото е едно от първите неща, които се зареждат от една компютърна система (след BIOS/UEFI). Непосредствено след него се зарежда обвивката и едва след това потребителя получава възможност да работи с други сервизни или приложни програми. В днешно време много от операционните системи се различават по своите обвивки и сервизни програми, но работят под едно и също ядро – например такова е положението с различните дистрибуции на Linux и някои BSD системи.

 



Добави коментар

Адресът на електронната поща няма да се публикува


*