Всем привет!
Пишу этот пост, чтобы поделиться своим опытом и получить критику или советы от людей с большим опытом.
Мне 22 года, я из Латвии. По об��азованию я судовой механик, но уже около 4 лет увлекаюсь программированием. Долгое время это оставалось хобби: пробовал сайты, простые игры — но они не приносили настоящего удовольствия. Я считал, что в программировании нужно было разбираться ещё со школы, и долго не верил, что могу найти себя в этой сфере.
Переломный момент наступил, когда я заинтересовался системным программированием. Каждый раз, когда узнаю, как работает низкоуровневая часть ОС, у меня будто открывается новый мир. Особенно зацепила тема процессорного планирования: все говорят «железо, CPU, видеокарта», но на практике даже реализация планировщика процессов может заметно влиять на производительность.
Учёба и идея проекта
Год назад я поступил в университет на программу Computer Systems, чтобы увеличить свои шансы на работу в ИТ. Но, к сожалению, программа оказалась сильно смещена в сторону веба и сетей. Поэтому я сделал ставку на самообучение и параллельно развивался в системном направлении, а университет оставил для диплома.
На одном из экзаменов по ООП нужно было реализовать программу с применением объектно-ориентированного подхода. Тогда я решил совместить приятное с полезным — сделать первый серьезный pet-проект который:
можно защитить на экзамене;
покажет, что я "умею" проектировать и писать код;
и будет реально интересен мне самому.
Так родилась идея synd3 — сообственного процесс-менеджера для Linux.
От идеи до реализации
Когда я впервые познакомился с Linux через WSL (Windows Subsystem for Linux), мне понадобилось отслеживать нагрузку на систему. Я запустил htop — и сразу заметил, что отображение загрузки CPU идет по ядрам, а не по суммарной мощности процессора.
Мне захотелось сделать инструмент, который, по моему мнению, будет отображать статистику более "человечно" и интуитивно.
Мы работали над проектом вдвоем и решили разделить обязанности:
Логика на С,
Интерфейс (TUI) на С++ с использованием ncurses и ООП.
Сборка проекта осуществляется через простой Makefile, который компилирует оба модуля и связывает их.
Как synd3 работает внутри
Подсчет загрузки CPU
Основные данные synd3 получает из файлов /proc/stat и proc/[PID]/stat.
Для каждого процесса мы вычисляем разницу между его пользовательским (utime) и системным (stime) временем между двумя циклами опроса.
Затем результат нормализируется относительно общего CPU време��и, чтобы получить процент загрузки.
Если "упростить", то мы измеряем, сколько тиков CPU досталось процессу за последний интервал, и сравниваем это с общим временем работы всех ядер за тот же промежуток.
Пример логики в упрощенном виде:
unsigned long long prev_total = total_ticks();
unsigned long long prev_proc = process_ticks(pid);
sleep(1);
unsigned long long total = total_ticks();
unsigned long long proc = process_ticks(pid);
double usage = 100.0 * (proc - prev_proc) / (total - prev_total);Подсчет использование памяти
В synd3 для вычисления использования памяти реализована функция get_process_mem_usage(pid_t pid, float *mem_usage).
Она не просто считывает VmRSS а учитывает весь контекст использования памяти — в том числе кэш, буферы, и reclaimable-области, чтобы получить более точное значение реальной нагрузки.
Алгоритм выглядит примерно так:
Считываются метрики /proc/meminfo: MemTotal, MemFree, Buffers, Cached, SReclaimable.
Подсчитывается используемая память:
used_mem = MemTotal - MemFree - Buffers - Cached - SReclaimable;Для каждого процесса извлекается VmRSS из /proc/[PID]/statm.
Расчитывается процент использования памяти:
*mem_usage = (VmRSS / used_mem) * 100.0;
При этом в коде учитываются ситуации, когда /proc[PID]/statm может временно отсутствовать (например, при завершении процесса), а так же ошибки при чтении.
Такой подход дает более реалистичную картину загрузки памяти, чем простое чтение RSS — ведь часть памяти может быть кэширована или освобождена системой, но еще не возвращена пользователю.

Проблемы и неожиданные открытия
Когда мы впервые тестировали synd3, первое, что нас удивило — разное поведение программы под WSL и полноценным Linux. Тестируя программу на полноценном Linux, мы столкнулись с тем, что в synd3, отображались процессы без имени. У них был PID, однако имя отсутствовало. Нас это насторожило, так как тестируя на WSL, мы такой проблемы не наблюдали.
Оказалось, что в WSL процессы без имени не отображаются в /proc обычными средствами, из-за чего список в synd3 выглядел “аккуратнее”. Проще говоря, эти процессы “фильтруются“ и не видны.
На реальной системе же таких процессов много, и часть из них просто не имеет ничего в строке в /proc/[PID]/cmdline.
Проблема решилась добавлением одной проверки: если при чтении /proc/[PID]/cmdline функция fgets() возвращает NULL (что озночает, что строка пуста и у процесса нет имени), то такой процесс мы просто пропускаем.

Вторая проблема оказалась куда интереснее.
Изначально мы хотели, чтобы интерфейс обновлялся каждую секунду в отдельном потоке, пока логика считывает метрики. Но довольно быстро ncurses буквально "сломался" — текст начинал мигать разными цветами, символы наслаивались друг на друга, а вывод вел себя хаотично, будто "матрица" на минималках.
После нескольких бессоных вечеров и десятков printf-отладок мы наконец поняли причину:
ncurses не является потокобезопасной библиотекой.
Все операции по выводу должны выполнятся строго из одного потока, иначе внутренние буферы ncurses начинают конфликтовать — именно поэтому происходила "рябь" и разъезжавшийся текст.
Мы пробовали использовать мьютексы и ручную синхронизацию, но это только усложняло код.
В итоге мы отказались от многопоточности для интерфейса и сделали обновление экрана синхронным: сначала сбор данных, потом отрисовка.

Да, интерфейс обновляется чуть реже, зато стабильно, без артефактов и цветных глюков.
Этот опыт, пожалуй, стал самым ценным: теперь мы четко понимаем, что TUI-библиотеки (вроде ncurses) требуют однопоточного вывода и аккуратного обращения с буферами.
Планы на будущее
Переписать проект полностью на С, отказаться от ООП и снизить уровень абстракции.
Сделать архитектуру ближе к POSIX.
Реализовать мониторинг потоков.
Разработать клиент-хост взаимодействие, чтобы можно было мониторить процессы на удаленной машине.
Улучшить интерфейс: добавить дерево процессов и адаптивную перерисовку при изменении размера окна.
Репозиторий проекта
Проект лежит на GitHub: oxonomiAK/synd3.
Зачем пишу
Я не призываю никого пользоваться нашей программой — просто хочу понять взгляд со стороны.
Любая критика, советы или даже просто впечатления будут очень ценны.
Мне также интересно, почему кто-то выбирает htop, а кто-то — btop++ или даже glances?
Что именно для пользователя важно в системных мониторах: функциональность, визуальная часть, минимализм, или, может быть, производительность?
Я хочу понять, какие решения делают подобные инструменты удобными и живыми, а не просто «ещё одним монитором процессов».
Всё это поможет точнее направлять развитие как synd3, так и других будущих проектов — чтобы они были не просто учебными, а реально полезными
Спасибо, что дочитали!
