16270
Присоединяйтесь к нашему каналу и погрузитесь в мир для C/C++-разработчика Связь: @devmangx РКН: https://clck.ru/3Foc4d
Ты знал, что в IP-адресе можно «выкидывать» нули, и он всё равно будет работать?
Например:
10.20.0.2 → 10.20.2
10.0.0.68 → 10.68
В обоих случаях ты попадёшь на тот же самый хост.
Это одна из тех мелких, но прикольных особенностей IP, которые я использую в лабораторках, экономит пару нажатий каждый раз.
👉 @Cpportal
Классический пример pass by value и pass by reference.
Допустим, нам нужно поменять местами значения x и y.
swap(int a, int b);
swap(int *a, int *b);
Чип на 8 КБ. Написано на C. И этого оказалось достаточно, чтобы разблокировать этот телефон.
👉 @Cpportal
Как двоичные данные транслируются в инструкции ассемблера
👉 @Cpportal
Dive into Systems – топовая бесплатная книга по системному программированию на C
Разбирают:
- как работает компьютер на низком уровне
- основы C для системного программирования
- оптимизацию кода
- ассемблер под разные архитектуры (x86, ARM и др.)
Плюсом попробуй ASM-визуализатор – пишешь C-код → сразу видишь, во что он превращается на ассемблере
Чекай тут → diveintosystems.org/book
👉 @Cpportal
Разработчик представил собственный C++ inference-движок для LLM, который полностью работает на CPU и уже выдает около 60 токенов в секунду.
В текущей версии реализованы GPT-2, byte pair encoding, KV-кеш, greedy и temperature-сэмплирование, а также SIMD-оптимизации через NEON-интринсики. В планах разработчика добавить flash attention, operator fusion, многопоточность, квантизацию с бенчмарками, поддержку новых архитектур и перейти к GPU-вычислениям через CUDA C++.
👉 @Cpportal
Изоляция процессов в Linux держится на двух вещах:
1. Виртуальная память
2. Приватные адресные пространства
Процесс A не может трогать данные процесса B.
Если только не использовать shmget (системный вызов №29 на x86_64).
Он буквально пробивает дыру в этой изоляции и позволяет процессам шарить один и тот же участок физической RAM.
Большинство IPC (pipes, сокеты и прочее) заставляет ядро копировать данные.
Процесс A пишет в ядро -> ядро копирует данные процессу B.
Shared memory этого избегает.
Разница примерно такая же, как пересылать Excel-файл туда-сюда по почте против совместного редактирования Google Sheet в реальном времени.
Вот полностью рабочий пример. Дочерний процесс меняет данные в shared memory, родитель видит изменения — доказательство того, что оба PID работают с одним и тем же физическим адресным пространством.
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main() {
int id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
char *mem = shmat(id, NULL, 0);
strcpy(mem, "Hello!");
if (fork() == 0) {
// Child: read, modify, exit
printf("Child [%d] sees: %s\n", getpid(), mem);
strcpy(mem, "Changed by child!");
} else {
wait(NULL);
// Parent: see child's modification
printf("Parent [%d] sees: %s\n", getpid(), mem);
shmctl(id, IPC_RMID, NULL);
}
return 0;
}
Child [12346] sees: Hello!
Parent [12345] sees: Changed by child!
Вот так для меня звучат все эти любители «красивых высокоуровневых абстракций»
👉 @Cpportal
Задачки для тех, кто хочет прокачать GPU-программирование 🔥
Если хотите разобраться, как работают GPU и параллельные вычисления, попробуйте GPU-Puzzles
Это набор интерактивных задачек, которые помогут освоить вычисления на графических процессорах. Отличный вариант для изучения CUDA и оптимизации кода!
🟡Интерактивные упражнения
🟡Фокус на понимание GPU-алгоритмов
🟡Подходит как новичкам, так и опытным разработчикам
А здесь реализация задач на C++ — тык
👉 @Cpportal
Инженер представил экспериментальный 8-битный софт-кор Mrav, работающий на FPGA. На вид скромный чип, но идея за ним куда интереснее: собрать железо и софт как единую систему, без разрыва между Verilog и C/ASM.
В классических embedded-проектах железо и прошивка живут отдельно. Здесь же всё сведено в один репозиторий, а Bazel выступает «клеем». Сборка не только компилирует код, но и генерирует RTL на основе тех же определений. Контроллер памяти синтезируется сразу с бинарником внутри.
Автор называет это Hermetic Engineering: никакой ручной установки тулчейнов, симуляторов или FPGA-утилит. Одна команда поднимает окружение, собирает инструменты и прогоняет симуляцию. Получается полностью воспроизводимый «компьютер в коробке».
Для тех, кто интересуется SystemVerilog, Go, Bazel или просто любит смотреть, как с нуля рождаются процессоры, проект стоит внимания. 😎
Ссылка на проект: https://popovicu.com/mrav-cpu/
👉 @Cpportal
Я обычно скептически смотрю на весь шум вокруг новых проектов, которые появляются пачками, но Zig реально выглядит как крутая тема.
Не так часто встретишь инструменты, собранные настолько аккуратно.
Один чистый статически слинкованный бинарь и всё нужное уже внутри.
👉 @Cpportal
Проверь z-libs, если нужен удобный high-level API без потери сырой производительности C.
Сейчас там четыре маленькие однозаголовочные C-библиотеки, которые наконец делают работу с контейнерами в C нормальной:
→ zvec.h (динамический вектор, contiguous-память, swap-remove, сортировка/поиск)
→ zstr.h (нормальная UTF-8 строка с 22-байтовым SSO, views, форматирование, split)
→ zlist.h (двусвязный список, non-intrusive, splice за O(1))
→ zmap.h (hash table с open addressing, linear probing и cache-friendly поведением)
Дополнительно:
→ Ноль зависимостей
→ C11 и выше (строго по стандарту)
→ Полная type safety
→ Поддержка кастомных аллокаторов
→ MIT-лицензия
Работает в GCC, Clang, MSVC и так далее.
Никаких build-систем, никакого void*-хаоса и никакого макро-аду.
Просто кидаешь нужный .h — и оно работает.
Смотреть тут: https://github.com/z-libs
👉 @Cpportal
Объяснение race conditions простыми словами. Хорошая отправная точка, чтобы разобраться с проблемами, которые возникают при работе с конкурентностью.
https://youtu.be/FY9livorrJI
👉 @Cpportal
gRPC обычно ассоциируется с микросервисами поверх HTTP/2.
Но знаешь, что можно гонять gRPC по шине гипервизора в Linux?
Вот как использовать vsock, чтобы управлять локальными виртуалками, не трогая сетевой стек.
AF_VSOCK это семейство сокетов в Linux, которое обеспечивает коммуникацию между хостом и гостевой системой. QEMU поддерживает его нативно через устройство vhost-vsock-pci.
В gRPC на C++ это почти то же самое, что TCP. Единственное отличие это адрес. Вместо 127.0.0.1:8080 ты просто пишешь vsock:3:9999.
Всё остальное на уровне транспорта берет на себя библиотека gRPC.
Сервер: статически собранный бинарник, который запускается как init внутри гостевой QEMU-машины.
Клиент: статически собранный бинарник, который работает на хосте.
Они выполняют арифметику через RPC, полностью обходя сетевую карту.
Зачем это делать?
Безопасность: сокет не торчит в локальную сеть.
Производительность: задержка ниже, чем у loopback TCP.
Проще настройка: никакого DHCP или сетевых мостов.
Хочешь попробовать? Вот гайд, как собрать это с нуля на Bazel и C++.
В нём есть нужные флаги для QEMU, Proto-файлы и процесс сборки debootstrap-образа, плюс ссылка на GitHub.
👉 @Cpportal
Неправильное использование двумерных массивов может убить производительность.
Есть два простых способа создать двумерный массив int:
int**: выделять память построчно через malloc в цикле
int*: один большой непрерывный блок памяти
Разница? Первый вариант заметно медленнее.
Почему так происходит? Все упирается в cache locality.
Когда память выделяется для каждой строки отдельно, аллокатор разбрасывает их по разным участкам RAM.
Аппаратный prefetcher процессора пытается предугадать следующий адрес, но из-за разрозненности строк он промахивается. В итоге процессор простаивает, ожидая данные из оперативной памяти.
И да, RAM примерно в 100 раз медленнее L1 cache.
В случае с непрерывным блоком такого не происходит. Prefetcher спокойно подгружает данные подряд без задержек.
Итог=хороший разработчик знает, как работают указатели. А отличный понимает устройство памяти и важность локальности данных.
👉 @Cpportal
Хочешь стать ниндзя в CUDA?
Начни с нового CUDA Programming Guide. Раздел 4 это твоя золотая жила.
Там собраны фичи, о которых большинство разработчиков даже не в курсе, а они дают серьёзный буст по производительности, более умную отладку и более чистый GPU-код.
Так что повысьте уровень своей игры на GPU
👉 @Cpportal
fff.nvim официально объявили самым быстрым файловым поиском
Разработчики fff.nvim показали демо поиска в реальном времени по директории на 100 000 файлов объёмом 6 ГБ из полного git-дерева ядра Linux.
По их словам, в реализации нет debounce. Поиск идёт прямо в основном UI-потоке, при этом система выдерживает до 120 поисковых запросов в секунду.
Среднее время одного запроса составляет 4,5 мс.
👉 @Cpportal
Разработчик представил кастомный CPU, полностью собранный с нуля, и показал, как автоматизировал генерацию SoC, чтобы избежать рассинхрона между железом и софтом.
Вместо ручной сборки на Verilog он использует Bazel как единый источник истины. Периферия описывается один раз в конфиге, после чего билд-система автоматически генерирует SystemVerilog для шины и адресного пространства, создаёт ассемблерные библиотеки с нужными символами и вшивает прошивку прямо в RAM на уровне RTL.
Любое изменение в конфигурации мгновенно обновляет и аппаратную, и программную часть. Без дрейфа, только полностью синхронизированная генерация.
Подробный разбор архитектуры доступен здесь ✋
👉 @Cpportal
Это... программирование как у истребительного пилота.
Одна необработанная ошибка уничтожила ракету за 500 миллионов долларов за считанные секунды.
F-35 не собирался повторять эту ошибку.
Инженеры, аккуратно «разрезая» C++, создали один из самых жестких стандартов кодинга, когда-либо написанных.
Фулл видео: смотрим
👉 @Cpportal
Комьюнити, полезное для всех бекенд-разработчиков
Как работает VK изнутри? Что происходит за интерфейсами, когда миллионы пользователей одновременно отправляют сообщения, загружают фото и смотрят клипы?
В канале Backend VK Hub мы рассказываем о работе всех наших сервисах: от VK Play до Tarantool. Делимся подходами к масштабированию, оптимизации и новым архитектурным решениям. Открыто дискутируем, а также регулярно публикуем вакансии в нашу команду.
Здесь — реальные кейсы, технические разборы, советы от наших экспертов и возможность поговорить с ними в любой момент. Подписывайся!
🔥3 декабря в Москве прошла OS DevConf 25 powered by GigaChat — конференция про разработку системного ПО, ядра Linux и open source
30+ докладов, 3 трека — концентрат практического опыта, знаний и инструментов, готовых к внедрению сразу по возвращению в офис.
Поговорили на такие темы:
-Инструменты и примеры отладки, виртуализации, оптимизации производительности
-Практический опыт оптимизации сетевых решений с DPDK
-Эффективные методы безопасной разработки ядра Linux
-Реальные кейсы создания драйверов на Rust
-Все про GPU, NPU, ASIC и как запускать AI на железе под Linux и не только. Как AI встраивается в современную разработку
-Современные подходы к разработке системного и embedded ПО
Много активностей, полезных докладов, и конечно же афтепати.
Уже скоро выложим видеозаписи конференции в наших соцсетях, а пока присоединяйтесь к сообществу по разработке системного ПО и Linux в России!
#реклама
О рекламодателе
Команда энтузиастов собрала впечатляющий набор проектов на миниатюрном ESP32C3 — микроконтроллере с 400 КБ RAM и одним RISC-V ядром. На этой скромной платформе им удалось запустить сразу несколько вполне серьезных штук:
• Space Invaders
• 3D wireframe-рендеринг в реальном времени
• распознавание жестов с помощью ML
• Wi-Fi-сканер
• систему кастомных bitmap-логотипов
В работе использовали C++, Adafruit GFX, ручную математику матриц для 3D и Python для конвертации в RGB565.
Весь набор железа обошелся примерно в 8 долларов.
Хороший пример того, как даже микроскопические ресурсы не мешают выпускать работающие проекты.
👉 @Cpportal
Linux-ядро обычно просто угадывает.
Когда оно управляет памятью, кеширует файлы или свапает страницы, всё держится на эвристиках.
Но иногда твоё приложение знает будущее.
Тут и появляется madvise (syscall №28 на x86_64).
Вот как перестать играть в угадайку.
madvise() позволяет шепнуть подсказку напрямую менеджеру памяти ядра.
Ты передаёшь диапазон памяти и стратегию.
«Я стримлю данные.»
«Я закончил с этим блоком.»
«Это секрет.»
Данные не меняются. Меняется только то, как ОС работает с физической RAM под ними.
Работаешь с ключами шифрования? 🔑
Используй MADV_WIPEONFORK
Это говорит ядру: «Если процесс сделает fork, отдай ребёнку нули вместо копии этого диапазона.»
Это предотвращает утечку секретов в дочерние процессы. (Работает только с private anonymous memory.)
#include <sys/mman.h>
// Protect the secret
madvise(secret_key, key_len, MADV_WIPEONFORK);
MADV_SEQUENTIALMADV_GUARD_INSTALL 🛡
❤️ Как не попасть в ловушку масштабирования при росте нагрузки в PostgreSQL?
В видеопроекте Road to Highload разработчик ядра Яндекс Диска Андрей Колнооченко рассказывает, как проектировать и развивать базы данных так, чтобы они оставались стабильными и быстрыми даже при росте QPS и объёма данных.
Разберём реальные примеры и обсудим типичные ошибки и подходы, которые помогают избежать проблем с производительностью и консистентностью. Особое внимание уделим согласованности кода и данных в БД для предотвращения проблем с race conditions, которые часто возникают при росте нагрузки.
Road to Highload — это цикл видео от Яндекс 360 о том, как строятся системы, которыми ежедневно пользуются миллионы людей и тысячи компаний. Здесь говорят о highload и отказоустойчивости не по учебникам, а на основе многолетнего опыта разработки.
Memory-mapped I/O на Linux работает быстро, но у этого подхода есть неприятный момент.
Когда ты пишешь в memory-mapped файл (mmap), ты не пишешь на диск. Ты пишешь в RAM, точнее в Page Cache.
Если в этот момент пропадет питание, данные улетят в небытие.
Здесь появляется msync (системный вызов номер 26 на x86_64). Это своего рода кнопка Save для mmap.
Когда ты делаешь mmap() файла, ядро напрямую отображает блоки файла в память.
Чтение и запись происходят в памяти и не требуют read() или write(), что экономит системные вызовы.
Но эти измененные страницы живут в RAM, пока фоновые процессы ядра не сбросят их на диск. А слово "когда-нибудь" не подходит, если речь про важные данные.
msync позволяет указать диапазон памяти и заставить ядро записать его на устройство хранения.
Это мост между скоростью оперативки и безопасностью постоянного хранилища.
Пример на C:
int fd = open("db.dat", O_RDWR);
char *p = mmap(0, 4096, PROT_WRITE, MAP_SHARED, fd, 0);
// Запись в RAM
sprintf(p, "Critical Data");
// Сброс на диск
msync(p, 4096, MS_SYNC);блокируй выполнение и не возвращай управление, пока данные не окажутся на диске.
Лучшее, что может получить программист C++
https://agner.org/optimize/optimizing_cpp.pdf
👉 @Cpportal
Наглядно как выглядит выравнивание данных в памяти
👉 @Cpportal
А что если компилятор помогал бы писать потокобезопасный C++ код?
В этой статье объясняется, как Clang использует аннотации и статический анализ, чтобы находить race conditions еще на этапе компиляции.
https://research.google.com/pubs/archive/42958.pdf
👉 @Cpportal
Тебе не обязательно настраивать сеть, чтобы коннектиться к своей Linux VM.
Ни IP-адресов. Ни SSH-ключей. Ни правил в фаерволе. Ни таблиц маршрутизации.
Если хост и виртуалка работают на одной физической машине, TCP/IP иногда просто лишний слой.
Знакомься: AF_VSOCK.
Это специальное address family в ядре Linux, рассчитанное именно на обмен данными между гипервизором и виртуальными машинами.
Можно представить это как трубу, которая проходит сквозь стену виртуалки.
Вместо IP (192.168.x.x) используется Context ID (CID). У хоста обычно CID 2. У гостя свой CID, например 3.
Дальше всё делает ядро, гоняя данные между памятью хоста и гостя.
Сервер крутится внутри виртуалки (C++). Клиент работает на хосте. А задержка? Почти нулевая.
Если тебе нравится низкоуровневая возня с Linux — ставь лайк 👍
👉 @Cpportal
У процесса в Linux может быть раздвоение личности. 🎭
У него сразу две идентичности:
1. Реальная (тот пользователь, который запустил процесс).
2. Эффективная (пользователь, от имени которого процесс сейчас выполняется).
На этом работает sudo. И из-за этого появляется интересная задачка с точки зрения безопасности.
Загадка такая: программа, запущенная с root правами (эффективный ID), должна понять, может ли исходный пользователь (реальный ID) получить доступ к файлу.
Как ей проверить твои права, не отказываясь от своих root-возможностей? Просто вызвать open() не получится, он смотрит только на эффективный ID, у которого полный доступ.
И вот зачем существует системный вызов access()
Он уникален тем, что проверяет права доступа к файлу по реальному UID процесса, а не по эффективному.
Он позволяет привилегированной программе безопасно спросить у ядра:
"Тот пользователь, который меня запустил, вообще может читать этот файл?"
#include <unistd.h>
#include <stdio.h>
int main() {
if (access("/somefile", R_OK) == 0) {
printf("Real user can read /somefile.\n");
} else {
perror("access");
}
return 0;
}