Learning Platform
Troubleshooting
Глоссарий

Глоссарий — Operating Systems для Junior

Справочник ключевых терминов курса Operating Systems для Junior.

10 категорий · 88 терминов

Kernel, userspace, syscalls

Kernel

Kernel (ядро)
Термин

Центральный компонент ОС, работающий с привилегированным доступом к железу. Управляет памятью, процессами, файловыми системами, сетью и устройствами. В Linux всё это монолит в едином адресном пространстве (но с loadable modules для драйверов). У kernel свой стек, своя память, свой набор машинных инструкций (включая privileged: HLT, CLI, LIDT). Userspace не может напрямую вызвать функции kernel -- только через syscall, который физически выполняет переход CPU в kernel mode.

Пример:
# Какое ядро запущено
uname -r
# 6.6.12-amd64

# Версия и параметры сборки
cat /proc/version
# Linux version 6.6.12 (gcc ...) #1 SMP PREEMPT_DYNAMIC ...

# Параметры, с которыми ядро загружено
cat /proc/cmdline
# BOOT_IMAGE=/vmlinuz-6.6 root=UUID=... ro quiet

# Размер ядра в памяти и виртуальные области
cat /proc/meminfo | grep -i kernel
Подробнее в уроках:

Userspace

User space
Термин

Область памяти и привилегий, где запускаются обычные процессы -- ваш bash, Python, nginx, браузер. CPU выполняет код в non-privileged режиме (ring 3 на x86), не может писать в kernel-память, не может напрямую обращаться к железу. Любая операция, требующая привилегий (чтение файла, сетевой запрос, fork процесса) -- это syscall в kernel. Изоляция userspace процессов друг от друга обеспечивается виртуальной памятью: у каждого процесса свой address space.

Пример:
# Где живёт user-код процесса -- /proc/PID/maps
cat /proc/self/maps | head -3
# 555555554000-555555556000 r--p 00000000 ...
# 555555556000-55555555c000 r-xp 00002000 ...

# Какой UID/привилегии у текущего процесса
cat /proc/self/status | grep -E 'Uid|Cap'

# Сравнить kernel vs user CPU time
time sleep 1
# real 1.001s  user 0.001s  sys 0.000s
Подробнее в уроках:

Syscall

System call
Термин

Граничный API между userspace и kernel. Физически: специальная CPU-инструкция (`syscall` на x86_64, `svc` на ARM), переключающая CPU в kernel mode и передающая управление по заранее зарегистрированному адресу (entry point). Номер syscall кладётся в регистр (rax на x86_64), аргументы -- в rdi/rsi/rdx/r10/r8/r9. Возвращаемое значение приходит в rax. В Linux ~400 syscalls: read, write, open, close, mmap, fork, execve, brk, getpid и т.д. Стандартная C-библиотека glibc оборачивает syscalls в удобные функции (printf -> write, malloc -> brk/mmap).

Пример:
# Все syscalls текущей команды
strace -c ls /tmp
# % time     seconds  usecs/call     calls    syscall
# ------ ----------- ----------- --------- ----------
#  21.34    0.000064          16         4 mmap
#  18.34    0.000055          11         5 openat

# Конкретный syscall в деталях
strace -e openat ls /etc
# openat(AT_FDCWD, '/etc', O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
Подробнее в уроках:

Ring 0

Ring 0 (kernel mode)
Термин

Привилегированный уровень исполнения на x86. CPU имеет 4 кольца (Ring 0-3), реально используются только два: Ring 0 для kernel, Ring 3 для userspace. В Ring 0 доступны привилегированные инструкции (управление прерываниями, MMU, I/O-портами), полный доступ ко всей физической памяти. Переход Ring 3 -> Ring 0 происходит только через контролируемые точки входа: syscall, interrupt, exception. Это аппаратная основа изоляции kernel от userspace -- даже если процесс попытается выполнить privileged-инструкцию, CPU выкинет General Protection Fault.

Пример:
# Linux запускает userspace в Ring 3, kernel в Ring 0.
# На x86_64 виртуализация добавляет Ring -1 (hypervisor).

# В исполняемом коде userspace privileged-инструкции дадут SIGSEGV:
# __asm__('cli');  # Disable interrupts -- невозможно из Ring 3

# Посмотреть текущий privilege-level можно через CS register (последние 2 бита),
# но только через ядро -- /proc/cpuinfo показывает только статически известное
Подробнее в уроках:

Ring 3

Ring 3 (user mode)
Термин

Непривилегированный уровень на x86, где работают userspace-процессы. Запрещены privileged-инструкции, прямой доступ к I/O-портам, изменение IDT/GDT/CR3. Каждый процесс видит только свой виртуальный адресный спейс. Любая попытка обратиться к kernel-памяти или выполнить запрещённую инструкцию -> General Protection Fault, kernel перехватывает и обычно убивает процесс (SIGSEGV). Это аппаратный sandbox: ошибка в userspace не может уронить kernel.

Пример:
# Простой эксперимент: попытаться записать в kernel-адрес
# из C-программы -- получишь SIGSEGV (segmentation fault).

# В strace это видно как exit с сигналом:
strace ./bad_program
# --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xffffffff} ---
# +++ killed by SIGSEGV +++
Подробнее в уроках:

Monolithic Kernel

Monolithic kernel
Термин

Архитектура, где все системные сервисы (файловые системы, сетевой стек, драйверы устройств, планировщик, IPC) живут в едином адресном пространстве kernel. Преимущество: быстро, нет накладных расходов на IPC между подсистемами. Недостаток: баг в драйвере = kernel panic, всё падает. Linux, FreeBSD, классический Unix -- монолитные. Современные монолиты допускают loadable kernel modules (LKM): драйверы и FS можно подгружать/выгружать без перезагрузки.

Пример:
# Какие модули загружены
lsmod | head
# Module                  Size  Used by
# nvidia_drm            106496  4
# btrfs                1773568  1

# Загрузить модуль
sudo modprobe overlay

# Информация о модуле
modinfo overlay
Подробнее в уроках:

Microkernel

Microkernel
Термин

Архитектура, где в kernel только минимум: scheduling, IPC, базовое управление памятью. Драйверы, FS, networking работают как обычные userspace-сервисы и общаются через message passing. Преимущества: изоляция (падение FS-сервиса не валит систему), легче верифицировать. Недостатки: больше context switches между сервисами => медленнее. Примеры: L4, MINIX, QNX, частично macOS XNU (Mach + BSD). Реальный мейнстрим -- гибридный подход: monolith с возможностью выноса.

Пример:
# macOS XNU = Mach (microkernel concepts) + BSD subsystem.
# Smartphone модемы часто на QNX или L4.
# Полностью microkernel'овая ОС на десктопе -- редкость.
Подробнее в уроках:

Процессы, fork, exec

Process

Process
Термин

Запущенный экземпляр программы, изолированный в собственном виртуальном адресном пространстве. У процесса есть PID, PPID, UID/GID, набор открытых файловых дескрипторов, address space (text/data/heap/stack), credentials, сигнальная маска. В Linux представлен структурой task_struct в kernel. Процессы образуют дерево: каждый создан родителем через fork, корень -- init (PID 1). Изоляция процессов друг от друга обеспечивается виртуальной памятью и проверкой UID при доступе к ресурсам.

Пример:
# Список всех процессов с PID, PPID, UID
ps -eo pid,ppid,uid,comm | head
# PID  PPID  UID COMMAND
#   1     0    0 systemd
#   2     0    0 kthreadd

# Информация о процессе
cat /proc/$$/status | head -10
# Name: bash
# Pid: 12345
# PPid: 12344
# Uid: 1000 1000 1000 1000

# Дерево процессов
pstree -p | head
Подробнее в уроках:

PID

PID (Process ID)
Термин

Уникальный (на момент жизни) идентификатор процесса в kernel. В Linux 32-битное число, по умолчанию диапазон 1..4194304 (контролируется `/proc/sys/kernel/pid_max`). PID 1 -- init (systemd). Kernel-потоки часто имеют низкие PIDы (2, 3, ...). PID переиспользуется после смерти процесса -- через какое-то время этот же номер достанется другому. Поэтому код, держащий PID долго (например, файл с PID демона), должен дополнительно проверять имя процесса или использовать pidfd.

Пример:
# PID текущего shell
echo $$
# 12345

# Найти процесс по имени
pgrep nginx
# 2401
# 2402

# Подробно
ps -p 2401 -o pid,ppid,user,cmd
Подробнее в уроках:

PPID

PPID (Parent Process ID)
Термин

PID родительского процесса -- того, который сделал fork и породил данный процесс. Если родитель умирает раньше ребёнка, ребёнок становится orphan и его PPID меняется на 1 (init/systemd принимает осиротевших). Дерево процессов через PPID можно увидеть командой `pstree`. PPID полезен для понимания, кто запустил процесс: например, странный bash с PPID=ssh => кто-то залогинился; bash с PPID=cron => запущено по расписанию.

Пример:
# PPID текущего shell
ps -o ppid= -p $$
# 12344  (например, login shell или sshd)

# Полное дерево с командой
pstree -ap | grep -A1 systemd | head
Подробнее в уроках:

fork()

fork() syscall
Термин

Системный вызов, создающий точную копию текущего процесса. Ребёнок получает свой PID, но видит ту же память что и родитель (через copy-on-write -- страницы не копируются физически, пока кто-то не запишет). Те же открытые файлы (fd дублируются, offset общий). Возвращает 0 в ребёнке, PID ребёнка в родителе, -1 на ошибке. Это базовый механизм создания процессов в Unix -- даже shell делает fork+exec на каждую команду. В новых API часто заменяется на posix_spawn или vfork+exec для эффективности.

