Как (не) работят компютрите (2)
09.12.2014
Преговор
- Операционни системи
- Kernel
- Драйвъри
- Userland
- User space / Kernel space
Как User space достъпва kernel space
- През така наречените System Calls
- Това са обикновени функции, които можем да викаме
- Намират се в стандартната С библиотека, която върви с всяка ОС
- Те вътрешно ще направят магията
- Магията се нарича interrupt-и
... а какво всъщност са interrupt-и?
- Начин да кажем на ядрото, че искаме нещо да се случи (sys call)
- Това са инструкции, които можем да викаме директно от кода си
- Наричат се още синхронни или софтуерни интеръпти
- Начин на процесора да каже на ядрото, че нещо е станало (timer interrupt)
- Наричат се още асинхронни или хардуерни интеръпти
System Calls in x86/x64
- x86 - interrupts 0x80 (Linux) and 0x2E (Windows)
- x64 - syscall/sysret инструкциите
Преговор (OS building blocks)
- Процеси
- Threads
- Виртуална памет
... а какво всъщност е виртуална памет?
- Паметта, до която имат достъп процесите
- Те НЯМАТ достъп до истинските адреси във физическата памет
- Всеки процес има собствена като те не се застъпват
- Всеки процес има право да достъпи пълното адресно пространство
- Виртуалната памет може да не е във физическата (swap file, memory mapped files, etc)
Как изглежда един процес във виртуалната памет?
- Всеки процес, очевидно, има изпълним код
- Stacks, heaps, read-only segments
- Отделно има и mapped files, etc
Memory management
- Всяка програма работи с променливи, които се намират някъде в оперативната памет
- Има няколко подхода за това къде може да се намират
- В read-only паметта, например хардкоднати стойности в кода ни
- На стека, ако това са локални променливи във функции, например
- В heap-a, ако са променливи, които ще ни трябват по-продължително
- За последните някой трябва да се грижи ръчно кога да бъдат освободени
Manual memory management
- Езици като C/C++
- Това е най-бързото решение като скорост на изпълнение
- Освобождаваме ресурси максимално бързо, когато не ни трябват
- Стават МНОГО грешки
- Причината за 90% от crash-овете на приложения
Garbage collection
- По-модерни езици като Java/.NET/Ruby/Go
- По-бавно по време на изпълнение
- По-късно освобождаване на ресурси
- Но пък е programmer-proof
Преговор (изпълнение на код)
- Compilation
- Interpretation
- JIT
Преговор (изпълними файлове)
- Как получаваме изпълними файлове
- Static linking
- Dynamic linking
Изпълнимите файлове на твърдия диск
- Съдържа кода на приложението
- Може да съдържа кода на външни библиотеки
- Или просто имената на тези външни зависимости
- Примерна зависимост е стандартната С библиотека
Какво съдържа един 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-ване, демек няма динамични библиотеки
- Има типова информация в статичните библиотеки