GNU/Linux | Notes
2.36K subscribers
114 photos
8 files
80 links
Open Source, Dotfiles, Debian/Ubuntu, Software, Linux, Scripts, Notes, Terminal, Shell, Gnu, Tools, Games, Fun, Free Software Movement.

Автор: Кирилл Рехов
Почта: krekhov.dev@gmail.com
Кто я: https://xn--r1a.website/krxnotes/246
GitHub: https://github.com/krekhovx
Download Telegram
strace

Отследить работу процесса a.out:
$ strace a.out


Вывод в файл log:
$ strace -o my-log a.out


Отслеживание конкретного процесса:
$ strace -p <pid>


Отследить встроенную команду:
$ strace bash -c 'cd /tmp'


Например, команда 'mount -t nfs ...' возвращает отрицательный статус, можно проанализировать вывод утилиты strace:
$ strace -o mount.strace -s1024 -f -i -k -n mount -t nfs <path> <to-path>


Разбор:
-s1024 длина сообщений будет полная, а не обрезанная (32 длиной).
-f отслеживать дочерние процессы (если они будут созданы - fork()).
-i указатель инструкции во время системного вызова.
-k трассировка выполнения отслеживаемых процессов.
-n номера системных вызовов.

Данные трюки я использовал при отладке ПО. Работая системным программистом часто приходилось пользоваться strace. Если strace не работает, можно обратиться к файлу /proc/sys/kernel/yama/ptrace_scope, про него описано в man 2 ptrace.

#kernel #utils
Как смотреть журналы (dmesg и journalctl)

journalctl
- системный журнал (читает /var/log/journal).

Вывод в реальном времени:
$ journalctl -f


Отобразить сегодняшние записи:
$ journalctl -S today


Вывести только err уровень:
$ journalctl -S today -p err


err, warning уровни:
$ journalctl -S today -p 3..4


Показывает журнал конкретного сервиса:
$ journalctl -u <name>.service


dmesg - системный журнал ядра (читает /var/log/kern.log или напрямую из ядра).

less вывод:
$ dmesg -H


Читабельный формат:
$ dmesg -T


Показывает уровень (приоритет):
$ dmesg -x


Вывод в реальном времени:
$ dmesg -w


В сумме:
$ dmesg -HTx


Зачистить dmesg:
$ dmesg -C


#kernel #utils
LFS (Linux From Scratch)

LFS (Linux From Scratch) — это проект (и книга), который учит создавать Linux-дистрибутив буквально с нуля — вы компилируете и собираете каждый компонент вручную, начиная с ядра, libc, bash, gcc и далее.

- Получается минимальная, полностью самостоятельная система, не зависящая от других дистрибутивов.

- Процесс долгий, требует глубокого понимания Linux, компиляции, зависимостей.

- Система после сборки обычно не содержит ничего лишнего, только самые необходимые компоненты — всё остальное вы добавляете самостоятельно.

- LFS не предназначен для повседневного использования как обычный дистрибутив — это, прежде всего, учебный и исследовательский проект.

- На основе LFS можно строить свои собственные дистрибутивы, полностью контролируя набор программ и конфигураций.

LFS стоит использовать, если вы хотите глубоко разобраться во внутреннем устройстве Linux, получить максимальную свободу и контроль над каждым компонентом системы, экспериментировать с нетипичными настройками, патчами и структурой, а также если вас не устраивают стандартные дистрибутивы и вы готовы потратить много времени на ручную сборку и решение возникающих проблем. Кроме того, LFS подходит для создания минимальных систем под специфические задачи, например, для встраиваемых устройств или проведения экспериментов.

Ссылка: https://www.linuxfromscratch.org

Ссылка: https://ru.wikipedia.org/wiki/Linux_From_Scratch

Перевод книги на русский: https://book.linuxfromscratch.ru

#kernel #books #build
kernel-hardening-checker

Это инструмент и библиотека для Linux, предназначенная для проверки конфигурации ядра на соответствие рекомендациям по усилению безопасности (security hardening) и противодействию эксплойтам. Он позволяет выявить, какие конфигурации ядра включены, а какие нет, помогая администраторам настроить систему на более безопасный уровень работы.

Установка:
# Пакет проходит проверку и скоро появится в ветке sid (unstable)

Проверяет указанный файл конфигурации ядра Linux на включённые меры харденига и выводит отчёт с рекомендациями, опция -c указывает путь к конфигу:
$ kernel-hardening-checker -c /boot/config-6.1.0-32-amd64


> GitHub

#kernel #security #utils #opensource #software
Отладка ядра

Отладка ядра Linux напрямую (например, через gdb и vmlinux) обычно малоэффективна. Даже если загрузить символьный файл, большинство переменных будет отображаться как optimized out. Это происходит потому, что ядро нельзя собрать с флагом -O0: без оптимизаций оно будет слишком медленным, нестабильным и во многих случаях просто не загрузится. Поэтому vmlinux полезен в основном для просмотра структуры данных и отдельных символов, но не для полноценной пошаговой отладки.