Пример:
import os

pid = os.fork()
if pid == 0:
    print(f'Child: pid={os.getpid()}, parent={os.getppid()}')
    os._exit(0)
else:
    print(f'Parent: I forked pid={pid}')
    os.wait()
Подробнее в уроках:

exec()

exec() family of syscalls
Термин

Семейство syscalls (execve, execvp, execl и т.д.), полностью заменяющих образ текущего процесса на новую программу. PID остаётся тот же, но память, code, data, stack заменяются на содержимое нового binary. Открытые файловые дескрипторы по умолчанию остаются (если на них не выставлен FD_CLOEXEC). После успешного exec код после exec() не выполняется -- его уже физически нет. Комбинация fork + exec -- классический способ запуска новой программы в Unix.

Пример:
import os

# В дочернем процессе
os.execvp('ls', ['ls', '-la', '/tmp'])
# Этот print никогда не выполнится -- exec заменил образ
print('never reached')

# В strace это виден один execve
strace -e execve ls /
# execve('/usr/bin/ls', ['ls', '/'], 0x7ffd...) = 0
Подробнее в уроках:

wait()

wait() / waitpid()
Термин

Syscall, через который родитель ждёт завершения ребёнка и забирает его exit code. Без wait завершённый процесс остаётся в системе как zombie -- занимает запись в process table, держит свой PID и exit status. waitpid позволяет ждать конкретный PID или с флагом WNOHANG не блокироваться (вернёт 0 если ребёнок ещё жив). Родитель может игнорировать SIGCHLD -- тогда kernel сам почистит зомби. Если родитель умер раньше -- ребёнка усыновляет init/systemd и он его wait'ит.

Пример:
import os

pid = os.fork()
if pid == 0:
    os._exit(42)
else:
    waited_pid, status = os.waitpid(pid, 0)
    print(f'Child {waited_pid} exited with {os.waitstatus_to_exitcode(status)}')
    # Child 12346 exited with 42
Подробнее в уроках:

Zombie

Zombie process
Термин

Процесс, который завершился (вызвал exit), но его родитель ещё не сделал wait() -- exit code не забран. Зомби не потребляет CPU/RAM, но занимает PID и запись в process table. В `ps` отображается как `Z` в STAT. Множество зомби -- баг родителя, не вызвавшего wait. Убить зомби невозможно (он уже мёртв) -- надо или заставить родителя сделать wait (SIGCHLD ему), или убить родителя -- тогда init/systemd подберёт сирот и почистит их.

Пример:
# Найти всех зомби
ps -eo pid,ppid,stat,comm | awk '$3 ~ /Z/'
#   PID  PPID STAT COMMAND
#  4242  4200 Z+   <defunct>

# Чей родитель -- кто баг?
ps -o pid,ppid,comm -p 4200

# Лечение: kill родителя (его дочки уйдут к init)
kill -CHLD 4200  # пусть отреагирует
# или
kill 4200
Подробнее в уроках:

Orphan

Orphan process
Термин

Процесс, чей родитель умер до его завершения. Kernel автоматически меняет PPID такого процесса на 1 (init/systemd) -- init обязан wait()'ить сирот, поэтому orphans не превращаются в zombie. Это разные понятия: orphan -- живой процесс без оригинального родителя; zombie -- мёртвый процесс, на который никто не сделал wait. В daemonization-паттерне специально делают двойной fork, чтобы процесс гарантированно стал orphan и его принял init.

Пример:
# Симуляция: запустить процесс в фоне и убить shell
bash -c 'sleep 60 &'
# Сразу:
ps -o pid,ppid,comm | grep sleep
#   PID  PPID COMMAND
#  5050  4040 sleep
# Через секунду (когда shell умер):
ps -o pid,ppid,comm | grep sleep
#   PID  PPID COMMAND
#  5050     1 sleep   <- PPID стал 1, его принял init
Подробнее в уроках:

Process Lifecycle

Process states / lifecycle
Термин

Процесс в Linux находится в одном из состояний (поле STAT в ps): R -- running/runnable, готов или исполняется на CPU; S -- interruptible sleep, ждёт события (можно прервать сигналом); D -- uninterruptible sleep, обычно ждёт I/O от железа (не убить даже SIGKILL); T -- остановлен (SIGSTOP, или debugger); Z -- zombie. Переходы: created -> ready (R) -> running (R) -> blocked (S/D) -> ready -> ... -> terminated (Z). Многочисленные D-state процессы указывают на проблемы с диском.

Пример:
# Состояния всех процессов
ps -eo stat,comm | awk '{print $1}' | sort | uniq -c | sort -rn | head
#   320 S
#    25 I
#    12 R
#     2 D

# Найти D-state (uninterruptible)
ps -eo stat,pid,comm | awk '$1 ~ /D/'
Подробнее в уроках:

Потоки и синхронизация

Thread

Thread (поток)
Термин

Единица планирования внутри процесса. Все потоки одного процесса разделяют адресное пространство (heap, глобальные переменные, открытые файлы), но у каждого свой stack, свои регистры, свой program counter. В Linux реализованы через clone() с флагами CLONE_VM|CLONE_FS|CLONE_FILES -- технически это просто 'lightweight process'. Планировщик не различает процессы и потоки -- видит task_struct и решает, что запустить. Множество потоков нужно для параллелизма на multi-core, фонового I/O, отзывчивого UI.

Пример:
# Сколько потоков у процесса
ps -o nlwp -p $$
# NLWP
#    1

# Все потоки конкретного процесса
ps -L -p <PID>
# или
ls /proc/<PID>/task/

# Стек и состояние каждого потока
cat /proc/<PID>/task/<TID>/stat
Подробнее в уроках:

pthread

POSIX Threads (pthreads)
Термин

Стандартизированный POSIX-API для работы с потоками: pthread_create, pthread_join, pthread_mutex_t, pthread_cond_t. В Linux реализован через библиотеку NPTL (Native POSIX Thread Library), под капотом использует clone() syscall. Один pthread = один task_struct в kernel = 1:1 модель threading (в отличие от старого LinuxThreads или зелёных потоков). Большинство языков (Python, Go runtime, Java) либо строятся поверх pthread, либо имеют свой scheduler поверх него.

Пример:
// C, gcc -pthread
#include <pthread.h>
#include <stdio.h>

void *worker(void *arg) {
    printf('thread %ld\n', (long)arg);
    return NULL;
}

int main() {
    pthread_t t[4];
    for (long i = 0; i < 4; i++)
        pthread_create(&t[i], NULL, worker, (void*)i);
    for (int i = 0; i < 4; i++)
        pthread_join(t[i], NULL);
}
Подробнее в уроках:

Race Condition

Race condition
Термин

Баг, при котором результат зависит от порядка выполнения нескольких потоков -- и этот порядок недетерминирован. Классический пример: два потока делают `counter += 1` без синхронизации; операция не атомарна (read-modify-write), поэтому при переплетении инструкций одно из обновлений теряется. Race conditions сложно отлавливать: они проявляются под нагрузкой и могут не воспроизводиться в дебаге. Лечатся блокировками (mutex, atomic), либо архитектурно -- избегая разделяемого мутабельного состояния (actor model, immutable data).

Пример:
import threading

counter = 0

def worker():
    global counter
    for _ in range(1_000_000):
        counter += 1

