14. Как компютрите все още (не) работят

14. Как компютрите все още (не) работят

14. Как компютрите все още (не) работят

25 април 2016

Въпрос 1

Какво е ОС? Избройте 2 ключови неща, които тя трябва да прави.


ОС е парче софтуер, което менажира хардуера и управлява потребителски процеси.

Въпрос 2

Какво е kernel, drivers, userland?


Ядрото е това, което има достъп до (почти) всичкия хардуер, всичко в ОС-а и което се грижи за потребителските процеси.

Драйвърите са код, който е чужд за ОС-а, който управлява конкретен вид хардуер.

Юзърленд-а са потребителски програми, без които една ОС би била безполезна.

Въпрос 3

Какво са Kernel space и User space и защо съществуват?


Първото е "привилегированата" част на една ОС.

Второто е там, където вървят потребителските процеси.

Това се прави за сигурнст - процесите да не се достъпват помежду си, както и да не омажат ядрото.

Въпрос 4

Какво е процес?


Абстракция за виртуална памет. Това е една потребителска програма, която има собствена памет.

Въпрос 5

Как (едно време) се е минавала границата User space / Kernel space?


Интеръпти.

Въпрос 6

Какви сегменти има в паметта на един процес?


Image files (code)

Stacks

Heaps

Static data

etc

Изпълнимите файлове на твърдия диск

Съдържа кода на приложението

Може да съдържа кода на външни библиотеки

Или просто имената на тези външни зависимости

Примерна зависмист е стандартната С библиотека

Как получаваме изпълними файлове?

Чрез компилация и линкване

Компилацията превежда отделен файл с програмен код към машинни инструкции

Линкването "свързва" отделни компилирани единици

Какво правим с външни зависимости, които не са наш код?

Като например printf от стандартната С библиотека?

Static linking

Когато кодът на нужните библиотеки е в изпълнимия файл

Dynamic linking

В изпълнимия файл има единствено имена на библиотеки и функции

Пример: libc.so:printf или msvcrt.dll:printf

ОС-а се грижи да "зареди" библиотеката и да навърже адресите

static VS dynamic linking

По-големи изпълними файлове при статично линкване

Малко по-бързо изпъленение при статично линкване

Няма споделяне на код в обща библиотека при статично линкване

Изпълнение на код

Компютрите "говорят" на машинен език

Ние програмираме на човешко-четим език

Трябва някой по някакъв начин трябва да го обърне до машинен, за да може да бъде изпълнен от компютъра

Има (грубо-казано) 2 начина за това

Compilation / Interpretation

При първия, една програма "превежда" човешкия език на машинен преди изпълнението му

Тя се нарича компилатор

Включва процеса на linking, за който говорихме предния път

При втория, една програма директно изпълнява човешкия език

Тя се нарича интерпретатор

Работи на принципа read-eval-print (REPL)

Плюсове и минуси

Компилацията отнема време (C++, anyone?)

Компилираният код се изпълнява по-бързо

Времето за зареждане на интерпретиран код може да е голямо

Интерпретируемите езици нямат нужда от build системи

По-често (и лесно) се ползват за rapid prototyping

Компилираният код остава същия през времето

Това може да е проблем, когато хардуерът става по-добър

JIT

Идеята е да компилираме човешкия език до междинен код (Java bytecode, MSIL)

Който после, по време на изпълнение, се компилира до машинен

Това, което прави вторичната компилация, се нарича runtime

Типичните примери за това са .NET/Java

Плюсове и минуси

По-бавен startup time, тъй като се налага междинния код да се транслира

Евентуално по-бързо изпълнение от чист native код по две причини:

При дълго вървящи процеси, runtime-ът може да оптимизира hot paths

Когато upgrade-нем хардуера и runtime-а, всички "стари" програми ще вървят по-бързо

Доста повече метаинформация, идваща от runtime-a

Благинки като garbage-collection, reflection

Виртуални машини

Междинният код се изпълнява от нещо наречено виртуална машина (JVM/CLR)

Обикновено използват JIT

Някои могат да интерпретират междинния код

Някои могат да правят и двете (JVM)

Python

Къде се намира Python в картинката

Има bytecode

Няма JIT; винаги се интерпретира

Кешира се в .pyc файлове

Python (2)

В известен смисъл е виртуална машина

Имплементиран е на C

Части от стандартната библиотека са DLL-ове написани на C

Какво съдържа един native DLL/so

Практически няма разлика между DLL и EXE

Съдържа изпълним код, import таблица, export таблица

Последната съдържа само имената на функциите за C DLL-и

За C++ такива съдържа в името си и имената на типовете на аргументите си

Не съдържат, обаче, дефиниции на типове

Как тогава можем да компилираме код, който използва функции от такива DLL-и?

В чисто C и C++

С header файлове. Те съдържат дефинициите на типове, декларации на функции и т.н.

В Java/.NET

Java използва JAR файлове, а в .NET DLL-ите не са (просто) native такива

В тях има много метаинформация за всички типове, функции, etc

Скриптовите езици

Те обикновено не се компилират, а интерпретират, което означава, че ship-ват код

Тогава нямаме проблем с липса на типова информация

Memory management

Всяка програма работи с променливи, които се намират някъде в оперативната памет

Има няколко подхода за това къде може да се намират

В read-only паметта, например хардкоднати стойности в кода ни

На стека, ако това са локални променливи във функции, например

В heap-a, ако са променливи, които ще ни трябват по-продължително

За последните някой трябва да се грижи ръчно кога да бъдат освободени

Manual memory management

Езици като C/C++

Това е най-бързото решение като скорост на изпълнение

Освобождаваме ресурси максимално бързо, когато не ни трябват

Стават МНОГО грешки

Причината за 90% от crash-овете на приложения

Garbage collection

По-модерни езици като Java/.NET/Ruby/Go

По-бавно по време на изпълнение

По-късно освобождаване на ресурси

Но пък е programmer-proof

Въпроси?