CompTalks
16 subscribers
29 photos
1 video
2 files
14 links
Download Telegram
На першій частині стріма, я розширив декодування інструкцій та набір opcode'ів. Включено повний список базових інструкцій ARM64. Додано допоміжні функції декодування.

Єдине, що не реалізовано це гілки та операції з пам'яттю, вони залишаються як OPCODE_UNKNOWN для майбутньої реалізації.

https://github.com/DenysSkobalo/silico/commit/735e18c706178ba4bb72e015f40f924b3f8eb76c

Продовжую далі😌
За три години стріма, розширив DecodeInstr, ввів InstrClass для класифікації інструкцій (арифметика, логічні, гілки, памʼять, системні). Переписав decode() та імплементував execute() для підтримки цієї класифікації. Виніс арифметичні та логічні інструкції у execute_alu(). Додано інструкції: ADD, SUB, ADDI, SUBI, MUL, MOVZ, MOVN, MOVK, AND, ORR, EOR, ANDI, ORRI, EORI.

Додано повідомлення про невідому інструкцію з точним PC, щоб легше відловлювати баги.

У main.c тепер є зручний приклад з повним тестовим набором інструкцій, які працюють: обчислення, логіка, завантаження констант, зсуви.

Commit 1: https://github.com/DenysSkobalo/silico/commit/99468597a66ed3c3012fd468f3e5d6af19ef78b7

Commit 2: https://github.com/DenysSkobalo/silico/commit/dd4d1cc077181f082c3554a6725b3b5758231fa1
Літо всралося, відпочинок закінчився, час знову грузнути в грьобаному універі й розгрібати свої проєкти. Останній курс, тому треба добивати все, що почав.

Кілька місяців тому я запускав експеримент — писати свою мінімальну ОС. Потім забив, але репо на GitHub залишив. І ось тиждень тому дістав його з архіва й нарешті почав рухати далі.

Що вже зроблено:
- прибрав старий 16-бітний bootloader на ASM;
- завів Multiboot через GRUB та ISO;
- організував лінкування ядра через LD і NASM;
- написав мінімальне ядро на C з виводом на VGA;
- навів лад у Makefile: тепер є build, iso, qemu, docker;
- додав build.sh для Docker-збірки.

Проєкт оживає, і навіть у такому мінімальному вигляді він уже приносить кайф. Далі буде цікавіше.

Репо: https://github.com/DenysSkobalo/detux
На днях, мені прийшов мікроконтролер на базі ESP8266EX. В ній присутній WiFi (802.11 b/g/n) з TCP/IP стеком, SRAM (64KB instructions + 96KB data), SPI Flash 4 MB, GPIO, SPI, I^2C, UART, PWM, ADC.

І перше, що я вирішив на ньому зроюити, це підняти легкий вебсервер. Написав все на С++ та скомпілював для Arduino через заголовковий файл. А далі все постандарту, збірка проєкта та прошивка через Makefile. Одне з мінусів те, що я не маю доступу до роутера тому підняв через телефон хотспот та підключився до нього і на ПК на якому потрібно відкрити піднятий сервер, він повинен теж бути підключеним до WiFi (у моєму випадку хотспот), що підключений сам сервер. Далі відкриваєм IP-адрес котрий пише на OLED, що підключений до чіпсета, вбиваємо в браузер, відкривається сайт, пишемо повідомлення та отримуємо повідомлення на екрані, що було написано на сайті.

Але, щоб вирішити проблему щодо відкриття сайту з любого WiFi, то я придумав рішення. Можна прокинути тунель через Ngrok або Cloudfare Tunnel, але я вибрав Ngrok, прокинув тунель, отримав згенероване рандомне URL-посилання і все працює так само.

Ось такий невеликий, але доволі цікавий проєкт. Нижче залишаю посилання на репо.

https://github.com/DenysSkobalo/ESP8266-webAP
CompTalks
На днях, мені прийшов мікроконтролер на базі ESP8266EX. В ній присутній WiFi (802.11 b/g/n) з TCP/IP стеком, SRAM (64KB instructions + 96KB data), SPI Flash 4 MB, GPIO, SPI, I^2C, UART, PWM, ADC. І перше, що я вирішив на ньому зроюити, це підняти легкий…
Продовжую гратись з ESP8266EX 🙂
Після того як підняв базовий вебсервер і прокидав тунель через Ngrok, я вирішив трохи ускладнити завдання.