threads = [threading.Thread(target=worker) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()

print(counter)
# Ожидали 4_000_000, получили что-то меньше -- race condition
# (в CPython GIL частично спасает, но не от каждого случая)
Подробнее в уроках:

Mutex

Mutex (mutual exclusion)
Термин

Примитив синхронизации, гарантирующий, что критическую секцию в момент времени исполняет только один поток. Операции: lock (блокирует поток если mutex занят), unlock (отпускает). В Linux реализован через futex syscall: на быстром пути lock'нуться можно в userspace через atomic-операцию, без захода в kernel; только при contention делается futex_wait. У mutex есть владелец -- только захвативший поток может разлочить. Recursive mutex позволяет одному потоку lock'нуться повторно (для рекурсии).

Пример:
import threading

counter = 0
lock = threading.Lock()

def worker():
    global counter
    for _ in range(1_000_000):
        with lock:
            counter += 1

threads = [threading.Thread(target=worker) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()

print(counter)  # 4_000_000 -- корректно
Подробнее в уроках:

Semaphore

Semaphore
Термин

Счётчик-примитив синхронизации. Поток делает wait (P-операция): если счётчик > 0, декрементирует и продолжает; иначе блокируется. Signal (V) -- инкрементирует и будит ожидающего. В отличие от mutex, у семафора нет владельца -- любой поток может сигнализировать. Binary semaphore (счётчик 0/1) близок к mutex. Counting semaphore используется для ограничения количества одновременных операций (rate limiter, connection pool). В POSIX: sem_init, sem_wait, sem_post.

Пример:
import threading

# Ограничить количество одновременных загрузок
sem = threading.Semaphore(3)

def download(url):
    with sem:  # max 3 одновременно
        # ... делать запрос ...
        pass
Подробнее в уроках:

Deadlock

Deadlock
Термин

Ситуация, когда два или более потоков ждут друг друга, и никто не может продолжить. Классический пример: поток A держит lock1 и ждёт lock2, поток B держит lock2 и ждёт lock1. Кофман сформулировал 4 необходимых условия: mutual exclusion, hold-and-wait, no preemption, circular wait. Лечение архитектурное: всегда брать блокировки в одинаковом порядке (lock ordering), использовать try_lock с откатом, или избегать вложенных блокировок. На диск-уровне случается с fcntl-locks между процессами.

Пример:
# Linux: можно посмотреть, кто кого держит
cat /proc/<PID>/status | grep State
# State: D (disk sleep)  -- застрял в kernel I/O lock

# Для futex-deadlock в userspace:
perf lock report
# или strace -e futex показывает FUTEX_WAIT, который не получает FUTEX_WAKE
Подробнее в уроках:

Планировщик и приоритеты

Scheduler

Scheduler (планировщик)
Термин

Подсистема kernel, решающая, какой из готовых (runnable) потоков получит CPU следующим. Главные задачи: справедливость (fairness), отзывчивость (latency), пропускная способность (throughput). В Linux основной планировщик -- CFS (Completely Fair Scheduler) для обычных задач, плюс real-time классы SCHED_FIFO/SCHED_RR/SCHED_DEADLINE для критичного по времени. Решение принимается при каждом tick'е таймера, syscall, прерывании, пробуждении задачи.

Пример:
# Какие задачи в системе и их класс
chrt -p $$
# pid 12345's current scheduling policy: SCHED_OTHER
# pid 12345's current scheduling priority: 0

# Статистика scheduler'а
cat /proc/<PID>/sched | head
# se.exec_start                : ...
# se.vruntime                  : ...
# nr_switches                  : 12345
Подробнее в уроках:

Preemptive Scheduling

Preemptive scheduling
Термин

Модель, в которой kernel может в любой момент отобрать CPU у текущего потока и переключить на другой. В Linux это делается по тику таймера (~100-1000 Hz), при пробуждении более приоритетной задачи, при возврате из syscall. Противоположность -- cooperative scheduling (как в classic Mac OS или asyncio), где поток сам должен явно отдать управление. Preemption обеспечивает отзывчивость даже если userspace-код зацикливается -- его всё равно прервут.

Пример:
# Частота тиков таймера kernel'а (HZ)
grep CONFIG_HZ= /boot/config-$(uname -r)
# CONFIG_HZ=1000

# Сколько раз процесс был preempted
cat /proc/<PID>/status | grep -i ctxt
# voluntary_ctxt_switches:        1234
# nonvoluntary_ctxt_switches:     567   <- preemption
Подробнее в уроках:

CFS

CFS (Completely Fair Scheduler)
Термин

Основной планировщик Linux с 2007 года. Не использует фиксированные time slices -- вместо этого ведёт виртуальное время (vruntime) для каждой задачи и всегда выбирает ту, у которой vruntime минимально. Получается, что задачи получают CPU пропорционально своему weight (выводится из nice value). На практике 'completely fair' = взвешенно справедливо. CFS хорошо работает для общих interactive/batch workload, но для жёстких real-time нужны другие классы (SCHED_DEADLINE).

Пример:
# vruntime текущей задачи
cat /proc/<PID>/sched | grep vruntime
# se.vruntime  : 12345678.123456

# Веса nice <-> weight можно посмотреть в исходниках kernel/sched/core.c
# nice -20 -> weight 88761, nice 19 -> weight 15
Подробнее в уроках:

Nice

Nice value
Термин

Userspace-настройка приоритета процесса в Linux. Диапазон -20..+19, по умолчанию 0. Низкое значение = выше приоритет = больше CPU. Имя от 'be nice to others' -- положительный nice делает процесс уступчивым. Только root может ставить отрицательный nice (повышать приоритет). Стартовый nice задаётся при запуске (`nice -n 10 cmd`), потом меняется через `renice`. Влияет только на CPU-scheduling, не на disk I/O (для этого ionice).

Пример:
# Запустить с пониженным приоритетом
nice -n 19 ./backup.sh

# Изменить nice уже запущенного процесса
renice -n 10 -p 12345

# Текущий nice
ps -o pid,ni,pri,cmd -p $$
# PID  NI PRI COMMAND
# 12345  0  19 -bash
Подробнее в уроках:

ionice

ionice (I/O priority)
Термин

Утилита для управления приоритетом дискового I/O процесса (в kernel это part of BFQ/mq-deadline I/O scheduler). Классы: 1 (Realtime), 2 (Best-effort, default), 3 (Idle -- ждёт пока никто не использует диск). Внутри классов 0-7 уровней приоритета. Полезно для backup-скриптов, индексаторов, etl-задач -- чтобы не мешать prod-нагрузке. Реальный эффект зависит от I/O scheduler'а блочного устройства: noop/none их игнорирует.

Пример:
# Запустить процесс в idle-классе I/O
ionice -c3 ./backup.sh

# Изменить у запущенного
ionice -c2 -n7 -p 12345

# Текущий приоритет
ionice -p 12345
# best-effort: prio 4

# I/O scheduler устройства
cat /sys/block/sda/queue/scheduler
# [bfq] mq-deadline none
Подробнее в уроках:

Виртуальная память и MMU

Virtual Memory

Virtual memory
Термин

Абстракция, при которой каждый процесс видит свой 'полный' адресный спейс (на x86_64 -- 128 TiB), не зависящий от физической RAM. Виртуальные адреса транслируются в физические через page tables, которыми управляет kernel + MMU. Преимущества: изоляция между процессами (каждый видит только свою память), отсутствие фрагментации физической памяти (физически память может быть разбросана, виртуально -- последовательна), возможность держать процессы больше RAM (через swap), copy-on-write (fork без копирования).

Пример:
# Виртуальная память процесса
cat /proc/self/maps | head
# 555555554000-555555556000 r--p ...  /usr/bin/cat
# 555555556000-55555555c000 r-xp ...  /usr/bin/cat
# 7ffff7d83000-7ffff7da8000 r--p ...  /usr/lib/libc.so.6

# Общая статистика
cat /proc/self/status | grep -E 'VmSize|VmRSS|VmData'
# VmSize:    12345 kB  <- виртуально
# VmRSS:      4321 kB  <- физически в RAM сейчас
Подробнее в уроках:

Paging

Paging
Термин

Разбиение виртуальной и физической памяти на блоки фиксированного размера (страницы, обычно 4 KiB на x86; есть huge pages 2 MiB и 1 GiB). Kernel ведёт page table, мапящую виртуальные страницы на физические frame'ы. При доступе CPU через MMU транслирует адрес. Если страница не в RAM (был swapped или ни разу не trigger'ился) -- page fault, kernel либо подгружает её с диска (major fault), либо аллоцирует свежую (minor fault).

Пример:
# Размер страницы
getconf PAGESIZE
# 4096

# Поддерживаемые huge pages
cat /proc/meminfo | grep -i huge
# HugePages_Total:       0
# Hugepagesize:       2048 kB

# Page faults процесса
cat /proc/self/stat | awk '{print 'minflt='$10, 'majflt='$12}'
Подробнее в уроках:

Page Table

Page Table
Термин

Структура данных в kernel-памяти, описывающая, как виртуальные адреса процесса транслируются в физические. На x86_64 используется 4-уровневая иерархия (PGD -> PUD -> PMD -> PTE), что позволяет компактно представлять 128 TiB виртуального пространства, не аллоцируя страницы для неиспользуемых регионов. Каждый процесс имеет свой root page table -- именно его адрес лежит в регистре CR3, и переключение CR3 на context switch -- это переключение address space. Запись в PTE содержит physical frame number плюс флаги (present, writable, user, accessed, dirty).

Пример:
# Размер page tables процесса
cat /proc/self/status | grep -i pagetable
# VmPTE:        80 kB

# Можно через /proc/self/pagemap прочитать mapping для конкретного адреса
# (требует root)
Подробнее в уроках:

TLB

TLB (Translation Lookaside Buffer)
Термин

Аппаратный кэш на CPU, хранящий результаты последних трансляций виртуальный -> физический адрес. Без него каждое обращение к памяти требовало бы хождения по page table (4 чтения на x86_64 -- очень дорого). При hit TLB трансляция занимает 0 циклов; при miss MMU делает page walk (~100 циклов на DDR-доступ). При context switch TLB частично сбрасывается (с CONFIG_PCID -- по тегам). Huge pages уменьшают TLB pressure: одна 2 MiB-запись покрывает 512 4 KiB-обращений.

Пример:
# Прямого способа смотреть TLB-stats в Linux без perf нет.
perf stat -e dTLB-load-misses,iTLB-load-misses ./my_program
# 1,234,567  dTLB-load-misses
# 12,345     iTLB-load-misses
Подробнее в уроках:

MMU

MMU (Memory Management Unit)
Термин

Аппаратный блок в CPU, выполняющий трансляцию виртуальных адресов в физические по page table. Без MMU работа process isolation была бы невозможна -- надо было бы делать программные проверки на каждое обращение к памяти. MMU также проверяет права доступа (writable, executable, kernel-only) и при нарушении генерирует page fault. На x86_64 MMU интегрирована с CPU; на ARM/RISC-V похожая архитектура. У контроллеров без MMU (embedded) полноценная виртуальная память невозможна -- запускают uClinux или RTOS.

Пример:
# MMU всегда есть на x86_64/ARM с MMU.
# Проверить, что у процессора (косвенно):
grep -i 'mmu\|pae\|pse\|paging' /proc/cpuinfo
Подробнее в уроках:

Swap

Swap
Термин

Дисковая область (раздел или файл), куда kernel выгружает неактивные страницы памяти, когда не хватает RAM. Позволяет процессам в сумме использовать больше памяти, чем физически есть. Цена: доступ к swapped-странице в тысячи раз медленнее, чем к RAM (DDR ~100 ns vs SSD ~100 us). Поведение управляется `/proc/sys/vm/swappiness` (0..200, default 60): выше -- активнее свопить. На серверах с быстрым SSD swap полезен; на DB-серверах часто отключают чтобы избежать I/O-всплесков.

Пример:
# Состояние swap
swapon --show
free -h

# Кто сейчас активно использует swap
for f in /proc/*/status; do
  awk '/VmSwap|Name/{printf $2 " " $3 "\n"}' $f 2>/dev/null
done | paste - - | sort -k2 -h | tail

# Изменить swappiness
sysctl vm.swappiness=10
Подробнее в уроках:

OOM Killer

OOM Killer (Out Of Memory)
Термин

Механизм kernel, активирующийся когда система не может аллоцировать память даже после очистки кэшей и свопа. Kernel выбирает 'жертву' по oom_score (учитывается размер процесса, время жизни, oom_score_adj) и шлёт ей SIGKILL. Цель -- освободить достаточно памяти, чтобы система выжила. Алгоритм агрессивно выбирает крупных потребителей: часто жертва -- сам важный процесс (Postgres, JVM). Защититься можно через oom_score_adj=-1000 (immunity), но это рискованно -- зацикливается nothing-to-kill.

Пример:
# Кто был убит
dmesg -T | grep -i 'killed process'
# [...] Out of memory: Killed process 12345 (python3) total-vm:8GB, anon-rss:7GB

# Защитить процесс от OOM (root)
echo -1000 > /proc/12345/oom_score_adj

# Текущий счёт
cat /proc/12345/oom_score
Подробнее в уроках:

Overcommit

Memory overcommit
Термин

Политика, при которой kernel выдаёт процессам в сумме больше виртуальной памяти, чем есть физической + swap. Работает потому что большинство аллоцированной памяти процессы реально не трогают. Управляется `/proc/sys/vm/overcommit_memory`: 0 -- эвристика (default), 1 -- всегда соглашаться (даже на безумные malloc), 2 -- никогда не overcommit'ить, лимит = swap + ratio*RAM. Без overcommit fork() большого процесса часто бы падал (хотя copy-on-write делает реальную копию минимальной).

Пример:
# Текущая политика
sysctl vm.overcommit_memory
# vm.overcommit_memory = 0

# Сколько памяти 'commit'нуто и лимит
cat /proc/meminfo | grep -i commit
# CommitLimit:     8388608 kB
# Committed_AS:    4194304 kB

# Жёсткая дисциплина (для прода с DB)
sysctl vm.overcommit_memory=2
sysctl vm.overcommit_ratio=80
Подробнее в уроках:

NUMA

NUMA (Non-Uniform Memory Access)
Термин

Архитектура многосокетных серверов, где у каждого CPU-сокета своя локальная память. Доступ к 'чужой' (remote) памяти медленнее, чем к локальной (1.5-3x latency). Kernel пытается аллоцировать память на том же node, где работает процесс (NUMA affinity), но при memory pressure может уйти на другой node. Для perf-критичных задач (DBMS, ML training) важно явно прибивать процессы и память к одному node через numactl. На однопроцессорных серверах NUMA отсутствует.

Пример:
# Сколько NUMA-нод
numactl --hardware
# available: 2 nodes (0-1)
# node 0 cpus: 0-15
# node 0 size: 64512 MB
# node 1 cpus: 16-31
# node 1 size: 64512 MB

# Запустить на конкретном node
numactl --cpunodebind=0 --membind=0 ./db_server

# Где сейчас память процесса
numastat -p <PID>
Подробнее в уроках:

Stack

Stack (стек)
Термин

Область памяти процесса/потока, растущая в сторону уменьшения адресов на x86 (auto-grow до RLIMIT_STACK, default 8 MiB). Хранит локальные переменные функций, аргументы, адреса возврата, saved registers. У каждого потока свой stack. Переполнение stack (`stack overflow`) -- обычно из-за бесконечной рекурсии или огромного локального массива -- даёт SIGSEGV. Размер настраивается через `ulimit -s` или pthread_attr_setstacksize. В отличие от heap, аллокация/освобождение на стеке -- просто инструкция изменения регистра sp, без участия kernel.

Пример:
# Stack-границы текущего потока
cat /proc/self/maps | grep stack
# 7ffe...000-7ffe...000 rw-p ... [stack]

# Лимит размера stack
ulimit -s
# 8192   (в KiB, т.е. 8 MiB)

# Увеличить (для текущего shell)
ulimit -s 16384
Подробнее в уроках:

Heap

Heap
Термин

Область памяти процесса для динамической аллокации через malloc/new/realloc. Растёт в сторону увеличения адресов через syscall brk (расширяет program break) или mmap (отдельный регион). Управляется аллокатором (glibc ptmalloc, jemalloc, tcmalloc, mimalloc), который ведёт свободные блоки внутри полученных от kernel страниц -- minimizing syscalls. В отличие от stack, heap общий для всех потоков (отсюда возможность race в malloc, лечится thread-local arenas).

Пример:
# Область heap процесса
cat /proc/self/maps | grep heap
# 5555...000-5555...000 rw-p ... [heap]

# Какой аллокатор используется (в Python)
import ctypes
libc = ctypes.CDLL('libc.so.6')
# malloc на самом деле звонит в ptmalloc (glibc)

# Активность аллокатора
strace -e brk,mmap python -c 'a = [0]*1_000_000' 2>&1 | head
Подробнее в уроках:

malloc

malloc() / calloc() / realloc()
Термин

Стандартные C-функции для динамической аллокации памяти. malloc(size) возвращает указатель на size байт неинициализированной памяти. Внутри glibc реализована через ptmalloc2: для маленьких аллокаций (<128 KB обычно) использует heap через brk/sbrk, для больших -- mmap. Многопоточный режим использует множественные arenas (по одной на поток обычно) чтобы избежать contention на одном lock. Возвращаемый указатель выровнен на 16 байт на x86_64.

Пример:
// C
char *buf = malloc(1024);
if (!buf) { /* OOM */ }
// ... use buf ...
free(buf);