Линус Торвальдс много раз подчёркивал: ядро — это не та система, которую нужно отлаживать классическим способом (breakpoint -> step -> step). Правильный подход — использовать трассировки и профилирование. То есть не "останавливать мир", а собирать информацию во время работы системы.

Итог: полноценная пошаговая отладка ядра на той же машине, где оно выполняется, невозможна и бессмысленна. Правильный путь — инструменты вроде printk, ftrace, perf, bpftrace, kprobes, tracepoints. Они дают детальную картину происходящего без остановки системы.

#kernel
Как модули попадают в ядро Linux

Когда ядро обнаруживает необходимость в тех или иных функциональных возможностях, ещё не загруженных в память, оно вызывает helper kmod (через механизмы uevent/hotplug). Kmod в свою очередь запускает утилиту modprobe, а уже modprobe вызывает insmod. Посмотреть можно так:
$ systemctl status kmod


Утилиты modprobe, insmod, modinfo и другие - это просто ссылки на /bin/kmod, они ничем не отличаются как отдельные бинарники. Всем заправляет один kmod, можно вызвать /bin/kmod напрямую и он сам определит, какую "утилиту" вы имели в виду.

kmod и modprobe запускаются ядром автоматически, когда требуется загрузка определённого модуля. modprobe принимает на вход имя модуля или его alias.

У модулей есть alias. Например, модуль qrtr в выводе lsmod имеет такое имя. Его alias можно посмотреть в /lib/modules/*/modules.alias. Например: net-pf-42 -> qrtr

Это значит, что modprobe можно передавать один и тот же модуль:
$ modinfo qrtr
$ modprobe net-pf-42

(Примечание: modinfo ищет только по реальному имени файла модуля, alias понимает modprobe)

Затем modprobe просматривает /lib/modules/*/modules.dep. Этот файл описывает модули, которые требуют загрузки других модулей перед своей загрузкой - то есть зависимости. Файл создается командой:
$ depmod -a


Например, модуль qrtr-mhi.ko запрашивает загрузку qrtr.ko и mhi.ko:
kernel/net/qrtr/qrtr-mhi.ko: kernel/net/qrtr/qrtr.ko kernel/drivers/bus/mhi/host/mhi.ko