🔹 Тепер мікроконтролер працює у режимі Access Point (AP) -- тобто він сам створює WiFi-мережу. Не потрібно ніякого роутера чи хотспоту з телефону: ESP8266 піднімає свій SSID, показує його та IP прямо на OLED-екрані, і до цієї мережі можна підключитися будь-яким пристроєм. Відкриваєш браузер → заходиш за IP → бачиш сайт із ESP.

По суті, ESP8266 перетворився на мініатюрний роутер із власним вебсервером.

Репо той самий, але тепер у ньому інша назва:
https://github.com/DenysSkobalo/ESP8266-webAP
Давно не читав, що там в "улюбленому" ІТ ринку робиться, і наткнувся на нове дослідження Гарварду (62 млн резюме + 285 тис. компаній) показало цікаву річ.

До 2022 року все було рівно: і джуни, і сеньйори росли в кількості.
Але з початку 2023 року, коли компанії масово почали інтегрувати ChatGPT-подібні інструменти, відбувся так сказати перелом:
- джуни пішли вниз, їх перестали активно наймати,
- сеньйори залишились у плюсі, їх найм продовжився.

Особливо сильно це вдарило по оптовій і роздрібній торгівлі.
Але цікаво не масові звільнення, а саме зменшення найму а тих, хто вже всередині компанії, навпаки, частіше піднімають.

Найбільше втратили випускники “середніх” університетів. Еліта та самий низ залишилися більш захищеними.

Висновок такий, що генеративний AI робить кар’єрну драбину вужчою знизу. Увійти в гру джунам стало важче, а нерівність лише зростатиме.

https://papers.ssrn.com/sol3/papers.cfm?abstract_id=5425555
👍1
Project DB.zip
6.3 MB
Перший за три роки університетський проєкт, який реально викликав інтерес, проєктування і реалізація бази даних для керування віртуальними машинами (PostgreSQL + Docker).
Нарешті завдання, де можна було мислити як інженер, а не просто писати блять базові алгоритми або слухати брєд професорів без досвіду.

*прикріпляю зіпку проєкта зверху, там і скрипти, і документація на французькій та українській
🔥2
AI повністю змінив відчуття від програмування.
Раніше застряг, значить, кілька днів у StackOverflow, Reddit і нескінченних костилях.
Тепер просто чекаєш апдейт моделі або перемикаєшся на іншу LLM, і все запрацювало. І ми навіть ще не в еру AGI
Сьогодні хочу поділитися невеликим експериментом із low-level програмування на macOS – це Data Link Sniffer, простий sniffer Ethernet/Wi-Fi, побудований на основі BPF (Berkeley Packet Filter).

Ідея дуже проста, але водночас демонструє роботу з мережею на найнижчому рівні: ми читаємо сирі Ethernet-фрейми з мережевого інтерфейсу, а потім виводимо MAC-адреси відправника та отримувача і тип кадру (EtherType).

Технічно, програмі потрібні лише:
- macOS,
- права root (щоб отримати доступ до /dev/bpf*),
- компілятор Clang.

Після компіляції (make) та запуску (sudo ./bpf_sniffer) можна спостерігати трафік у реальному часі. Варто пам’ятати, що на Wi-Fi в managed mode ви не побачите всі підключені пристрої для цього потрібен monitor mode. І ще невелике зауваження: іноді macOS може виводити попередження про BIOCSETBUFSIZE – його можна ігнорувати.

Цей проєкт чудовий приклад того, як низькорівневе програмування дозволяє отримати доступ до мережі на рівні кадрів, обходячи високорівневі API. Для тих, хто цікавиться мережею, BPF і системним програмуванням, це відмінний старт/

Github Repo:
https://github.com/DenysSkobalo/bpf_sniffer
Три тижні тому в мене прийшла ідея зробити маленьку утиліту для macOS: щоб клавіатура автоматично переключалась залежно від активного додатку. Наприклад, коли я відкриваю Telegram — розкладка українська, а коли відкриваю термінал — англійська. Потім я трохи забив на цю ідею… і ось учора вирішив нарешті реалізувати її.

Ідея виявилась цікавою, бо на перший погляд здається простою, але насправді довелось продумати декілька речей: як відслідковувати активний додаток і як переключати розкладку клавіатури у реальному часі.