# Какие malloc-syscalls делает программа
strace -e mmap,brk ./my_program 2>&1 | wc -l

# Замена аллокатора через LD_PRELOAD
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 ./my_program
Подробнее в уроках:

free

free()
Термин

Освобождает память, ранее выделенную malloc. Память возвращается в пул аллокатора, но не обязательно kernel'у -- glibc может держать освобождённое в своих arenas для будущих аллокаций (быстрее, не надо syscall). Этого можно достичь через malloc_trim(0). free на уже освобождённом указателе (double-free) -- UB, обычно сразу падает или corrupts heap. Free на не-malloc'нутом указателе -- тоже UB. Современные аллокаторы детектят простые случаи и аварийно падают с диагностикой.

Пример:
// C
char *buf = malloc(1024);
free(buf);
buf = NULL;  // защита от случайного double-free

// Вернуть память kernel'у (если возможно)
#include <malloc.h>
malloc_trim(0);
Подробнее в уроках:

mmap

mmap() syscall
Термин

Syscall, мапящий файл или анонимный регион памяти в виртуальное пространство процесса. Используется в трёх ролях: (1) загрузка исполняемых файлов и .so в память, (2) шаринг памяти между процессами (MAP_SHARED), (3) большие аллокации в malloc (поверх MAP_ANONYMOUS). Mmap'нутый файл читается lazy: страница загружается с диска только при первом обращении (page fault). MAP_SHARED + запись -> изменения видны другим процессам и (при наличии файла) попадают на диск.

Пример:
import mmap

with open('huge.dat', 'rb') as f:
    mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    # Доступ как к массиву, без read()
    print(mm[1024:1100])
    mm.close()

# Что в адресном пространстве -- из mmap
cat /proc/self/maps | grep -v stack | grep -v heap | head
Подробнее в уроках:

Shared Memory

Shared memory
Термин

Память, видимая нескольким процессам -- самый быстрый способ IPC (нет копирования при общении). В POSIX API: shm_open создаёт файл-объект в /dev/shm, дальше его mmap'ят с MAP_SHARED. Старый SysV API (shmget, shmat) реже используется. Координация доступа -- через отдельные примитивы (mutex в shared memory, семафоры). Часто используется для shared cache, ML inference (одна модель, много worker'ов), zero-copy IPC.

Пример:
import multiprocessing as mp
import numpy as np

# Python: shared memory из multiprocessing
shm = mp.shared_memory.SharedMemory(create=True, size=1024*1024)
arr = np.ndarray((1024,), dtype=np.int64, buffer=shm.buf)
arr[0] = 42

# В другом процессе:
# shm2 = SharedMemory(name=shm.name)
# arr2 = np.ndarray(..., buffer=shm2.buf)
# print(arr2[0])  # 42
Подробнее в уроках:

IPC: пайпы, сигналы, сокеты

IPC

IPC (Inter-Process Communication)
Термин

Механизмы общения между процессами. В Linux основные: pipes (anonymous и named/FIFO), Unix domain sockets, signals, shared memory, message queues (SysV/POSIX), eventfd/signalfd. Выбор зависит от: направление (one-way / bidirectional), родственность (parent-child или unrelated), нагрузка (control plane vs big data), требования к latency. Для большинства задач Unix sockets хорошо балансируют простоту и производительность; для high-throughput -- shared memory + futex.