Затем modprobe вызывает insmod (указывая путь из /lib/modules/*/), который загружает сначала зависимые модули, затем нужный модуль.

insmod довольно "глуп" в отношении нахождения модулей, поэтому принимает абсолютные пути и нужный порядок вручную:
$ insmod /lib/modules/2.6.11/kernel/fs/fat/fat.ko
$ insmod /lib/modules/2.6.11/kernel/fs/msdos/msdos.ko


modprobe более "умный" - он ориентируется по modules.dep, поэтому достаточно передать имя:
$ modprobe msdos


Для загрузки модулей, собранных вне дерева ядра, полезно иметь включённый CONFIG_MODVERSIONS=y

Он не обязателен для загрузки модулей в принципе, но позволяет обеспечивать совместимость символов между версиями ядра и модулей (versioned symbols), что уменьшает риск получить ошибку при insmod.

#kernel #utils
Процессы в ядре Linux

В ядре существует понятие "ядерных потоков" или "потоков ядра" (kernel threads, kthreads) - это легковесные процессы, которые выполняются полностью в пространстве ядра и никогда не переходят в пространство пользователя. Они используются для различных фоновых задач: управление устройствами, обработка событий, обслуживание подсистем ядра и другие служебные функции. Большинство kthreads создаются при загрузке системы или динамически ядром по мере необходимости.

Есть также процессы kworker (kernel worker). Это универсальные фоновые рабочие потоки, обслуживающие работу подсистем workqueue. Они выполняют задачи, которые были отложены другими частями ядра: обработка таймеров, deferred work, обслуживание драйверов, ввод-вывод, управление памятью и многое другое. Kworker‑процессы автоматически создаются ядром, масштабируются по количеству CPU и не связаны с конкретным приложением - они обслуживают всю систему.

kthread - это любой обычный поток ядра, созданный через kthread_create. Он выполняет свою собственную задачу, прописанную автором кода.

kworker - это специальный тип kthread, который используется подсистемой workqueue. Эти потоки создаются и управляются автоматически ядром, а не вручную.

Каждый kworker - это kthread.
Но не каждый kthread - kworker.

#kernel
ioctl()

Input/Output Control.
Это системный вызов в UNIX‑подобных системах, который позволяет отправлять драйверу устройства специальные команды, выходящие за рамки обычных операций read/write. Каждое устройство само определяет набор своих команд, поэтому ioctl даёт гибкий, но низкоуровневый механизм управления.

Команды для ioctl разрабатываются создателями драйверов устройств и могут варьироваться от драйвера к драйверу. Это мощный инструмент, но он также может быть опасным, так как позволяет выполнять низкоуровневые операции, которые могут повредить данные или аппаратное обеспечение, если они используются неправильно.

Используется для:
1. Выполнения операций, специфичных для устройства (например, очистка буфера).
2. Запроса информации, недоступной через read.
3. Настройки параметров драйвера или устройства.
4. Любых других операций, для которых нет стандартных системных вызовов.

Пример работы выглядит так.
В пользовательской программе вызывается команда:
ioctl(fd, IOCTL_GET_MSG, buffer)


Эта команда не читает данные напрямую, а сообщает драйверу: "выполни действие IOCTL_GET_MSG". Обычно для таких команд используются макросы _IOR, _IOW и _IOWR:
#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char*)


_IOR — получить данные из драйвера
_IOW — отправить данные драйверу
_IOWR — и отправить, и получить

В драйвере эти команды обрабатываются функцией ioctl, указанной в структуре file_operations:
struct file_operations Fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
.unlocked_ioctl = device_ioctl, // основной обработчик ioctl
.compat_ioctl = device_ioctl // нужен только для 32‑бит -> 64‑бит совместимости
};


Таким образом, ioctl создаёт "канал команд":
пользовательское приложение отправляет запрос -> драйвер получает код команды -> выполняет нужное действие -> возвращает результат.

Это простой способ расширить возможности устройства так, как нужно автору драйвера, не изобретая собственные протоколы поверх read/write.

#kernel
Rust

Компилируемый системный язык, ориентированный на безопасность памяти и отсутствие неопределённого поведения, без GC (garbage collector). Позволяет писать низкоуровневый код с производительностью на уровне C/C++, но значительно безопаснее благодаря модели владения и строгой типизации.

Где полезен:
- Backend: высоконагруженные сервисы (Actix, Axum), микросервисы.
- Системное программирование: драйверы, ОС‑компоненты, сетевые стеки.
- WebAssembly: написание высокопроизводительных частей веб‑приложений.
- Безопасная работа с параллелизмом: многопоточные сервисы и runtime‑системы.
- Инструменты и CLI: cargo, ripgrep, fd, starship — многие современные утилиты пишутся на Rust.

Плюсы:
- Высокая производительность, сравнимая с C/C++.
- Отличная экосистема: crates.io, tokio, serde, tracing.
- Cargo: один из лучших менеджеров пакетов/сборки в мире.
- Строгий анализ на этапе компиляции предотвращает целые классы ошибок.
- Безопасность памяти без garbage collector — нет segfault, нет use‑after‑free.

Минусы/реалии:
- Компиляция тяжелее и медленнее, чем у C.
- Встраивание Rust в очень старые экосистемы (например, firmware) может быть сложным.
- Иногда низкоуровневые операции требуют unsafe (компилятор снимает с себя ответственность).
- Крутая кривая обучения из‑за модели владения и borrow checker (строго контролирует доступ к памяти).

Rust vs C/C++:
- Безопаснее C/C++ благодаря строгой модели владения.
- Но C всё ещё проще интегрировать в старые системы и ABI стабильнее.
- Производительность сопоставима или выше, особенно в многопоточных задачах.
- Для embedded Rust часто удобнее C++, но не всегда доступен на самых низких MCU.

Rust в ядре Linux:
- Rust официально принят в mainline Linux (начиная с 6.1).
- Поддержка пока ограничена, но активно развивается.
- Можно писать драйверы и части подсистем ядра, но API Rust в ядре ещё не полный.
- В ядро Rust включён не для переписывания всего, а для безопасных новых драйверов.
- Модули ядра на Rust уже возможны, но только те, которые используют предоставленный Rust‑абстракционный слой (kernel crate).

Где Rust нужен в Linux:
- Пользовательские утилиты: многие современные CLI (ripgrep, exa, fd, bat, starship) уже стандарт-де-факто.
- Внутренние абстракции ядра: безопасные обёртки над указателями, блокировками, refcount, pinning.
- Рендеринг и графика: wgpu (кроссплатформенный WebGPU/Vulkan/Metal/DX12 backend), rend3.
- Игры: на Rust пишут игры и игровые движки с поддержкой Linux (Bevy, Fyrox, Amethyst).
- Новые драйверы: сетевые, USB, storage, сенсоры — безопасное ядро без use-after-free.
- Аудио и DSP: rodio, kira, cpal.
- WebAssembly: выполнение WASM‑модулей на Linux (wasmtime, wasmer).
- DevOps/инфраструктура: контейнерные рантаймы, файловые утилиты, CI‑инструменты.
- Сетевые сервисы: высокопроизводительные backend‑приложения под Linux (Axum, Actix).
- Security‑инструменты: сканеры, песочницы, анализаторы (Rust популярен в security‑комьюнити).
- Файловые системы и блочные устройства: есть исследования и эксперименты по FUSE‑драйверам на Rust.

Сложность:
- Порог входа выше среднего.
- Но после понимания модели владения продуктивность высокая.
- Отлично подходит для кода, где важна безопасность + скорость.

Итог: Rust — мощный системный язык, который сочетает скорость C с безопасностью на уровне высокоуровневых языков (Rust ведёт себя по скорости как C). Подходит для драйверов, системного ПО, сетевых сервисов и CLI. Linux уже официально поддерживает Rust, и будущее ядра включает постепенное расширение Rust‑подсистем для безопасных драйверов и новых модулей.

#misc #kernel
Анализ исправления ошибок в ядре Linux - в среднем ошибки замечают через 2 года

Новость: https://www.opennet.ru/opennews/art.shtml?num=64574

#kernel #news