Основите на Интернет и UNIX
от Ерик Реймънд
Eric S. Raymond <[email protected]>
Този документ описва на достъпен език основни
положения, характерни за PC клас компютри, UNIX
базирани операционни системи и Интернет.
1. Въведение
1.1 Предназначение на този
документ
1.2 Тематично свързани източници
1.3 Нови варианти на този
документ
2. Базова анатомия на Компютъра
3. Какво се случва когато включите
компютъра
4. Какво става когато стартираме
програма от shell?
5. Как работят входящите устройства и
прекъсвания.
6. Как компютърът върши няколко задачи
едновремено?
7. Как компютърът предпазва отделните
процеси от застъпване помежду си.
8. Как компютърът запазва неща на диска.
8.1 Low-level (ниско ниво) на диска и
организация на файловата система.
8.2 Файлови имена и директории.
8.3 Точки на монтиране
(прикачване)
8.4 Как става получаването на
един файл
8.5 Как нещата могат да се объркат
9. Как работят компютърните езици.
9.1. Компилиращи езици.
9.2 Интерпретиращи езици.
9.3. P-code езици.
10. Как работи Интернет?
10.1. Имена и локации.
10.2 Пакети и рутери.
10.3. TCP и IP
10.4. HTTP, един application протокол
1. Въведение.
1.1. Предназначение на този документ
Този документ има за цел да помогне
на Linux и Интернет потребителите, които са самоуки и допълват своите знания
в движение. Като начин на обучение, това е много удобно, но
така остават фундаментални пропуски в основни
направления; пропуски, които затудняват
творческотото мислене, а също така и ефективното
справяне с възникващите проблеми, поради липсата
на една ясна представа за реално протичащите
процеси.
Ще се опитам по един ясен и лесен за
разбиране начин да Ви обясня как всъщност работи
всичко. Този документ е насочен към Linux
потребителите и по специално на Intel PC
базирани машини.
Нещата няма да се повтарят в процеса
на излагане на материала, така че е добре да се
внимава на всяка дума. Добра идея е, след един
първоначален повърхностен прочит, да се върнете
повторно с цел по-пълното възприемане на
материала.
Този документ ще се обогатява в
течение на времето, така че периодично
проверявайте за наличието на осъвременен
вариант.
1.2. Тематично свързани източници
Ако намерението Ви е да се научите
как да станете хакер , би трябвало да прочетете и
материала How To
Become A Hacker FAQ. (Превод на български на същия
документ можете да намерите тук -
бел. Linux center)
1.3. Нови варианти на този документ
Нови варианти на този документ
периодично ще бъдат зареждани на comp.os.linux.help
или news:comp.os.linux.announce или news.answers
, а също така и на http://sunsite.unc.edu/LDP/HOWTO/Fundamentals-HOWTO.html в оригинал на английски език.
2. Базова анатомия на Компютъра.
Във Вашия компютър има процесор,
който извършва операциите. Има и вътрешна памет
(DOS/Windows потребителите я наричат RAM, докато UNIX
потребителите я наричат core). Процесорът и
паметта се разполагат на motherboard (дънната
платка), която е сърцето на Вашия компютър.
Имате също така и монитор,
клавиатура, твърд диск, флопи и т.н. Мониторът и
дисковите устройства имат контролери (така
наречените карти), които са поставени на дънната
платка и осъществяват управлението на външните
устройства. (Клавиатурата е елементарна, така че
не се нуждае от отделен контролер – той е вгрaден
в нея)
Детайлни подробности за работата на
тези устройства ще разгледаме по-късно, като
засега е необходимо да имате в предвид само някои
основни зависимости при съвместната им работа.
Всички вътрешни компоненти са
свързани посредством bus (шина). Физически
шината е това, към което се включват отделните
контролери (например видеокарта, звукова карта,
дисков контролер). Шината е магистралата за
пренос на данни между процесора, паметта,
монитора, дисковете и всичко друго във Вашия
компютър.
Процесорът е това, което кара всички
тези неща да работят, но всъщност не вижда
пряко отделните компоненти, а се свързва с тях
посредством шината. Единствената подсистема,
която има пряк и незабавен контакт с процесора е
оперативната памет. За да работят програмите, те
трябва да се заредят в тази оперативна памет.
Това което се случва, когато вашия
компютър чете програма или данни от диска,
всъщност е това, че процесорът използва шината за
да изпрати до дисковия контролер заявка
за четене от диска. Малко по-късно дисковия
контролер използва шината за да оповести, че
данните са прочетени и се намират на определено
място в оперативната памет. Тогава процесора
може да използва шината за да види съдържанието
на тази памет.
Клавиатурата и монитора също
комуникират с процесора посредством шината, но
по един по-прост начин, като това ще бъде обект на
вниманието ни на един по-късен етап. Засега
знаете достатъчно за да разберете какво се
случва, когато включите компютъра.
3. Какво се случва когато включите
компютъра
Компютърът без работеща програма, е
просто куп електроника. Първото нещо, което се
случва когато се включи компютъра, е
стартирането на специална програма наречена операционна
система. Задачата на операционната система е
да помогне на работата на другите компютърни
програми в сложния процес по управлението на
компютърните компоненти.
Процеса на зареждане на
операционната система се нарича booting(това е
класическа игра на думи, като се прави
шеговита аналогия с другото значение на думата boot
, а именно ботуш и трудността човек да се вдигне
сам, като се хване за ботушите). Вашият компютър
знае как да зареди операционната система, защото
използва една инструкция как да стане това. Тази
инструкция е вградена в специален чип на
компютъра наречен BIOS (Basic Input/Output System).
BIOS посочва едно определено място
от boot диска (зареждащия диск), където се
намира програма наречена boot loader (диспечер,
контролиращ първоначалното зареждане на
операционна система), под Linux този boot loader се
нарича LILO ( Linux Loader). Този boot loader се
зарежда в оперативната памет и се стартира.
Задачата на boot loader е да стартира
операционната система.
Boot loader прави това, като намира kernel
(кърнъл), зарежда го в оперативната памет и го
стартира. Когато стартирате Linux и видите LILO
последван от поредица от точки, това онагледява
зареждането на кърнъла. Появяването на всяка
следваща точка отбелязва зареждането на
поредния дисков блок от кърнъл кода.
Може би се чудите защо BIOS не
зареди кърнъла директно, а се преминава през този
двустъпков процес с boot loader? Истината е, че BIOS
не е достатъчно интелигентен. В действителност,
може да се каже дори, че е глупав и Linux не се
обръща повече към него след първоначалното
зареждане. Поначало BIOS е написан за
примитивните 8 битови PC с малки дискове и
буквално не може да адресира толкова голямо
дисково пространство, колкото е необходимо на
кърнъла за да се зареди директно. Преминаването
през етапа boot loader освен това, Ви дава
възможността да стартирате и други операционни
системи, намиращи се в други дялове на същия диск,
в редките случаи когато UNIX, като операционна
система не е достатъчно добра за Вас.
Веднъж стартиран, кърнълът трябва да
се огледа, да опознае наличните хардуерни
компоненти и да подготви стартирането на
програмите. Той опознава наличните хардуерни
компоненти като ги търси на I/O Ports
(входно/изходните портове) – това са специално
адресирани участъци от шината, на които са
поставени контролерите на периферните
компоненти. Тези контролери са в режим на
очакване на команди адресирани към тях. Това
опознаване става планомерно, защото кърнълът има
необходимите познания за това, какви контролери
очаква да намери и как те биха инициализирали
наличието си. Този процес се нарича autoprobing (самотестване).
Повечето от съобщенията, които
виждате в процеса на зареждане са именно
тестовете, които кърнълът прави на хардуерните
компоненти (през входно-изходните портове),
съобразявайки какво има налично и как би могъл да
се настрои към особеностите на Вашата машина. Linux
кърнълът е особено добър в това отношение,
по-добър от другите UNIX-и и значително по-добър
от DOS и Windows. Много Linux ветерани считат, че
именно интелигентността на процеса на тестване
при стартирането (а това го прави лесен за
инсталиране), е факторът привлякъл значителна
маса потребители.
Но зареждането и стартирането на
кърнъла не завършва boot процеса (процеса на
първоначалното зареждане), това е само първи етап
(наричан run level 1).
Следващата стъпка която трябва да
направи кърнълът е да провери дали Вашите
дискове са наред. Файловите системи на дисковете са
нещо доста деликатно и ако има някакви нарушения
породени от хардуерни проблеми или внезапно
прекъсване на захранването, то е необходимо да се
направят няколко възстановителни стъпки, преди UNIX
да продължи нататък. Ще се върнем отново на този
въпрос когато стане дума за това как
нещата около файловата система могат да тръгнат
на зле.
Следваща стъпка на кърнъла е да
стартира няколко daemons (демона). Демонът е
програма, която може да се сравни с принтерния
спулер (файла който съдържа заявките към
принтера), с програмата, която следи за
обработката на е-mail или пък с Web сървъра.
Това са програми, които чакат на заден план (казва се, че работят в background или фонов режим - бел. Linux center) и са в
готовност да изпълнят отнасящи се към тях задачи.
Тези специални програми често трябва да
координират няколко различни задачи, което от
своя страна може да предизвика конфликти. Те се
наричат демони, защото е доста по-лесно да се
напише една програма, която да работи
непрекъснато и да следи всички направени заявки,
отколкото да се използват множество копия (всяко
от които да следи една отделна заявка от всичките
течащи едновременно) и да сме сигурни, че нещата
няма да се объркат. В частност, наборът от демони,
които се стартират на Вашата система може да
варира, но почти винаги включва принтерния спуул
(демона за Вашия принтер).
След като са стартирани всички
необходими демони, може да се приеме, че сме в run
level 2. Следваща стъпка е подготовката за работа
с потребителите. Кърнълът стартира едно копие на
програмата наречена getty, която да наблюдава
конзолата (могат да бъдат стартирани и няколко
копия на програмата за да се следят и dial-in
портовете). Getty е програмата която извиква login
prompt (командния ред, в който първоначално се
въвеждат потребителското име и паролата) на
конзолата. Сега сме в run level 3 и сме готови за log
in (логване, логическо включване) и стартиране на програмите.
Когато извършите логването (т.е. да
въведете потрбителското си име и паролата) Вие се
идентифицирате пред getty и пред компютъра. След
това се статира програма наречена login, която
извършва няколко подготвителни задачи и след
това стартира командния интерпретатор, наречен shell (обвивка на ядрото).
Наистина getty и login могат да бъдат
обединени в една програма, но за да бъдат две
отделни програми си има исторически причини,
които не е необходимо да коментираме на този
етап.
Да видим какво става когато
стартираме програма от shell (командния
интерпретатор).
4. Какво става когато стартираме програма
от shell?
Обикновено shell Ви изправя пред
командния промпт $ след като се логнете
(разбира се, ако не сте променили вида на знака).
Ние няма да говорим за синтаксиса и за това което
виждате на екрана, вместо това ще видим какво
става зад сцената – от гледна точка на самия
компютър.
След първоначалното зареждане и
преди стартирането на програмите може да се каже,
че в компютъра има една скрита менажерия от
процеси очакващи някакво действие. Всички те
очакват някакво събитие. Събитие може да бъде
натискането на клавиш или движение на мишката. А
ако машината ви е свързана в мрежа, събитие може
да бъде и пристигането на пакет данни.
Кърнълът (ядрото) е един от тези процеси. Той е
по-специален, защото има правата да контролира
работата на всички други процеси и обикновено е
единствения процес, имащ директен достъп до
хардуерните компоненти. На практика, останалите
процеси трябва да направят заявка към кърнъла
кога могат например; да получат сигнал от
клавиатурата, да пишат на монитора, да четат или
пишат на диска или пък просто да 'схрускат'
някой и друг бит от паметта. Тези заявки са
познати като system calls (системни повиквания)
Обикновено всички входящи и изходящи
заявки преминават през кърнъла, така че той да
може да следи процесите и да предотвратява
смесването им. Някои по-специални процеси имат
правата да заобикалят кърнъла и имат директен
достъп до входно/изходните портове. X Server
(графичния сървър – програмата, която управлява
обръщенията на другите програми за поява на
графични изображения на монитора) е един такъв
процес. Но ние все още нямаме X Server и сме пред
командния интерпретатор на текстовата конзола.
Командният интерпретатор е един
обикновен процес. Той следи за натискането на
клавиш, като очаква сигнал (през кърнъла) на
входно-изходния порт на клавиатурата. Когато
кърнъла види такъв сигнал, той го препраща към
екрана, а едновременно и към shell. Когато
кърнълът види Enter той изпраща съдържанието на
целия ред към shell, а той се опитва да го
възприеме като команда.
Например нека да напишем ls и Enter
за да предизвикаме разлистване на текущата
директория. Shell изпълнява вградените си
инструкции и преценява че трябва да стартира
изпълнимите команди намиращи се във файла /bin/ls.
Той прави заявка към кърнъла за стартирането на
нов дъщерен процес и даване на достъп на този
процес до клавиатурата и монитора. Тогава shell
заспива очаквайки ls да свърши.
Когато /bin/ls е готов, той (чрез заявка
за изход), дава знак на кърнъла че е приключил.
Тогава кърнъла събужда shell и му казва да
продължи работата си и съответно shell дава нов prompt.
Докато стават тези неща (нека да
приемем, че директорията, която разлистваме е
достатъчно голяма), Вие може да се заемете с нещо
друго, например да стартирате друга конзола, да
се логнете и да започнете играта Quake. Или пък да
се поразгледате из Интернет, или да изпратите и
получите пощата си докато върви /bin/ls.
5. Как работят входящите устройства и
прекъсвания.
Вашата клавиатура е едно елементарно
входящо устройство, защото създава малки
количества данни и с малка скорост (имайки
предвид компютърните стандарти). Когато
натиснете или отпуснете един клавиш това
посредством кабела на клавиатурата се възприема
като хардуерно прекъсване.
Работата на операционната система е
да следи за такива прекъсвания. За всеки вид
прекъсване си има отделна част от операционната
система следяща това прекъсване и съхраняваща и
обработваща данните свързани с него.
Това което прави всъщност този handler
(регулатор) на прекъсването за клавиатурата, е да
изпрати получените данни към една област
(наречена системна) от оперативната памет. Там
тези данни ще бъдат в готовност, докато
операционната система проверява коя е
програмата, от която се очаква да се занимава с
клавиатурата.
По-сложните входящи устройства като
дисковите и мрежовите контролери работят по
подобен начин. Преди всичко се обръщаме към
дисковия контролер през шината, за да отбележим,
че дисковата заявка е изпълнена. Това, което се
случва е, че дискът предизвиква едно прекъсване.
Регулаторът на дисковото прекъсване копира
исканите данни в оперативната памет за да бъдат
подръка на програмата, която е направила
заявката.
Всеки вид прекъсване има съответното
приоритетно ниво. Прекъсванията с по-ниско
приоритетно ниво (като сигналите от
клавиатурата), трябва да изчакват прекъсванията
с по-висок приоритет (като тактовете на системния
часовник или дискови операции). UNIX е
проектиран така. че да дава приоритет на
процесите изискващи по-голяма скорост, с оглед на
това да се запази най-висока работоспособност на
машината.
По време на boot процеса се виждат
справки за различните номера на IRQ. Трябва да
се има предвид, че най-често срещания начин за
недобро конфигуриране на хардуерните
компоненти, е опита да се използува едно и също IRQ
от две различни устройства, без да е ясно защо се
получава така.
Ето отговора: IRQ е абревиатура на Interupt
ReQuest. За операционната система е необходимо, по
време на стартирането, да знае кой номер
прекъсване, от кое устройство ще се използва, за
да може да му се определи и съответния регулатор.
Ако две различни устройства се опитват да
използват едно и също прекъсване, то
прекъсването може да избере погрешния регулатор
(нарича се още 'обработчик на събитие' или 'обработчик на прекъсване - бел. Linux center).
В най-общия случай, това може да предизвика
блокиране на устройството, а понякога и да
повлияе на работата на операционната ситема,
като предизвика блокиране или дори срив.
6. Как компютърът върши няколко задачи
едновремено?
В действителност това не е точно
така. Компютърът може да изпълнява само една
задача (процес) за определен момент, но може да
променя задачите по които работи много бързо и
заблуждава бавното човешко мислене, че върши
няколко неща наведнъж. Това се нарича
времеделене.
Една от задачите на кърнъла, е да
управлява точно този процес на споделяне на
времето. Има една част от него наречена scheduler (диспечер),
която следи всички текущи процеси (без самия
кърнъл). На всяка 1/60 –та от секундата системният
часовник се намесва в кърнъла предизвиквайки
прекъсване. Диспечерът спира течащия в момента
процес, оставяйки го в готовност за продължаване
по-късно и се насочва към управление на
следващия.
Една 60-та от секундата може и да не
звучи като много време, но за модерните процесори
е достатъчно, за да изпълнят десетки хиляди
инструкции и така да извършат голям обем работа.
Така, че дори и да имате голям брой едновремено
течащи процеси, то всеки един процес може да
свърши определен обем работа за неговия си
отрязък от време.
Може да се случи програмата да не
получи целия отрязък от време определен за нея.
Ако се получи заявка за прекъсване подадена от I/O
устройство, кърнълът прекратява изпълняващата
се в момента задача, вкарва в работа диспечера на
съответното устройство и тогава отново се връща
към задачата си. Един такъв наплив от високо
приоритетни прекъсвания може да предизвика thrashing
(нестабилност на системата). За щастие това се
случва много рядко при модерните UNIX.
В действителност, скоростта на
работа на програмите рядко се влияе от машинното
време, което им се отделя (има някои изключения от
това правило, като например звукообработка или
работа с триизмерна графика). Много по-често
забавянето се предизвиква от по-бавния обмен на
данни с дисковите или мрежовите устройства.
Операционна система поддържаща
едновременно течащи процеси се нарича multitasking
(многозадачна). Фамилията операционни системи UNIX
са проектирани в такъв аспект от самото си
създаване и многозадачната им работа е
изключително добра – много по-добра от Windows или
Mac, при които изискването за многозадачна работа
е присадено впоследствие и то доста зле.
Ефикаснaта и надеждна, многозадачна работа е
това, което прави Linux превъзходен за мрежови
комуникации и работа в Web.
7. Как компютърът предпазва отделните
процеси от застъпване помежду си.
Диспечерът на кърнъла предпазва
смесването на процесите по време. Операционната
система трябва да ги отдели и в пространството,
така че да не се смесва тяхната работа в паметта.
Това, което први операционната система за
решавнето на този проблем, се нарича memory management
(управление на паметта).
Всеки текущ процес се нуждае от
собствена област в оперативната памет, като
място където да развие програмния си код и да
пази променливите величини и получените
резултати. За тази област може да се мисли и като
за една съвкупност от два сегмента; разрешения
само за четене code segment (сегмент за кода, съдържащ
инструкциите за процеса) и разрешения за запис data
segment (сегмент за данни, съдържащ всички
променливи на този процес). Сегментът за данни е
уникален за всеки процес, но два процеса които
използват един и същ програмен код, автоматично
се насочват от UNIX към работа с един общ code
сегмент, като мярка за постигане на по-голяма
ефикасност.
Ефикасността е важен елемент, защото
оперативната памет е нещо ценно и понякога
нямате достатъчно, за да се поемат всички
работещи едновременно процеси, особено ако
използвате големи програми като X-server. За да
се справи с това UNIX ползва стратегия наречена
virtual memory (виртуална памет). UNIX не се опитва
да държи всички данни и кодове на течащите
процеси в оперативната памет. Вместо това той
държи там подръка малки части от тях, а основните
са на твърдия диск в така наречената swap
(трансферна) област.
По време на изпълнението на текущите
процеси UNIX се опитва да предвиди в каква
посока ще се развиват тези процеси и кои от
елементите да запази в оперативната памет. Да се
прави това успешно, е много трудно и сложно,
затова няма да се разглежда тук. Достатъчно е да
се знае, че всъщност указателите на данните и на
програмните кодове образно казано, приличат на
зърна и са организирани подобно на грозд, като
всяко новообразувано зърно е свързано с едно
по-старо. Така че, ако UNIX успее да държи
подръка по-често и по-скоро използваните кодове и
данни, може да се каже, че успява да спести време.
Трябва да се отбележи, че в миналото
размерът на оперативната памет е бил относително
много по-малък от размера на работещите програми,
така че прехвърлянето в swap областта се е
случвало често. Понастоящем цената на
оперативната памет е спаднала значително, така
че дори и непретенциозни машини имат достатъчно
обем. Например на една съвременна машина с 64 и
повече Mb оперативна памет, спокойно могат да
работят едновремено и X Server и приличен набор
от други програми, без дори да е необходимо
прехвърляне в swap областта.
Дори при една такава благоприятна
ситуация, тази част от операционната система
наричана memory manager (диспечер на паметта), има
още важни неща за вършене. Трябва да се подсигури
условието, че всяка програма може да променя само
собствения си сегмент данни, да се избегне
възможността лошо написан или погрешен
програмен код да извърши запис в сегмента с данни
на друга програма и така да наруши работата и. За
да стане това се съставя един регистър на данните
и кодовете, който се опреснява при всяка отделна
заявка за ползване на памет и съответно
освобождаване на памет (второто става при изход
на програмата).
Този регистър се използва за да се
прехвърлят командите в една определена част на
хардуера наречена MMU – Memory Management Unit
(устройство за управление на паметта), като при
модерните процесори е вграден в тях. MMU има
едно особено свойство да поставя прегради между
различни области от паметта. Така един опит за
достъп отвън се отхвърля и се предизвиква
специално прекъсване.
Ако някога видите UNIX съобщение: Segmentation
fault , Core dumped или нещо подобно, това е точно
такъв случай, опитът на работещата в момента
програма да достигне област извън нейния
сегмент, е предотвратен и е предизвикано особено
прекъсване. Това е белег за наличие на бъг в
програмния код и създадения файл core dump носи
определена информация, предназначена да помогне
на създателите на програмата, да проследят
причините за това.
8. Как компютърът запазва неща на диска.
Когато погледнете съдържаниeто на
твърдия диск под UNIX, ще видите едно дърво от
директории и файлове. Обикновено не е необходимо
да се навлиза по-навътре от това, но е полезно да
се знае какво се случва зад кулисите, при
положение, че се получи срив на диска и трябва да
се спасяват файлове. За нещастие няма добър начин
да се опише дисковата организация от ниво файл
надолу, затова ще направим това от хардуерна
гледна точка.
8.1. Low-level (ниско ниво) на диска и
организация на файловата система.
Повърхността на диска за съхраняване
на данни е разделен на концентрични кръгове
(подобно на дъска за дартс) наречени писти и още
веднъж е разделен на сектори (подобно на парчета
торта). Тъй като пистите които са най-далеч от
центъра на въртене имат по-голяма площ от тези
които се намират близо до него то външните писти имат повече секторни филийки от вътрешните. Всички дискови
блокове имат еднаква големина, като при
модерните UNIX това е 1 бинарен Килобайт (1024 байта). Всеки
дисков блок си има уникален адрес наречен номер
на дисковия блок.
UNIX разделя диска на disk partitioins
(дискови дялове). Всеки отделен дисков дял
представлява една непрекъсната поредица от
дискови блокове, които са отделени от другите
дялове: и като вид на файловата система и като swap
space (област за прехвърляне). Дисковите блокове с
най-ниска номерация са по-специални, например
блока за boot partition (дял от който става
първоначалното зареждане), където може да се
зарежда кърнъла.
Всеки дял е съставен както от swap space
– област използвана за работата на virtual memory (виртуалната памет)
, така и от файлова система, която да съхранява
файловете. За блоковете на swap space се приема, че
са разположени в линейна непрекъсната
последователност, докато за файловата система е
необходимо разположението на дисковите блокове,
от които се състои даден файл да се отразява в
някаква таблица. Тъй като файловете нарастват,
свиват се и се променят в течение на времето,
данните от които се състои един файл не са
разположени в непрекъсната последователност от
блокове, а са разхвърляни из целия дял (там където
операционната система е намерила свободен блок
на диска, когато и е потрябвал такъв).
8.2. Файлови имена и директории.
В рамките на една файлова система
конвертирането от физическото представяне на
файла към неговото логическо представяне става
посредством една структура наречена i-node (i-
възел). Тези i-възли се намират в дисковите
блокове намиращи се почти най-долу в диска (с
най-ниска номерация). Малко по-надолу от тях е
разположен блок с данни за размерите и етикети на
различните участъци на дяла (но това не е предмет
на нашето внимание). Всеки i-възел описва един
отделен файл. Над блоковете съдържащи i-възлите,
се разполагат блоковете, в които са разположени
самите файлове.
Всеки i-възел съдържа списък на
номерата на дисковите блокове, от които е
съставен файла. (В действителност това е
полуистина, защото е вярно само що се отнася до
файловете с по-малки размери, но може да се каже
че подробностите по този въпрос не са толкова
важни за нас). Забележете, че i-възела не съдържа
името на файла. Имената на файловете се групират
в директория. Директорията всъщност
представлява файл, съдържащ таблица с информация
за имената на файловете и номерата на i-възлитe
асоциирани с тях. Това е обяснението, че в UNIX,
файловете могат да имат много различни валидни
имена (или твърди връзки сочещи към тях), те са
просто различни записи в различни директории,
които в действителност сочат към един общ за тях
i-възел.
8.3. Mount points (Точки на прикачване)
В най-общия случай, цялата UNIX
файлова система се разполага на един дисков дял.
Така е при малките UNIX системи, иначе едно
такова разпределение не е много характерно.
По-често ще видите разпределение в различни
дискови дялове или дори и на различни физически
дискове. Например, може да имате един малък дял, в
който се намира кърнъла, един по-голям, в който са
съставните части на операционната система и една
друга още по-голяма част, в която са директориите
на потребителите.
Единствения дял, който трябва да се
достига непосредствено след всяко стартиране на
системата е root (основния) дял, откъдето, (в
повечето случаи) се извършва първоначалното
зареждане. В root дяла се намира и root директорията
на файловата система, главният възел, върху който се
гради всичко останало.
Останалите дялове в системата трябва
да се прикачват към root дяла за да бъдат
достижими. Някъде по средата на процеса на
зареждане, UNIX ще направи тези не root дялове
достижими. Тоест, те ще бъдат прикачени към
директории, принадлежащи на root директорията.
Например, ако имате директория
наречена /usr тя може да бъде точка на прикачване
към дял, който съдържа много програми
инсталирани на системата, но които не са
необходими за първоначалното стартиране.
8.4. Как се получава съдържанието на един
файл.
Сега нека да погледнем на файловата
система от друга гледна точка (в смисъл на
логическото представяне на един файл). Когато
отваряме файл (например /home/esr/WWW/ldp/fundamentals.sgml) се
случва следното:
Кърнълът стартира задачата си в root
директорията (на root дяла). Там той търси
директория наречена home. Обикновено home е точка на
прикачване на един голям потребителски дял и
съответно кърнълът започва търсенето там. В
най-горната директория на този потребителски дял
той ще търси запис с наименование esr и ще види кой
е номера на съответния i-възел. Виждайки, че за
този i–възел съответства директория, той започва
търсенe на запис с името WWW, по същия начин става и
прехвърлянето в поддиректорията ldp. Намирайки в
тази директория записа на fundamentals.sgml и съответния
му i–възел, се разбира, че това не е директория, а
файл съдържащ списък на номерата на дисковите
блокове, в които е разположен той.
8.5. Как нещата могат да се объркат
По-рано се спомена че файловата
система e нещо доста крехко. Сега вече знаем, че за
да достигнем до един файл, трябва да лъкатушим по
една доста верига от директории и съответстващи
i-възли. Сега да предположим, че на твърдият диск
се появят лоши сектори.
Ако сте късметлия, ще загубите само
данни от някои файл, но ако е обратното, могат да
бъдат нарушени структурата на някоя директория
или таблица на i-възел и така цяла клон от
дървовидната структура на директориите да отиде
в забвение. Или най-лошото, ако се наруши
структура, сочеща по различни пътища до едни и
същи блокове или i-възли. Такова нарушение може да
се разшири, повреждайки всички данни
произхождащи от първоизточника –повредените
дискови блокове, следствие на лошите сектори.
За щастие такива случайности се
срещат доста рядко, особено при непрекъснато
нарастващата надеждност на твърдите дискове.
Това означава още, че UNIX ще намери за добре
периодично да проверява файловата система за
съвместимост, за да е сигурно, че няма нещо
объркано. Модерните UNIX правят една такава
бърза проверка на всички дялове при
първоначалното стартиране, точно преди
прикачването им. През няколко рестартирания се
прави една по-подробна проверка, отнемаща малко
по-дълго време.
Ако всичко това звучи, така като, че
ли UNIX е една ужасно сложна и склонна към
пропадания система, то трябва да уточним, че тези
проверки при първоначалните зареждания, са само
за да се установят проблемите в самото начало,
преди те да са станали наистина сериозни. Другите
операционни системи не притежават такива
функции, което малко ускорява тяхното
първоначално зареждане, но за сметка на това може
да Ви изправи пред перспективата да се опитвате
да възстановявате разрушените файлове на ръка (а
това ще ви принуди да имате нещо от рода на Norton
Utilities наблизо).
9. Как работят компютърните езици.
Ние вече дискутирахме въпроса как работят програмите. Всяка програма в
основата си трябва да изпълни поредица от битове,
които са инструкции на компютърен машинен език.
Но хората не се справят добре с този машинен език,
да правиш това е много рядко и граничи с черната
магия дори и в средите на хакерите.
Почти всички UNIX кодове, (с
изключение на поддръжките на някои директни
хардуерни интерфейси в кърнъла) са написани на
програмни езици от високо ниво (термина 'високо
ниво' е исторически и има задачата да се отдели
от програмните езици от 'ниско ниво', които
всъщност са една много тънка обвивка около
машинния код).
Има различни видове програмни езици
от високо ниво. Добре е, да се има предвид, че source
code (изходния код) на програмата (създадената от
човек и с възможност за редактиране версия),
трябва да се преведе на машинен език, за да бъде
изпълнен.
9.1. Компилиращи езици.
Най-общия вид са компилиращите езици.
Те се превеждат на изпълним от машината двоичен
код посредством специална програма наречена
(съвсем логично) компилатор. Един път създаден,
бинарния файл може да бъде стартиран, без повече
да се обръщаме към изходния код. Повечето
софтуерни продукти се издават като компилирани
бинарни файлове, състоящи се от код, който не е
достижим.
Характерни за компилиращите езици
са, както отличното им представяне и
непосредствения достъп до операционната
система, но също така и трудната работа с тях.
С - езика на който е написан UNIX,
е най-важният от тях (с разновидността си С++). FORTRAN
е друг компилиращ език, все още използван от
инженери и учени, но вече е доста стар и
примитивен. В UNIX не се използват масово други
компилиращи езици, с изключение на COBOL -
употребяван за финансови и бизнес приложения.
Има и много други компилиращи езици,
но те или са загубили значението си, или се
използват в строго определени области. Ако сте
нов в тази област препоръчително е да започнете
със С или С++
9.2. Интерпретиращи езици.
Един интерпретиращ език се базира на
интерпретираща програма, която чете изходния код
и в движение го преобразува в изчисления и
системни повиквания. Изходния код трябва да бъде
препрочитан (и това се прави от интерпретатора)
всеки път когато се изпълнява кода.
Интерпретиращите езици са по-бавни от
компилиращите и често имат ограничен достъп до
операционната система и хардуера. От друга
страна, те са по-лесни за работа и по-благосклонни
към грешки в кодирането, отколкото компилиращите
езици.
Много от инструментите на UNIX
включително shell и bc(1) и sed(1) и awk(1),
са малки интерпретиращи езици. BASIC и Tcl също.
В исторически план най-важен е бил LISP. Днес Perl
e много разпространен и бележи значително
увеличение на популярността си.
9.3. P-code езици.
След 1990 год. един вид хибридни
програмни езици, използващи едновремено и
компилиране и интерпретиране, добиват особено
значение. Р-code езиците, са като компилиращите
по отношение на това, че преобразуват програмния
код в изпълним бинарен файл, който обаче не е във
формата на машинния код. Той е p-code (pseudocode -
псевдо код), който обикновено е доста по-прост от
машинния eзик. Когато се стартира програма се
интерпретира p-code.
P-code може да работи почти толкова
бързо, колкото и компилирания бинарен файл (p-code
интерпретатора може да бъде направен достатъчно
малък, прост и бързодействащ) . Но p-code
програмния език запазва гъвкавостта и мощта на
добрия интерпретатор.
Основни p-code програмни езици са Python
и Java.
10. Как работи Интернет?
За да се разбере по-лесно как работи
Интернет, ще проследим какво се случва когато
изпълним една типична Интернет операция. Нека да
посочим на браузъра един Web адрес от заглавната
страница, а имено адреса на мястото където се
намира Linux Documentation Project. Това е:
http://sunsite.unc.edu/LDP/HOWTO/Fundamentals.html
което означава че той се намира във файла
LDP/HOWTO/Fundamentals.html в отворената за WWW директория на host-а
(хост – домакин, приемник) sunsite.unc.edu.
10.1. Имена и локации.
Първото нещо, което трябва да направи
браузърът, е да установи връзка с машината на
която се намира този документ. За да стане това
трябва да се намери местоположението на хоста
sunsite.unc.edu (хост е съкращение от host machine –хост
машина или host network – мрежов хост, sunsite.unc.edu е
типично име на хост). Съотвествуващото му
местоположение се определя от един номер,
наречен IP адрес (по нататък ще се обясни
значението на IP).
За целта се извиква програма
наречена name server (програма обслужваща имената
и адресите). Тя може да е на Вашата машина. Но
по-често се случва тя да се намира на машината към
която се обръщате. Ползвайки услугите на ISP
(Интернет доставчик), една от настройките е да се
укаже на софтуера който ползвате за Интернет,
какъв е IP адреса на name server-а на Интернет
доставчика.
Name server-ите на различните машини
си кореспондират обменяйки и обновявайки цялата
информация необходима за разпознаване на
хост-имената (преобразувайки ги в IP адреси). Name
server-ът може да разрови няколко различни сайта
в процеса на разпознаване на хоста sunsite.unc.edu, но
това става доста бързо (за по-малко от секунда).
Name server-ът ще каже на браузъра, че IP
адреса на Sunsite е 152.2.22.81. знаейки това, машината Ви
вече ще може да обменя данни директно с машината
на Sunsite.
10.2. Пакети и рутери.
Това което браузърът ще поиска да
направи, е да изпрати команда подобна на тази:
GET /LDP/HOWTO/Fundamentals.html HTTP/1.0
Ето как се случва това. Командата се
оформя като пакет, блок от битове, характеризиран
от три важни елемента; адреса на източника (IP
адреса на Вашата машина), направлението на
заявката (IP адреса на търсената машина в
случая 152.2.22.81) и служебния номер на порта (80 в този
случай) указващ Web характера на заявката.
Така, Вашата машина изпраща заявката
по кабела (на модема, или на локалната мрежа),
докато достигне една специална машина наречена
рутер. Рутерът има карта на Интернет в паметта си
– разбира се не пълна, но напълно описваща
мрежовото обкръжение, така че да може се достигне
безпрепятствено до следващи такива рутери в
Интернет.
Вашият пакет може да премине през
няколко такива рутери, докато достигне
направлението си. Рутерите са интелигентни. Те
следят колко време е необходимо на другите
рутери за да потвърдят приемането на пакета и
използват тази информация за да пренасочват
трафика през по-бързите връзки. Те отбелязват
кога даден рутер или кабел отпадат от мрежата и
компенсират при възможност, като намират друго
заобиколно трасе.
Мълвата гласи, че Интернет е
проектиран така, че да оцелее при ядрена война.
Това не вярно, но все пак е проектиран така, че да
постигне максимална надеждност, въпреки крехкия
хардуер на един нестабилен свят. Основно, това се
дължи на факта, че интелигентността е
разпределена между хиляди рутери, а не между
няколко масивни прекъсвача (както е при
телефонната мрежа). Това означава, че сривовете
имат свойството да бъдат много точно
локализирани и да се заобиколят като се използва
друго трасе.
Един път пакетът достигнал
направлението си, машината чрез обслужващия
номер предава пакета на web server. Web server
разбира къде да насочи отговора си, като
проверява кой е IP адреса на подателя. Когато web
server-а приготви заявения документ, той ще бъде
разделен на няколко отделни пакета, чиято
големина зависи от характерните особености на
мрежата и типа на обслужване.
10.3. TCP и IP
За да се разбере как се управлява
движението на многобройните пакети, трябва да се
знае че Интернет използва два основни вида
протоколи, работещи съвместно.
Протоколът от по ниско ниво IP (Internet
Protocol), знае как да придвижи пакетите от адреса
на подателя до получателя (затова и се наричат IP
адреси). Обаче IP не е надежден при условие че
някой от пакетите се загуби или пропадне,защото
нито машината подател, нито машината получател
ще разберат някога това. На мрежов жаргон това се
казва отсъствие на двустранна връзка; подателят
само изпраща пакетите, без да очаква
потвърждение за получаването им.
Все пак IP e бърз и евтин. Понякога
бърз, евтин и ненадежден е достатъчно. Когато се играе Doom
или Quake по мрежата всеки куршум се отъждествява с
един IP пакет и загубата на няколко пакета
няма да е фатална.
Протоколът от по-високо ниво TCP
(Transmission Control Protocol), дава надеждността. Когато
две машини обменят TCP връзка (това те правят
използвайки IP), приемника на пакетите изпраща
потвърждение за получаването на всеки отделен
пакет до подателя. Ако подателят не получи такова
потвърждене до определено време, той изпраща
пакета отново. Подателят дава на всеки пакет
собствен номер, който да послужи на получателя за
възстановяване на последователността за
сглобяване на отделните пакети в случай на
разбъркване на реда на приемането им. (Това
разбъркване обикновено става при нестабилност
на връзката).
TCP/IP пакетите съдържат също така и
контролни суми за детекция на нарушени данни от
лоша връзка. Така че, от гледна точка на
потребителя на TCP/IP и name server-ите
изпращането на данни между две машини изглежда
надеждно. Хората, които използват мрежовите
протоколи, почти никога не трябва да мислят за
всички тези пакети, разглобявания, проверки за
грешки, контролни суми и препращания, които се
крият под повърхността.
10.4. HTTP, един application protocol.
Нека да се върнем към примера. Web
браузърът и сървърът използват един application protocol
който върви върху TCP/IP протокола, използвайки
го за да обменят данни помежду си. Той се нарича HTTP
(Hyper-Text Transfer Protocol), и ние видяхме вече една
негова команда GET.
Когато командата GET пристигне на
sunsite.unc.edu и се насочи към web server с номер 80, тя се
пренасочва към демона на този сървър, който не
прави нищо друго освен да чака на порта и да следи
и изпълнява командите пристигащи на този порт.
Ако структурата на Интернет се
подчинява на някакво върховно правило, то това е,
че всички елементи трябва да бъдат максимално
прости и разбираеми от човек. HTTP и подобните
му (SMTP-Simple Mail Transfer Protocol, протокола служещ за
движение на електронната поща между хостовете) използват
прости, разбираеми от човек текстови команди
завършващи с carriage-return/line feed .
Това е определено неефикасно и при
определени обстоятелства може да се постигне
по-добра скорост, ако се използва по-строго
кодиран бинарен протокол. Опитът показва, че
предимството да имаме командите на един понятен
за човека език, е по-важно от относителното
предимство на по-високата ефикасност, получена
за сметка на сложния и непонятен език.
Така че, това което Ви изпраща
сървърния демон посредством TCP/IP протокола
отново е текст. Началото на този отговор би
изглеждало така (някои заглавни редове са
пропуснати):
HTTP/1.1 200 OK
Date: Sat, 10 Oct 1998 18:43:35 GMT
Server: Apache/1.2.6 Red Hat
Last-Modified: Thu, 27 Aug 1998 17:55:15 GMT
Content-Length: 2982
Content-Type: text/html
Тези редове ще бъдат последвани от
един празен ред и по-нататък следва текста на web
страницата (след което връзката прекъсва). Така
Вашият браузър просто показва исканата страница.
Заглавните редове му показват как да направи
това (в конкретния случай Content-Type реда му
казва, че данните са в HTML формат).