Пример:
# Список IPC-объектов в системе
ipcs -a
# ------ Message Queues --------
# ------ Shared Memory Segments --------
# ------ Semaphore Arrays --------

# Открытые pipe/socket конкретного процесса
lsof -p <PID> | grep -E 'PIPE|sock|FIFO'
Подробнее в уроках:

Pipe

Pipe (anonymous pipe)
Термин

Однонаправленный канал байтового стрима между процессами в Unix. Syscall pipe() возвращает два fd: один для чтения, один для записи. Buffer 64 KiB по умолчанию. Используется shell'ом для `|`: один процесс пишет в write-end, другой читает из read-end. Анонимные pipes доступны только через наследование fd (fork) -- unrelated процессы их не увидят. EOF на read'е приходит когда все писатели закрыли свой fd. Запись блокируется когда буфер полон.

Пример:
import os

r, w = os.pipe()
pid = os.fork()
if pid == 0:
    os.close(r)
    os.write(w, b'hello')
    os._exit(0)
else:
    os.close(w)
    print(os.read(r, 100))  # b'hello'
    os.waitpid(pid, 0)

# shell: $ ls | grep .txt -- это pipe()
Подробнее в уроках:

FIFO

FIFO (named pipe)
Термин

Pipe с именем в файловой системе. Создаётся через mkfifo(1) или mkfifo(3). В отличие от анонимного pipe, может использоваться unrelated процессами -- они оба открывают один и тот же путь. Запись/чтение -- через стандартные open/read/write. open блокируется до тех пор, пока кто-то не откроет другой конец (если не O_NONBLOCK). Данные не пишутся на диск -- передаются в kernel-буфере. Полезно для шёлл-скриптов и простой сериализации.

Пример:
# Терминал 1
mkfifo /tmp/mypipe
echo 'hello' > /tmp/mypipe
# Блокируется пока кто-то не прочитает

# Терминал 2
cat /tmp/mypipe
# hello
Подробнее в уроках:

Signal

Signal
Термин

Асинхронное уведомление, отправленное процессу. Стандартных сигналов 31 + real-time signals (32-64). Процесс может: обработать (handler), игнорировать (SIG_IGN), оставить default. SIGKILL и SIGSTOP нельзя ни поймать, ни проигнорировать. Сигнал доставляется в любой момент -- handler должен быть async-signal-safe (только список разрешённых syscalls). В новых API часто заменяется на signalfd: сигналы как poll'имый файл-дескриптор, что снимает большую часть граблей.

Пример:
import signal
import os
import time

def handler(signum, frame):
    print(f'got signal {signum}')

signal.signal(signal.SIGUSR1, handler)
print(f'my pid is {os.getpid()}, send: kill -USR1 {os.getpid()}')
time.sleep(60)

# В другом терминале
kill -USR1 <PID>
Подробнее в уроках:

SIGTERM

SIGTERM (15)
Термин

Стандартный сигнал 'просьба завершиться'. Процесс может перехватить и сделать graceful shutdown: закрыть соединения, флушнуть буферы, сохранить state. Это сигнал по умолчанию у `kill PID` без флага. systemd при остановке сервиса сначала шлёт SIGTERM, ждёт TimeoutStopSec (default 90 сек), затем SIGKILL. Хорошо написанный сервис при SIGTERM начинает draining: перестаёт принимать новые запросы, завершает текущие, корректно отключается.

Пример:
# Послать процессу SIGTERM
kill 12345
# или явно
kill -TERM 12345
kill -15 12345

# В Python
import signal
signal.signal(signal.SIGTERM, lambda *a: shutdown_gracefully())
Подробнее в уроках:

SIGKILL

SIGKILL (9)
Термин

Безусловное убийство процесса. Не может быть пойман или проигнорирован -- kernel убивает процесс немедленно. Используется как крайнее средство, когда SIGTERM не сработал. Минус: процесс не успеет закрыть файлы (буферы потеряются), отдать соединения, обновить state. На D-state (uninterruptible) процесса SIGKILL не подействует, пока процесс не выйдет из kernel-кода -- иногда D-процессы остаются 'до перезагрузки'.

Пример:
# Убить процесс наверняка
kill -9 12345
kill -KILL 12345

# Если процесс в D-state -- ждать или ребут
ps -eo pid,stat,comm | awk '$2 ~ /D/'
Подробнее в уроках:

Unix Socket

Unix domain socket
Термин

IPC-механизм через стандартный socket API (socket/bind/connect/send/recv), но без сети -- общение через файл-сокет в FS (`/tmp/app.sock`, `/var/run/docker.sock`) или абстрактное имя (с префиксом 0x00). Быстрее TCP loopback (нет TCP overhead), безопаснее (можно контролировать через файловые права на сокет, plus SO_PEERCRED -- узнать UID собеседника). Поддерживает SOCK_STREAM и SOCK_DGRAM. Используется в Docker, X11, PostgreSQL, systemd.

Пример:
# Сервер
import socket
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.bind('/tmp/my.sock')
s.listen(5)
conn, _ = s.accept()
print(conn.recv(1024))

# Клиент
import socket
c = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
c.connect('/tmp/my.sock')
c.send(b'hello')

# В FS
ls -la /tmp/my.sock
# srwxr-xr-x 1 user user 0 ... /tmp/my.sock
Подробнее в уроках:

Файловые системы

File Descriptor

File descriptor (fd)
Термин

Целочисленный handle, который kernel выдаёт процессу при открытии файла, сокета, pipe, eventfd и т.д. Уникален в рамках процесса. Стандартные: 0 stdin, 1 stdout, 2 stderr. open/socket/pipe возвращают свежий fd; read/write/close принимают fd. Все 'всё есть файл' в Unix реализовано через единый API над fd. Лимит на количество одновременно открытых fd ограничен: ulimit -n (default 1024). При исчерпании syscalls вернут EMFILE 'Too many open files'.

Пример:
# Все fd процесса
ls -la /proc/$$/fd/
# lrwx------ 0 -> /dev/pts/0
# lrwx------ 1 -> /dev/pts/0
# lrwx------ 2 -> /dev/pts/0

# Текущий лимит
ulimit -n
# 1024

# Системный максимум
cat /proc/sys/fs/file-max
Подробнее в уроках:

Inode

Inode (index node)
Термин

Структура метаданных файла на диске: размер, права, владелец, mtime/ctime/atime, ссылки на блоки данных, счётчик hard-links. Имя файла НЕ в inode -- оно живёт в директории как пара (имя -> номер inode). Поэтому два разных имени могут указывать на один inode (hard link). Количество inode фиксируется при mkfs (`mkfs.ext4 -N`). 'No space left on device' при df с free space -- часто исчерпан пул inode (см. `df -i`).

Пример:
# Номер inode файла
stat /etc/passwd
#   File: /etc/passwd
#   Inode: 12345  Links: 1

# То же из ls
ls -i /etc/passwd
# 12345 /etc/passwd

# Inode use на разделе
df -i /
# Filesystem  Inodes  IUsed   IFree IUse% ...
Подробнее в уроках:

Hard Link

Hard link
Термин

Второе (третье и т.д.) имя для существующего файла, указывающее на тот же inode. Все hard links равноправны -- 'оригинала' нет. Файл физически удаляется когда счётчик ссылок (`stat -c %h`) падает до нуля И никто его не держит открытым. Hard links нельзя сделать на директории (избегаем циклов) и через разные mount-точки (inode уникальны только в рамках FS). Удобны для дедупликации (rsync --link-dest, Time Machine).

Пример:
echo 'hello' > /tmp/orig
ln /tmp/orig /tmp/link
stat /tmp/orig | grep Links
# Links: 2
rm /tmp/orig
cat /tmp/link
# hello  -- файл жив, есть второе имя
Подробнее в уроках:

Symlink

Symbolic link (symlink)
Термин

Специальный файл, содержащий путь к другому файлу. При открытии kernel прозрачно следует по этому пути. Symlink может указывать на несуществующий файл (dangling), пересекать FS-границы, ссылаться на директорию. Удаление symlink не трогает target; удаление target оставляет dangling symlink. В отличие от hard link, видно через `ls -la` (`->`). Создаётся `ln -s`. readlink читает значение без следования.

Пример:
ln -s /etc/passwd /tmp/users
ls -la /tmp/users
# lrwxr-xr-x 1 ... /tmp/users -> /etc/passwd
readlink /tmp/users
# /etc/passwd

# Не следовать symlink
ls -l --no-dereference /tmp/users
stat -L /tmp/users  # с -L следовать
Подробнее в уроках:

Mount

Mount
Термин

Операция, прикрепляющая файловую систему (раздел диска, NFS-share, tmpfs) к точке в существующем дереве каталогов. Без mount раздел диска -- набор блоков, недоступный через обычное чтение файлов. После mount /dev/sda2 на /mnt/data, все файлы FS видны под /mnt/data/... Один блочный девайс может быть mount'ен в нескольких местах (с MS_BIND). Системные mounts описаны в `/etc/fstab` и автоматически делаются при boot.

Пример:
# Все смонтированное
mount | head
findmnt -l | head

# Подключить раздел
sudo mount /dev/sdb1 /mnt/data

# Отключить
sudo umount /mnt/data

# Что в fstab
cat /etc/fstab
Подробнее в уроках:

fstab

fstab (/etc/fstab)
Термин