Розробка йшла поетапно:
1. Моніторинг активного додатку
Спочатку я пробував різні способи отримати назву активного вікна. Виявилось, що найстабільніше працює NSWorkspace.sharedWorkspace().frontmostApplication через Objective-C код. Це стало основою модуля macos_bridge.m, який підключений до C-проєкту через заголовки macos.h та macos_bridge.h.
2. Зміна розкладки
Наступний крок — переключення розкладки клавіатури. Для цього я реалізував функцію set_keyboard_layout, яка працює через TIS (Text Input Source) API macOS. Тепер можна задавати ідентифікатори розкладок на кшталт com.apple.keylayout.ABC чи com.apple.keylayout.Ukrainian-PC.
3. Парсер JSON правил
Щоб користувач міг налаштувати, яка розкладка для якого додатку, я реалізував власний парсер JSON-файлу rules.json. Він читає конфігурацію правил у C, виділяє назви додатків та потрібні розкладки. Наприклад:

{
"rules": [
{"app": "kitty", "layout": "eng"},
{"app": "Telegram Desktop", "layout": "ua"},
{"app": "Google Chrome", "layout": "eng"}
]
}

Функція apply_rules_to_active_window перевіряє активний додаток і застосовує потрібну розкладку у реальному часі.

На даному етапі утиліта поки що в розробці, і готова лише підутиліта ADA (auto-detected-app). Вона вже може відслідковувати активний додаток та виводити debug-вивід із застосованими правилами розкладки.

Власна проблема з постійним переключенням розкладки перетворилась на окремий проєкт.

https://github.com/DenysSkobalo/macos-input-switcher
Зараз активно введеться розробка проєкту "MIS", і вже відбулося кілька важливих змін і покращень:

1. Повна інтеграція C та Objective-C
Тепер проєкт компілюється як єдиний бінарник, де C-логіка і Objective-C код (для macOS API) працюють разом без “костилів”. Тепер усі модулі, включно з відслідковуванням активного додатку і управлінням клавіатурою, компілюються через один Makefile і збираються у повноцінний .app.

2. Нова система правил
JSON-конфіг rules.json отримав оновлення: додав підтримку нових додатків і точних ідентифікаторів розкладок. Наприклад, тепер можна задати:

{
"rules": [
{"app": "kitty", "layout": "com.apple.keylayout.ABC"},
{"app": "Telegram", "layout": "com.apple.keylayout.Ukrainian-PC"},
{"app": "ChatGPT", "layout": "com.apple.keylayout.Ukrainian-PC"},
{"app": "Google Chrome", "layout": "com.apple.keylayout.ABC"}
]
}
1
3. Новий модуль layout_switcher
Реалізована централізована логіка зміни розкладки. Тепер не потрібно окремо викликати API для кожного додатку — функції layout_switcher_init та layout_switcher_free керують усім циклом переключень, економлячи ресурси та мінімізуючи затримки.

4. Відмовились від старого модуля auto-detected-app
Раніше я робив окремий агент, який тільки виводив debug-інформацію. Зараз він повністю інтегрований у головний бінарник, і відстеження активного додатку працює у фоновому режимі без додаткових процесів.

Результат: зараз утиліта вже збирається в готовий .app, автоматично підтягує правила з rules.json і змінює розкладку під час роботи з будь-яким додатком. Тестування показує, що переключення практично миттєве, а CPU навантаження мінімальне.

https://github.com/DenysSkobalo/macos-input-switcher/commit/57a66c3f9722924648c261f00abee2403d079240
Сьогодні день був так сказати проведений в резюме та LinkedIn. Але по закінченю, я загадав що у мене є ігровий ноутбук, який я вже не використовую. І в голову прийшла думка, а якщо я з нього спробую зробити сервер для своїх пет-проєктів. Ну і з цього почалось 4-годинне занурення як Sysadmin & DevOps.

Спочатку, я зробив загрузочну флешку з Ubuntu Server. Вставив в ноутбук, зніс до біса Windows (дратує Windows), встановив на свою машину Ubuntu Server Minimized, без GUI і лишнього сміття.
Далі, підключення до Wi-Fi. А це окрема проблема тому, що я живу у гуртожитку та немаю Ethernet кабелю. Хвилин 10-15, почитавши про netplan, написав конфіг для підключення до Wi-Fi і все, доступ отриманий. Після цього йшла Linux-рутина,
sh sudo apt update && sudo apt upgrade -y
, далі встановлення базових інструментів. З головного це nvim, я зрозумів, що я без нього як без рук, якщо йдеться про написання коду, конфігів. А потім я згадую, що якщо я буду не вдома а доступ до "сервера" треба буде отримати, я встановлюю та налаштовую OpenSSH. Одразу пересідаю за свій Macbook та підключаюсь до нього через ssh і продовжую налаштування "сервера". А да доречі, ще зробив таку структуру:

/srv/docker # for Docker container
/srv/projects # for my projects
/srv/volumes # for saved Docker volumes
1
Отже, далі в діло вступає DevOps engineering, встанволення базового так сказати для базових проєктів, це Docker. Налаштував, конфіг Docker'а, щодо директорій, щоб все було в одному місці. Думав k8s ще встановити, але у мене таких проєктів немає, щоб використовувати кластеризацію, тому я думаю, що у майбутньому встановлю, пограюсь з ним. Потім для Docker, налаштував інтерфейси та вільні порти. Також ще встановив docker-compose, щоб ну взагалі було пофеншую.

Сервер, посуті вже працює, але треба ж протестувати.

mkdir -p /srv/projects/myproject
, далі відкриваємо мій улюблений NVIM, і починаємо. Доречі я на Golang, вже не писав більше 2-х місяців, і щоб я писав 10хв, http server на GET запит використовуючи фреймворк це стидно, тому я думаю, що після двох проєктів на С, я повертаюсь до Golang. Отже я написав httpserver на одну GET ручку, де в response буде перше програмістське слово "Hello ....". Доречі на Golang я то не писав більше 2-х місяців а ось Dockerfile, docker-compose взагалі рік. У висновку думаю, погрішу сьогодні трохи, ChatGPT на базу. Отримую я і Dockerfile, і docker-compose. Піднімаю container, роблю локальний запит ніби працює, а тепер хочеться, щоб можна було запит робити не залежно чи в локальній мережі чи ні, я перевіряю публічний IP адрес, copy-paste + порт, enter, і ... НІ*УЯ.

Я нічого не отримую, запит просто зависає, я в логи до контейнера, там все нормально, я не розумію, що не так, ну не може бути, що десь в 15 рядках коду міг помилитись. Дивлюсь, та ніби все нормлально. Вирішую, якщо погрішив раз можна і другий, і до чата, пояснюю всю ситуацію від А до Я, а він каже що скоріш всього провайдер гуртожитку стоїть Firewall/ISP blocking. І я починаю далі думати, як вирішити питання, єдина робоча гіпотеза TUNNEL. Альтабаюсь до чату, щоб спитати, які є тунелі, бо я памятав тільки ngrok, а мені хотілось чогось нового спробувати, і я бачу що чат запропонував те саме що і я, одразу після повідомленння того, що скоріш всього є Firewall.
1
Я вибрав Cloudflare Tunnel, запригнув в доку, встановив CLI, думаю попрошу чата покращити docker-compose, щоб автоматично після ребута контейнера піднімав тунель. У висновку все вийшло, і тепер можна буде тестувати свої проєкти на власному сервері. Але єдине, що мене не влаштовує, що URL хаотичний а точніш domain , просто набір слів,но так як я не планую деплоїти щось серйозне, то безріниці.

На майбутнє планую спробувати, ще пдіняти на сервері БД, а потім вазгалі спробувати задеплоїти проєкт, де буде мікросервісна архітектура + RabbitMQ + DBs, і можливо як я згадував k8s. Ось так один вечір я побував Sysadmin + DevOps, та іноді один вечір з Linux дає більше, ніж тиждень туторіалів. Але у висновку цей вечір ще раз показав, що більшість знань приходить не з книжок, а з моменту, коли щось не працює, і ти змушений розбиратись, чому саме.
Сьогодні повернувся до розробки утиліти для MacOS. Подивився на свій парсер JSON та сказав "Що за це гавнокод, треба рефакторити", але посуті воно виконувало те що мені треба було, но якщо правила будуть маштабуватись то все може полетіти. І я прийняв рішення, не брати готову бібліотеку для парсинга JSON на С, а написати своє, ну коротше кажучи все як завжди в мене.

