Как компютрите не работят
28.10.2013
Въпрос за мъфин 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
Въпрос за мъфин 7
- Каква е разликата между статично и динамично линкване?
- При статичното кодът на външните библиотеки се вкарва директно в изпълнимия файл. Той нараства по размер, но нямаме нужда от допълнителни файлове.
- При динамичното кодът на външните библиотеки е в отделни файлове. В изпълнимия файл има само таблица с имена на зависимости.
Изпълнение на код
- Компютрите "говорят" на машинен език
- Ние програмираме на човешко-четим език
- Трябва някой по някакъв начин трябва да го обърне до машинен, за да може да бъде изпълнен от компютъра
- Има (грубо-казано) 2 начина за това
Compilation / Interpretation
- При първия, една програма "превежда" човешкия език на машинен преди изпълнението му
- Тя се нарича компилатор
- Включва процеса на linking, за който говорихме предния път
- При втория, една програма директно изпълнява човешкия език
- Тя се нарича интерпретатор
- Работи на принципа read-eval-print (REPL)
Плюсове и минуси
- Компилацията отнема време (C++, anyone?)
- Компилираният код се изпълнява по-бързо
- Времето за зареждане на интерпретиран код може да е голямо
- Интерпретируемите езици нямат нужда от build системи
- По-често (и лесно) се ползват за rapid prototyping
- Компилираният код остава същия през времето
- Това може да е проблем, когато хардуерът става по-добър
JIT
- Идеята е да компилираме човешкия език до междинен код
- Който после, по време на изпълнение, се компилира до машинен
- Това, което прави вторичната компилация, се нарича runtime
- Типичните примери за това са .NET/Java
Плюсове и минуси
- По-бавен startup time, тъй като се налага междинния код да се транслира
- Евентуално по-бързо изпълнение от чист native код по две причини:
- При дълго вървящи процеси, runtime-ът може да оптимизира hot paths
- Когато upgrade-нем хардуера и runtime-а, всички "стари" програми ще вървят по-бързо
- Доста повече метаинформация, идваща от runtime-a
- Благинки като garbage-collection, reflection
Какво съдържа един native DLL/so
- Практически няма разлика между DLL и EXE
- Съдържа изпълним код, import таблица, export таблица
- Последната съдържа само имената на функциите за C DLL-и
- За C++ такива съдържа в името си и имената на типовете на аргументите си
- Не съдържат, обаче, дефиниции на типове
- Как тогава можем да компилираме код, който използва функции от такива DLL-и?
В чисто C и C++
- С header файлове. Те съдържат дефинициите на типове, декларации на функции и т.н.
В Java/.NET
- Java използва JAR файлове, а в .NET DLL-ите не са (просто) native такива
- В тях има много метаинформация за всички типове, функции, etc
Скриптовите езици
- Те обикновено не се компилират, а интерпретират, което означава, че ship-ват код
- Тогава нямаме проблем с липса на типова информация
Go
- Go взима по-крайно решение
- Нямаме динамично link-ване, демек няма динамични библиотеки
- Има типова информация в статичните библиотеки
Memory management
- Всяка програма работи с променливи, които се намират някъде в оперативната памет
- Има няколко подхода за това къде може да се намират
- В read-only паметта, например хардкоднати стойности в кода ни
- На стека, ако това са локални променливи във функции, например
- В heap-a, ако са променливи, които ще ни трябват по-продължително
- За последните някой трябва да се грижи ръчно кога да бъдат освободени
Manual memory management
- Езици като C/C++
- Това е най-бързото решение като скорост на изпълнение
- Освобождаваме ресурси максимално бързо, когато не ни трябват
- Стават МНОГО грешки
- Причината за 90% от crash-овете на приложения
Garbage collection
- По-модерни езици като Java/.NET/Ruby/Go
- По-бавно по време на изпълнение
- По-късно освобождаване на ресурси
- Но пък е programmer-proof