Конфиг автоматических mount'ов при загрузке. Каждая строка: устройство (или UUID), точка монтирования, тип FS, опции, dump-флаг, fsck-order. Используется systemd при boot, а также `mount -a`. Лучше указывать UUID, а не /dev/sdaN -- порядок устройств может меняться. Опции типа `noatime` улучшают perf, `relatime` -- разумный default. Ошибки в fstab могут запретить загрузку -- использовать `mount -a` или `findmnt --verify` перед reboot.

Пример:
cat /etc/fstab
# /dev/disk/by-uuid/abc123 / ext4 errors=remount-ro 0 1
# UUID=def456 /home ext4 defaults 0 2
# tmpfs /tmp tmpfs nosuid,noexec 0 0

# Проверка перед reboot
sudo findmnt --verify
Подробнее в уроках:

VFS

VFS (Virtual File System)
Термин

Абстракция в kernel, дающая единый API для разных файловых систем. open/read/write/close работают одинаково для ext4, xfs, btrfs, tmpfs, NFS, FUSE, /proc, /sys. VFS определяет операции (inode_operations, file_operations, super_operations), а каждая FS их реализует под себя. Благодаря VFS, userspace не зависит от конкретной FS и можно прозрачно использовать сетевые/виртуальные FS. /proc и /sys -- pseudo-FS, не имеют дисковых блоков, операции read/write генерируют данные на лету.

Пример:
# Все смонтированные FS и их типы
findmnt --types ext4,xfs,btrfs,tmpfs,procfs,sysfs | head

# Поддерживаемые ядром типы FS
cat /proc/filesystems
# nodev sysfs
# nodev tmpfs
#       ext4
Подробнее в уроках:

ext4

ext4 filesystem
Термин

Журналируемая FS, default в большинстве Linux-дистрибутивов. Развитие ext2/ext3. Поддерживает extents (компактное описание непрерывных диапазонов блоков), журнал (восстановление после краха), backwards-compat с ext3. Хорошо балансирует производительность и стабильность для общего use case. Лимиты: до 16 TiB файлов, 1 EiB FS. Минусы: нет snapshot'ов, нет встроенного checksum'а данных, нет copy-on-write.

Пример:
# Создать ext4
mkfs.ext4 /dev/sdb1

# Проверить и оптимизировать
fsck.ext4 /dev/sdb1
tune2fs -l /dev/sdb1 | head

# Resize онлайн
resize2fs /dev/sdb1
Подробнее в уроках:

xfs

xfs filesystem
Термин

Журналируемая FS, изначально из SGI Irix, теперь главная FS для RHEL/Rocky/CentOS. Сильна на больших объёмах: миллионы файлов в директории, файлы до 8 EiB, отличное масштабирование на NVMe/multi-disk. Поддерживает delayed allocation (откладывает запись на диск, объединяя в большие extents). Не умеет shrink -- только grow. Хороший выбор для filer'ов, медиа-серверов, баз с тяжёлыми блобами.

Пример:
# Создать
mkfs.xfs /dev/sdb1

# Информация
xfs_info /

# Дефрагментация
xfs_fsr -v /

# Снимок-через-LVM (xfs сам snapshot не умеет)
Подробнее в уроках:

btrfs

btrfs filesystem
Термин

Copy-on-write FS с встроенными snapshots, checksums, compression, RAID, send/receive. Полностью реализована в mainline Linux. Default в SUSE, Synology DSM. Преимущества: атомарные snapshot за O(1), incremental backup через send/receive, прозрачное сжатие (zstd/lz4), проверка целостности. Минусы: исторически проблемы с RAID5/6 (write hole), требовательность к свободному месту (нельзя забивать >85%), медленнее ext4 на random-write workload.

Пример:
# Создать subvolume
btrfs subvolume create /mnt/data/work

# Snapshot
btrfs subvolume snapshot /mnt/data/work /mnt/data/work-2026-05-18

# Send/receive
btrfs send /mnt/data/work-2026-05-18 | ssh backup btrfs receive /backup/

# Использование
btrfs filesystem df /
Подробнее в уроках:

zfs

zfs filesystem
Термин

Самая богатая по фичам FS: copy-on-write, snapshots, send/receive, encryption, compression (zstd), deduplication, RAID-Z, end-to-end checksums, ARC-кэш в RAM. Изначально из Sun Solaris, в Linux через OpenZFS (license из-за CDDL ставится out-of-tree). Дорогая по памяти (1 GB RAM на 1 TB рекомендация), но мощь -- основа TrueNAS, многих storage-серверов. Дедупликация требует огромных ресурсов -- обычно отключают.

Пример:
# Создать pool из двух дисков (mirror)
zpool create tank mirror /dev/sdb /dev/sdc

# Dataset с сжатием
zfs create -o compression=zstd tank/data

# Snapshot
zfs snapshot tank/data@2026-05-18

# Список pool'ов и состояние
zpool status
Подробнее в уроках:

Page Cache

Page cache
Термин

Кэш файловых данных в RAM, через который проходит каждое чтение/запись на диск. При read из файла kernel сначала проверяет cache: если страница в нём -- мгновенно отдаёт, если нет -- читает с диска и кладёт в cache. При write по умолчанию данные попадают в page cache (dirty pages), а на диск сбрасываются позже (writeback). Размер кэша динамический -- всё свободное RAM. Поэтому 'free' показывает мало 'free' и много 'cache/buffers' -- это норма.

Пример:
# Состояние page cache
free -h
#               total   used   free   shared  buff/cache   available
# Mem:           16G    2G     1G     ...     13G          14G

# Очистить cache (root, на свой страх)
sync && echo 3 > /proc/sys/vm/drop_caches

# vmstat показывает активность
vmstat 1 5
# r b swpd free buff cache si so bi bo in cs us sy id wa st
Подробнее в уроках:

fsync

fsync()
Термин

Syscall, заставляющий kernel записать все dirty-страницы файла на физический диск и дождаться подтверждения. Без fsync write только обновил page cache -- при выключении питания данные потеряются. fdatasync аналогичен, но не флушит метаданные (mtime, ctime) если не было их изменения -- быстрее. Критично для баз данных (после commit), почтовых серверов, любых durability-требовательных приложений. На SSD относительно быстро (1-10 ms), на HDD дорого (10-50 ms).

Пример:
import os

with open('/data/important.dat', 'wb') as f:
    f.write(b'critical data')
    f.flush()           # из buffer Python в kernel
    os.fsync(f.fileno())  # из kernel на диск

# Замерить cost fsync на устройстве
# pip install pg-test-fsync или fio
fio --name=fsync_test --filename=/data/test --rw=write --size=1G --fsync=1
Подробнее в уроках:

O_DIRECT

O_DIRECT (direct I/O)
Термин

Флаг open(), сообщающий kernel'у не использовать page cache -- данные читаются и пишутся напрямую между userspace-buffer'ом и диском. Требует выравнивания buffer'а и размера I/O по размеру блока (обычно 4 KiB). Используется базами данных (PostgreSQL, MySQL InnoDB), которые ведут собственный buffer pool и не хотят double-buffering. Минус: каждое I/O -- syscall + физический disk-доступ, нет кэширования; ускоряет только если cache_hit_ratio был низкий.

Пример:
// C: открыть для direct I/O
int fd = open('/dev/sdb1', O_RDONLY | O_DIRECT);
// buf должен быть выровнен на блок
void *buf;
posix_memalign(&buf, 4096, 4096);
read(fd, buf, 4096);

# PostgreSQL пишет с O_DIRECT при wal_sync_method = open_datasync (в Linux)
Подробнее в уроках:

Права доступа, namespaces, cgroups

UID

UID (User ID)
Термин

Числовой идентификатор пользователя в Linux. 0 -- root, 1-999 обычно системные (daemon-аккаунты), 1000+ -- обычные пользователи. Хранится в /etc/passwd (login name <-> UID), процесс наследует UID от запустившего его. У процесса есть реальный (real), эффективный (effective) и saved UID -- разные для setuid-программ. Доступ к ресурсам (файлы, сокеты) проверяется по effective UID. UID 0 пропускает все проверки доступа (всё под root).

Пример:
# Текущий UID
id -u
# 1000

id
# uid=1000(lev) gid=1000(lev) groups=1000(lev),27(sudo)

# UID процесса
cat /proc/<PID>/status | grep Uid
# Uid: 1000  1000  1000  1000  (real, eff, saved, fs)
Подробнее в уроках:

GID

GID (Group ID)
Термин

Числовой идентификатор группы. Пользователь имеет primary group (в /etc/passwd) и supplementary groups (в /etc/group). При доступе к файлу проверяется effective GID и все supplementary. Группы используются для шаринга доступа: добавьте пользователей в `docker` группу -- они смогут юзать docker без sudo. Изменения в группах применяются при следующем login (не для текущей сессии -- надо relogin или `newgrp`).

Пример:
# Все группы пользователя
groups
# lev sudo docker

id -G
# 1000 27 999

# Добавить в группу
sudo usermod -aG docker lev

# /etc/group
grep docker /etc/group
# docker:x:999:lev,alice
Подробнее в уроках:

rwx

rwx file permissions
Термин

Базовая модель прав файлов в Unix: для owner, group, others -- читать (r), писать (w), executable (x). Отображается ls -l: `-rwxr-xr--`. В octal: r=4, w=2, x=1, owner+group+other => 754. На директорию: r -- ls; w -- создавать/удалять файлы; x -- cd внутрь. Без x на директории нельзя обращаться к её содержимому даже зная имя файла. chmod меняет права (требует ownership или root).