Але яка різниця ж була між тсарим "парсером" та новим паресром. Старий парсер, реалізовував парсинг "на пальцях" так сказати, тобто кожен масив/об’єкт шукали вручну {, }, [, ], ключі та значення. Потребував багато ручного виділення памяті і вільного звільнення для кожного ключа/значення. Також Код був крихкий, не перевіряв коректність JSON, та легко ламався на додаткових пробілах, комах чи змінах формату JSON. Фактично обробляв рядок як текст, а не як структурований JSON.
1
В свою чергу новий парсер використовував окремий структурований Parser, який працює з токенами (`TOKEN_STRING, TOKEN_COLON, TOKEN_LBRACE etc.`). Тобто розбиває JSON на токени: key, value, дужки, коми, двокрапки. Це дозволяє легше і надійніше опрацьовувати формат. Також присутні функції, які забезпечують контроль за синтаксисом, це praser_expect та parser_advance. Ще парсер, парсить масив та об’єкти окремо через parse_rule_array(&parser, cfg); , parse_rule_object(&parser, cfg);. Найголовніше для мене це те, що новий парсер мінімізує ризик витоків памяті та дублювання коду. Централізоване виділення strndup для key, value. І легше додавати нові ключі в JSON або змінювати структуру.

Новий парсер працює за таким планом:
1. Файл читається в память як рядок (тепер замість ручного сканування символів, весь JSON передається структуровано парсеру)
2. Ініціалізація парсера, встанволює початкову позицію у рядку, а також зчитує перший токен. Токени - це типізовані частини JSON.
3. Перевірка головного об’єкта, парсер очікує, що JSON починається з {. Якщо ні, то парсер видає помилку.
4. Читання ключів верхнього рівня, парсер перебирає ключі верхнього рівня у JSON. Для кожного ключа, зчитує його та перевіряє, чи це ключ "rules".
5. Парсинг масиву правил, якщо знайдено "rules", парсер далі очікує [ початок масиву правил. Потім перебираємо об’єкти правил, де для кожного об’єкта у масиві викликається parse_rule_object.
6. Парсинг окремого правила, знову парсер очіує {, потім ініціалізуємо змінні :

char *app_name = NULL;
char *layout = NULL;

Перебирає всі пари key-value у об’єкті, якщо токен це рядок це ключ ("app" або "layout"), потім `parser_advance` для переходу до двокрапки, зчитуємо значення після :, в залежності від ключа, присвоюємо значення app_name або layout. Після закінчення об’єкта }, виділяємо память у масиві cfg->rules та зберігаємо нове правило.
7. Завершення мсиву та JSON, після всіх об’єктів очікуємо ] (кінець масиву), потім } (кінець JSON), файл звільняється, структура RulesConfig готова до використання.

8. В результаті, в RulesConfig зберігається :

cfg->rule_count // кількість правил
cfg->rules[i].app_name // ім’я додатку
cfg->rules[i].layout // розкладка для цього додатку

Тепер можна викликати layout_switcher_init(cfg) і автоматично створювати таблицю відповідності додатків до клавіатурної розкладки.
Ось так потратив сьогодні 4 години на написання власного JSON Parser. Але також без тупих моментів сьогодні. Закінчив писати парсер, перекурив, тепер час перевіряти як працює моє творіння. Замінив парсер, комплюю бінарник, запускаю все працює, тільки для Google Chrome розкладка не змінюється, я думаю ну не може бути, що я десь помилився. Починаю дебажити, дивлюсь парсить все правильно, думаю може проблема в агенті layout_switcher, але я памятаю що до нового парсера все працювало, у чому тоді проблема. В правилах я памятаю, що поставив українську розкладку для Google Chrome, але вона не міняється, читаю далі код, перевіряю, дебажу. І не можу зрозуміти чому усі правила працюють а для Google Chrome ні.

Щоб ви розуміли, я передивився кожен файл, кожен рядок, але файл з правилами ні. Відкриваю, дивлюсь а там для Google Chrome, стоїть правило, що коли активний Google Chrome автоматично світчнути на англійську розкладку а не на українську як я думав, що я написав.

І після моєї необаності, все працювало правильно. Я зробив висновки сьогоднішньої роботи, це зрозуміти, що правильна структура та контроль синтаксису заощаджують час у майбутньому і спрощують масштабування. Також важливо перевіряти логіку правил і конфігурацій, перш ніж шукати помилки у коді, бо іноді «проблема» виявляється банальною у самому файлі правил.
😭1