Операционная система
ПО, которое организует доступ к ресурсам компьютера:
- унифицирует (драйверы, файловая система, ...);
- разделяет (вытесняющая многозадачность, виртуальная память, ...);
- разграничивает (права доступа для пользователей, ...).
Чтобы ОС могла выполнять свои функции, нужна поддержка со стороны процессора: привилегированный режим, в котором будет исполняться часть ОС, называемая ядром (kernel).
Прикладные программы
Системные утилиты
Userspace
────────────────────────────────────────────────────────
Kernelspace
Ядро ОС (привилегированный
режим)
Переносимость и совместимость
API (application programming interface) — контракт на уровне исходного кода (source-level).
Пример — API стандартной библиотеки языка Си.
ABI (application binary interface) — контракт на уровне машинного кода и двоичного представления данных: соглашения о вызовах, способы компоновки, порядок загрузки и запуска программы, интерфейс взаимодействия с ядром ОС. Нас будет особенно интересовать ABI Linux/x86.
Семейство юниксовых
Картинка из Википедии:
В 70-х Кен Tомпсон и Деннис Ричи разработали ОС Research UNIX. В 80-е AT&T ее коммерциализировала. В это же время Ричард Столлман придумал проект GNU, для него не хватало ядра. В 90-е Линус Торвальс начал разрабатывать Linux, проект GNU его подхватил. Теперь мы пользуемся ОС GNU/Linux, название означает OC GNU и ядро Linux.
Все это развивалось в разных направлениях, переносить программы между разными юниксами было тяжело, были попытки обеспечить переносимость программ между разными юниксами.
В 1985 году компания AT&T специфицировала UNIX System V в документе System V Interface Definition (SVID).
В 1988 рабочая группа IEEE выпустила первый стандарт POSIX (portable operating system interface), который стандартизировал, что такое UNIX.
xkcd: How standards proliferate
1994, X/Open: Single UNIX Specification (SUS).
Системные вызовы на Linux/x86
Осуществляются (пока что магической) инструкцией int $0x80
.
В регистре eax
должен быть номер системного вызова,
а в регистрах ebx
, ecx
и edx
— его аргументы по порядку.
Результат системного вызова возвращается в регистре eax
.
Напишем программу bare.S
, которая делает системный вызов exit
,
не пользуясь стандартной библиотекой языка Си:
#include <sys/syscall.h>
.global _start
_start: // default ELF entry point
mov $SYS_exit, %eax // SYS_exit == 1
mov $42, %ebx // exit(int status) ← status = 42
int $0x80
Соберём её:
gcc -m32 -static -nostdlib bare.S -o bare
То же самое в виде программы на языке Си:
#include <sys/syscall.h>
void _start() {
asm volatile ("int $0x80" : : "a"(SYS_exit), "b"(42));
}
Системные вызовы документированы в секции 2 руководства
(manual), поэтому почитать документацию на системный вызов
exit можно так: man 2 exit
.