Пример:
ls -l /etc/passwd
# -rw-r--r-- 1 root root 2048 ... /etc/passwd
# u=rw, g=r, o=r (644)

chmod 600 secret.txt   # только owner может читать
chmod u+x script.sh    # добавить executable для owner
chmod -R g+w /shared   # рекурсивно дать write группе
Подробнее в уроках:

sudo

sudo (substitute user do)
Термин

Утилита для выполнения команды от имени другого пользователя (по умолчанию root). Решение принимается на основе /etc/sudoers -- кто, какие команды, на каких хостах, с паролем или без. Преимущества над su: гранулярность (можно дать только nginx restart, не весь root), audit (логирует кто что делал в /var/log/auth.log или journalctl), отсутствие необходимости знать root-пароль. Best practice -- не давать NOPASSWD ALL, ограничивать конкретными командами.

Пример:
# Запустить от root
sudo apt update

# От другого пользователя
sudo -u postgres psql

# Список разрешённых команд
sudo -l

# Правка sudoers (всегда через visudo для валидации!)
sudo visudo
# %dev ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
Подробнее в уроках:

setuid

setuid bit (SUID)
Термин

Специальный бит прав, при выставлении которого исполняемый файл при запуске получает effective UID = UID владельца файла, а не запустившего. Классический пример -- /usr/bin/passwd: владелец root, SUID, обычный пользователь запускает и меняет /etc/shadow (доступный только root). В ls отображается как `s` вместо `x`: `-rwsr-xr-x`. Огромный security risk: ошибка в SUID-программе = privilege escalation. Современный Linux рекомендует заменять на capabilities.

Пример:
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root ... /usr/bin/passwd

# Поставить SUID
chmod u+s /usr/local/bin/myutil
# или octal
chmod 4755 /usr/local/bin/myutil

# Найти все SUID-binary в системе
find / -perm -4000 -type f 2>/dev/null
Подробнее в уроках:

Capabilities

Linux capabilities
Термин

Гранулярное разбиение root-привилегий на ~40 отдельных capability'и: CAP_NET_RAW (raw socket), CAP_NET_BIND_SERVICE (привязка к порту < 1024), CAP_SYS_ADMIN, CAP_KILL (kill чужих процессов), CAP_CHOWN и т.д. Можно дать программе только нужные capability'и, не делая её SUID root. Видны в getcap (на binary) и в /proc/PID/status (на запущенном). Контейнеры (Docker, podman) активно используют для drop'а лишних cap'ов.

Пример:
# Capabilities binary'я
getcap /usr/bin/ping
# /usr/bin/ping cap_net_raw=ep

# Дать программе CAP_NET_BIND_SERVICE
sudo setcap cap_net_bind_service=+ep /usr/local/bin/myserver

# Cap'ы процесса
grep Cap /proc/self/status
# CapInh: 00...
# CapPrm: 00...
# CapEff: 00...
Подробнее в уроках:

Namespaces

Linux namespaces
Термин

Механизм изоляции: процессы в namespace видят свой собственный 'instance' какого-то системного ресурса. Типы: pid (свои PIDs), net (свои интерфейсы, маршруты), mnt (свои mount points), uts (свой hostname), ipc (свои SysV IPC), user (свои UID/GID mappings), cgroup, time. Основа контейнеризации: Docker/podman/kubernetes создают комбинацию namespaces для каждого контейнера. Создаются через clone() с CLONE_NEW* флагами или unshare(2).

Пример:
# Свои namespaces у процесса
ls -la /proc/$$/ns/
# lrwxrwxrwx 1 ... ipc -> 'ipc:[4026531839]'
# lrwxrwxrwx 1 ... mnt -> 'mnt:[4026531840]'
# lrwxrwxrwx 1 ... net -> 'net:[4026531992]'
# ...

# Создать процесс в новом PID namespace
sudo unshare --pid --fork --mount-proc bash
# Теперь ps показывает только процессы внутри
Подробнее в уроках:

cgroups

Control groups (cgroups)
Термин

Механизм ограничения и учёта ресурсов (CPU, RAM, disk I/O, network) для группы процессов. Иерархическая структура контроллеров: memory, cpu, blkio, pids и т.д. В cgroup v2 (mainline с Linux 4.5) -- единая иерархия в /sys/fs/cgroup. systemd использует cgroups для каждого unit'а (services, scopes, slices). Контейнеры через cgroups ограничивают сколько RAM/CPU может съесть workload. memory.max -- hard limit (превышение -> OOM kill внутри cgroup).

Пример:
# cgroups текущего процесса
cat /proc/self/cgroup
# 0::/user.slice/user-1000.slice/session-3.scope

# Лимиты systemd service
systemctl show docker.service -p MemoryHigh,CPUQuota

# Сколько RAM использует cgroup
cat /sys/fs/cgroup/user.slice/user-1000.slice/memory.current
Подробнее в уроках:

Observability: top, vmstat, perf, /proc

/proc

/proc filesystem (procfs)
Термин

Pseudo-FS, дающая userspace интерфейс к kernel state. Не имеет дисковых блоков -- данные генерируются ядром по запросу. /proc/<PID>/ -- информация о процессе (status, maps, fd/, stat, sched). /proc/cpuinfo, /proc/meminfo, /proc/loadavg -- системная информация. /proc/sys/... -- настройки kernel (можно изменять через echo). Самый удобный способ диагностики Linux без специальных утилит. Сами утилиты ps, top, free, vmstat читают /proc.

Пример:
# CPU info
cat /proc/cpuinfo | grep -E 'model name|cpu cores' | head -4

# Memory
cat /proc/meminfo | head -5

# Загрузка
cat /proc/loadavg
# 0.45 0.34 0.28 1/512 12345  <- 1/5/15min loadavg, runnable/total, last PID

# Open fds процесса
ls /proc/<PID>/fd/
Подробнее в уроках:

/sys

/sys filesystem (sysfs)
Термин

Pseudo-FS, экспортирующая kernel device model: устройства, драйверы, kernel modules, шины. /sys/class/ -- по классам (net, block, usb), /sys/devices/ -- по железной топологии, /sys/module/ -- загруженные модули. Можно читать (свойства устройства, статистика) и иногда писать (включить/выключить функцию, изменить настройку). udev использует sysfs для генерации /dev. Хорошо подходит для скриптов мониторинга: например, /sys/class/thermal/thermal_zone*/temp для CPU-температур.

Пример:
# Сетевые интерфейсы
ls /sys/class/net/
# eth0 lo wlan0

# Скорость интерфейса
cat /sys/class/net/eth0/speed
# 1000

# Температуры CPU
for z in /sys/class/thermal/thermal_zone*/temp; do
  echo $((`cat $z` / 1000))C
done
Подробнее в уроках:

strace

strace
Термин

Утилита для трассировки syscalls процесса. Использует ptrace API kernel'а -- attach'ится к процессу и перехватывает каждый syscall, показывая аргументы и возвращаемое значение. Незаменимо для диагностики: 'почему программа упала?', 'к каким файлам обращается?', 'где зависла?'. Минусы: серьёзный slowdown (5-50x на syscall-heavy workload), требует CAP_SYS_PTRACE. Для production-критичных задач лучше eBPF/bpftrace -- меньше overhead.

Пример:
# Все syscalls команды
strace ls /tmp 2>&1 | head

# Только определённые
strace -e openat,read,write ./app

# Прицепиться к запущенному процессу
strace -p <PID>

# Статистика
strace -c ./app
# % time  seconds  usecs/call  calls  syscall
#  50.0   0.002    1          2000   read
Подробнее в уроках:

ltrace

ltrace
Термин

Аналог strace для библиотечных вызовов (dynamic linker hooks). Показывает вызовы malloc, free, strcpy, fopen и т.д. -- то что вызывается ВНУТРИ программы из glibc и других .so. В отличие от strace, не работает со статически слинкованными binaries и менее популярен (eBPF/uprobes для production удобнее). Полезно для отладки library-bug'ов в legacy-софте.

Пример:
ltrace ls /tmp 2>&1 | head
# __libc_start_main(...) <unfinished ...>
# getenv('LS_COLORS') = NULL
# malloc(...) = 0x55...
# strcpy(0x55..., '/tmp') = 0x55...

# Прицепиться
ltrace -p <PID>
Подробнее в уроках:

perf

perf (Linux perf_events)
Термин

Универсальный профайлер Linux, использующий perf_events kernel API. Считает hardware events (CPU cycles, cache-misses, branch-misses) через PMU процессора + software events (context switches, page faults). Делает statistical sampling: периодически записывает stack trace, по которому потом строится flame graph. Минимальный overhead, подходит для prod-профилирования. Главные команды: perf record (собрать), perf report (просмотр), perf top (live), perf stat (счётчики).

Пример:
# Статистика выполнения
perf stat ./my_program
# 1,234,567 cycles
#   123,456 instructions   #  0.10 insn per cycle
#    12,345 cache-misses

# Профиль (с stack traces)
sudo perf record -g ./my_program
perf report

# Live top по функциям
sudo perf top
Подробнее в уроках:

vmstat

vmstat
Термин

Утилита для мониторинга системных ресурсов: процессы (runnable/blocked), память (free, buffers, cache, swap), I/O (block in/out), system (interrupts, context switches), CPU (user/sys/idle/iowait/steal). Запускается с интервалом: vmstat 1 -- раз в секунду. Главные колонки для диагностики: r -- runnable queue (>cores значит CPU contention), wa -- iowait (медленный диск), cs -- context switches (если десятки тысяч -- много потоков или сигналов), si/so -- swap-in/out (если >0 -- активный swap, плохой знак).

Пример:
vmstat 1 5
# procs ----memory---- ---swap-- ---io--- -system- -----cpu-----
#  r  b  swpd free buff cache  si so   bi  bo   in  cs us sy id wa st
#  1  0    0  1.2G 200M 13G    0  0    4 100   80 200  5  1 90  4  0
#  2  0    0  1.1G 200M 13G    0  0    0   0  500 1000 80 5 15  0  0
Подробнее в уроках:

iostat

iostat
Термин

Утилита для мониторинга block-устройств: throughput (kB/s read и write), IOPS (r/s, w/s), latency (await), utilization (%util). Из пакета sysstat. Главные метрики: await -- средняя latency запроса в ms (для SSD <1, для HDD <10 нормально); %util -- процент времени, когда устройство было занято (100% не всегда значит насыщение -- современные NVMe могут параллелить); rkB/s, wkB/s -- пропускная способность.

Пример:
iostat -xz 1 5
# Device  rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
# sda     0.00   2.00   1.0 50.0 32     800   16.3     0.5    10.0  5.0   10.1   0.5   25.5

# Просто общая статистика
iostat
Подробнее в уроках:

top

top
Термин

Классическая интерактивная утилита: процессы отсортированы по CPU/MEM. Показывает: uptime, loadavg, общую статистику по процессам и CPU/RAM/swap, потом список процессов. Главные клавиши: P -- сорт по CPU, M -- по MEM, k -- kill процесс, c -- полная command line, 1 -- per-CPU stats. Колонки: %CPU (последний интервал), %MEM (RSS / total), VIRT (virtual size), RES (resident), SHR (shared).

Пример:
top -b -n 1 | head -15
# top -- 14:30:00 up 5 days, 2:15, 2 users, load average: 0.50, 0.45, 0.30
# Tasks: 312 total, 1 running, 311 sleeping, 0 stopped, 0 zombie
# %Cpu(s):  5.0 us, 1.0 sy, 0.0 ni, 93.5 id, 0.5 wa, 0.0 hi, 0.0 si, 0.0 st
# MiB Mem: 16384 total, 1024 free, 8192 used, 7168 buff/cache
#
#   PID USER  PR  NI VIRT  RES  SHR S %CPU %MEM   TIME+  COMMAND
Подробнее в уроках:

htop

htop
Термин

Улучшенная версия top: цветной интерфейс, scrollable список процессов, удобная навигация мышью, древовидный режим (F5), фильтр (F4), tree of children. Не требует sudo для базовых операций. Показывает per-CPU bars наглядно. Можно настраивать колонки (F2), сортировку (F6). Стандартная утилита для интерактивного мониторинга, но не подходит для скриптов -- для них ps и top -b.

Пример:
htop
# Tab    -- сворачивать tree-ветки
# F4     -- filter (по substring команды)
# F5     -- tree view
# F6     -- sort
# F9     -- kill
# /      -- search

# F2 (Setup) -- настроить колонки: добавить IO_RATE, CGROUP, и др.
Подробнее в уроках:

dmesg

dmesg
Термин

Утилита просмотра kernel ring buffer: сообщения от драйверов, kernel-подсистем, hardware events. Сюда попадают: USB-устройства plug/unplug, OOM killer-сообщения, segfault'ы, ошибки файловых систем, BUG/WARN из kernel. На systemd-системах те же сообщения дублируются в journalctl -k. Полезно при диагностике железа и kernel-проблем. Без root читается если /proc/sys/kernel/dmesg_restrict=0.

Пример:
# Последние сообщения с timestamps
dmesg -T | tail -20

# Только OOM-killer
dmesg -T | grep -i 'killed'

# Только конкретного типа
dmesg --level=err

# Follow (как tail -f)
dmesg -wT
Подробнее в уроках:

udev

udev (device manager)
Термин

Userspace-демон, обрабатывающий device events от kernel (uevents). Динамически создаёт ноды в /dev при подключении устройства, выставляет права, запускает скрипты по правилам. Правила в /etc/udev/rules.d и /usr/lib/udev/rules.d -- по device attributes можно дать стабильное имя (например, флэшке -- одинаковый mount point независимо от того, какой /dev/sdX ей выдан). В systemd объединён с systemd-udevd.

Пример:
# Текущие udev-events live
sudo udevadm monitor

# Атрибуты устройства
udevadm info -a -n /dev/sda1

# Reload правил
sudo udevadm control --reload-rules
sudo udevadm trigger

# /etc/udev/rules.d/99-myusb.rules
# ACTION=='add', SUBSYSTEM=='usb', ATTR{idVendor}=='1234', SYMLINK+='myusb'
Подробнее в уроках:

Boot, init, systemd

BIOS

BIOS (Basic Input/Output System)
Термин

Прошивка материнской платы, исполняющаяся при включении (legacy boot). Делает POST (Power On Self Test), инициализирует базовое железо, ищет загрузочный device по списку boot order, читает MBR (Master Boot Record) -- первые 512 байт диска, передаёт ему управление. Ограничения: real mode 16-bit, диски до 2.2 TB (MBR), без secure boot. На современных машинах заменён UEFI; даже если есть 'legacy mode' -- через эмуляцию.

Пример:
# Проверить, как загрузилась система
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS

# Boot order и сообщения
dmidecode -t bios | head
# BIOS Information
#   Vendor: American Megatrends
#   Version: 1.20
#   Release Date: 03/2024
Подробнее в уроках:

UEFI

UEFI (Unified Extensible Firmware Interface)
Термин

Современная замена BIOS. 32/64-bit, поддерживает GPT-диски (до зеттабайт), secure boot (подписанные bootloader/kernel), graphical interface, network boot из коробки. Boot из EFI System Partition (ESP, FAT32) по пути типа /EFI/BOOT/BOOTX64.EFI или зарегистрированным в NVRAM entries. На Linux -- работа через efibootmgr и /sys/firmware/efi/. Secure Boot требует подписанного shim/grub/kernel, иначе придётся отключать или подписывать модули самому (MOK).

Пример:
# Boot entries в NVRAM
sudo efibootmgr
# BootCurrent: 0001
# BootOrder: 0001,0000
# Boot0001* Linux Boot Manager

# Содержимое EFI partition
ls /boot/efi/EFI/
# BOOT  systemd  ubuntu
Подробнее в уроках:

GRUB

GRUB (GRand Unified Bootloader)
Термин

Самый распространённый bootloader на Linux. Загружается прошивкой (BIOS из MBR или UEFI из ESP), показывает меню выбора kernel/OS, загружает выбранное ядро в память и передаёт ему управление с параметрами. Конфиг -- /etc/default/grub (high-level) + /etc/grub.d/ (scripts). После изменений: grub-mkconfig -o /boot/grub/grub.cfg. Из GRUB-меню можно редактировать параметры одноразово (e), что спасает при сломанной системе (single mode, init=/bin/bash).

Пример:
# Реконфигурация
sudo grub-mkconfig -o /boot/grub/grub.cfg

# В режиме боли (boot не идёт):
# 1. Нажать e на нужной записи в меню GRUB
# 2. Добавить init=/bin/bash в линию linux
# 3. F10 -- boot
# Получаете root-shell с rw rootfs
Подробнее в уроках:

init

init (PID 1)
Термин

Первый процесс, запущенный kernel'ом после загрузки -- PID 1. Его задача -- запустить остальные сервисы, обработать сигналы, усыновлять сирот и wait'ить их. Исторически были разные init-системы: SysV init (через /etc/rc.d, последовательно), Upstart (Canonical, event-based), OpenRC. С 2015 года мейнстрим Linux -- systemd. PID 1 не может быть убит -- если упадёт, kernel panic.

Пример:
# Что является init на системе
ls -la /sbin/init
# /sbin/init -> /lib/systemd/systemd

# PID 1
ps -p 1 -o pid,comm
#   PID COMMAND
#     1 systemd
Подробнее в уроках:

systemd

systemd
Термин

Современная init-система и system/service manager для Linux. Запускает и управляет сервисами (units): service, socket, timer, mount, path, scope, slice. Параллельный запуск с dependency tracking -- сильно быстрее SysV. Использует cgroups для группировки и ограничения процессов сервиса. Журналирует через journald (бинарные логи в /var/log/journal). Управляющие команды: systemctl (start/stop/status/enable), journalctl (логи), systemd-analyze (boot performance).

Пример:
# Состояние сервиса
systemctl status nginx

# Включить автозагрузку и запустить
sudo systemctl enable --now nginx

# Логи сервиса
journalctl -u nginx -f

# Что тормозит загрузку
systemd-analyze blame | head
Подробнее в уроках:

journalctl

journalctl
Термин

Утилита для чтения systemd-журнала (бинарного лога от journald). Хранится в /var/log/journal/ или /run/log/journal/ (если persistent storage не настроен). Преимущества над plain text: индексированный поиск по unit/PID/UID/priority, structured fields, автоматическая ротация. Все системные логи (включая dmesg/kernel) в одном месте. Опции: -u <unit>, -p <priority>, -f (follow), --since/--until, -k (kernel-only), -b (current boot).

Пример:
# Логи сервиса с момента старта
journalctl -u postgresql.service -b

# Реалтайм follow
sudo journalctl -f

# Только ошибки
sudo journalctl -p err

# Конкретный период
sudo journalctl --since '2026-05-18 10:00' --until '2026-05-18 12:00'
Подробнее в уроках: