Промпты для системного программиста. 27 готовых примеров для генерации

От NP_Article

ИИ-технолог

Обучение управлению ИИ с 0 до мастерского уровня

250+ уроков Начато наполнение Без инфоцыган и воды

Системное программирование – одна из тех областей, где нейросеть либо становится незаменимым помощником, либо выдает такую чушь, что хочется закрыть ноутбук и уйти в огород. Разница почти всегда в одном: в том, как сформулирован запрос. Промпты для системного программиста – это не просто "напиши мне код", это точная инструкция с контекстом, ограничениями и форматом результата.

В этой статье собраны 27 готовых примеров запросов для работы с нейросетью. Они охватывают реальные задачи: от отладки ядра и работы с памятью до написания драйверов и анализа производительности.

Что найдете внутри:

  • Промпты для работы с низкоуровневым кодом на C и ассемблере
  • Запросы для анализа утечек памяти и состояний гонки
  • Шаблоны для написания и отладки драйверов устройств
  • Примеры для работы с межпроцессным взаимодействием и синхронизацией
  • Запросы для профилирования и оптимизации системного кода
  • Шаблоны для документирования архитектурных решений

Каждый промпт – готовый к использованию шаблон. Скопировали, подставили свои данные, получили результат. Никакой теории ради теории.

27 промптов для системного программиста: готовые шаблоны для нейросети

1. Анализ утечки памяти в C-программе

Проблема:
Утечки памяти в системном коде обнаруживаются поздно – когда процесс уже съел всю доступную оперативную память и упал в самый неподходящий момент.

Решение:
Промпт заставляет нейросеть пройтись по коду как опытный аудитор: найти незакрытые выделения, указать строки и объяснить причину каждой утечки.

Текст промпта:

*****

Ты – [укажите роль, например, “опытный системный программист со специализацией в отладке памяти на C и C++”].

Проанализируй следующий фрагмент кода на предмет утечек памяти:

[вставьте код, например, “функция инициализации буфера с выделением через malloc и несколькими путями возврата”]

Контекст: [опишите контекст выполнения, например, “код работает в многопоточной среде, вызывается из обработчика прерываний”]

Твоя задача:

  1. Найди все места, где выделенная память не освобождается при всех путях выполнения функции.
  2. Для каждой найденной утечки укажи номер строки (или описание места), причину возникновения и последствия при длительной работе программы.
  3. Предложи исправленный вариант кода с комментариями на русском языке.

Формат ответа: сначала список найденных проблем с объяснением, затем исправленный код.
Ограничения: не меняй логику программы, только исправь управление памятью. Не используй умные указатели C++ – только ручное управление памятью в стиле C.
Тон: строго технический, без лирических отступлений.

*****

Почему это работает:
Явное требование рассматривать все пути выполнения (включая пути ошибок) заставляет нейросеть не ограничиваться "счастливым путем", где все освобождается корректно. Ограничение "только C, без C++" исключает нерелевантные советы.

2. Написание драйвера символьного устройства для Linux

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

Решение:
Промпт генерирует рабочий каркас драйвера с правильной регистрацией, операциями файла и корректной очисткой ресурсов при выгрузке модуля.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик драйверов для ядра Linux с опытом работы с подсистемой символьных устройств”].

Напиши каркас модуля ядра Linux для символьного устройства со следующими характеристиками:

Устройство: [опишите устройство, например, “виртуальное устройство для передачи данных между пространством пользователя и ядром через буфер фиксированного размера”] Версия ядра: [укажите версию, например, “Linux 5.15 LTS”] Операции: [перечислите операции, например, “open, release, read, write, ioctl для управления размером буфера”]

Контекст: [опишите контекст, например, “драйвер будет использоваться во встроенной системе, ресурсы ограничены, приоритет – минимальный размер кода”]

Структура ответа:

  1. Заголовочные файлы с объяснением назначения каждого.
  2. Объявление структур и глобальных переменных с комментариями.
  3. Реализация каждой операции с подробными комментариями на русском языке.
  4. Функции инициализации (init) и выгрузки (exit) модуля.
  5. Макросы MODULE_LICENSE, MODULE_AUTHOR, MODULE_DESCRIPTION.

Ограничения: использовать только стабильный API ядра, не использовать устаревшие функции (register_chrdev вместо cdev_init – не нужен), обеспечить корректное освобождение всех ресурсов в функции exit даже при частичной инициализации.
Тон: технический, комментарии объясняют "почему", а не "что".

*****

Почему это работает:
Требование "корректное освобождение даже при частичной инициализации" – это именно то, что начинающие авторы драйверов упускают и что приводит к панике ядра. Явное указание версии ядра исключает советы с устаревшим API.

3. Поиск состояния гонки в многопоточном коде

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

Решение:
Промпт проводит систематический анализ общих ресурсов и точек синхронизации, выдавая конкретные места с объяснением механизма возникновения гонки.

Текст промпта:

*****

Ты – [укажите роль, например, “специалист по многопоточному программированию и анализу параллельного выполнения кода на C/C++”].

Проанализируй следующий многопоточный код на наличие состояний гонки и проблем синхронизации:

[вставьте код, например, “реализация пула потоков с общей очередью задач и несколькими рабочими потоками”]

Контекст выполнения: [опишите контекст, например, “код выполняется на многоядерном процессоре x86-64, компилятор GCC 12 с оптимизацией O2”]

Выполни анализ в следующем порядке:

  1. Определи все общие ресурсы (переменные, структуры данных, файловые дескрипторы).
  2. Для каждого общего ресурса проверь: есть ли защита мьютексом/семафором, правильно ли расставлены захват и освобождение блокировки, нет ли возможности взаимной блокировки.
  3. Проверь атомарность операций: какие операции выглядят атомарными, но таковыми не являются на уровне процессора.
  4. Укажи конкретные сценарии, при которых гонка проявится, с описанием последовательности событий.

Формат: таблица найденных проблем (ресурс – тип проблемы – сценарий – последствие), затем исправленный код.
Ограничения: не предлагай переписать все с нуля, работай с существующей структурой кода.

*****

Почему это работает:
Требование описать конкретный сценарий проявления гонки (последовательность событий) переводит анализ из абстрактного в воспроизводимый – именно это нужно для написания теста, который поймает проблему.

4. Оптимизация горячего пути в критической функции

Проблема:
Профилировщик показывает, что функция занимает 40% времени выполнения, но непонятно, что именно тормозит – алгоритм, промахи кэша или ветвления.

Решение:
Промпт проводит многоуровневый анализ производительности: от алгоритмической сложности до предсказания ветвлений и локальности данных.

Текст промпта:

*****

Ты – [укажите роль, например, “эксперт по низкоуровневой оптимизации кода для архитектуры x86-64”].

Оптимизируй следующую функцию, которая является узким местом по результатам профилирования:

[вставьте код функции, например, “функция обработки пакетов, вызываемая 10 миллионов раз в секунду”]

Данные профилирования: [опишите данные, например, “40% времени в этой функции, высокий процент промахов кэша L1, частые неверные предсказания ветвлений”] Целевая архитектура: [укажите архитектуру, например, “Intel Core i7 12-го поколения, кэш L1 32 КБ, L2 256 КБ”]

Проведи анализ по уровням:

  1. Алгоритмический уровень: можно ли снизить сложность или количество итераций.
  2. Уровень структур данных: оптимальна ли компоновка данных для кэша (выравнивание, структура vs массив структур).
  3. Уровень ветвлений: какие условия предсказуемы, какие нет, как их реструктурировать.
  4. Уровень инструкций: где применить векторизацию, встроенные функции процессора или подсказки компилятору.

Для каждой оптимизации укажи ожидаемый эффект и потенциальные компромиссы (читаемость, переносимость).
Ограничения: сохранить корректность результата, не использовать ассемблерные вставки без крайней необходимости.

*****

Почему это работает:
Многоуровневый подход к анализу позволяет не упустить причину на каждом из уровней абстракции – часто разработчики ищут проблему на уровне инструкций, когда она находится на алгоритмическом уровне и наоборот.

5. Разработка протокола межпроцессного взаимодействия

Проблема:
Выбор механизма межпроцессного взаимодействия без четкого понимания компромиссов приводит к архитектурным решениям, которые потом переписываются целиком.

Решение:
Промпт помогает выбрать и спроектировать механизм взаимодействия с учетом конкретных требований к задержке, пропускной способности и надежности.

Текст промпта:

*****

Ты – [укажите роль, например, “архитектор системного программного обеспечения с опытом проектирования высоконагруженных систем на Linux”].

Помоги спроектировать механизм межпроцессного взаимодействия для следующей задачи:

Описание системы: [опишите систему, например, “сервис мониторинга собирает метрики от 50 агентов каждые 100 миллисекунд и передает в центральный агрегатор”] Требования к производительности: [укажите требования, например, “задержка не более 1 миллисекунды, пропускная способность 100 МБ/с, данные не критичны к потере отдельных пакетов”] Ограничения среды: [укажите ограничения, например, “все процессы на одном хосте, Linux 5.15, нельзя использовать внешние библиотеки”]

Структура ответа:

  1. Сравнение подходящих механизмов (разделяемая память, очередь сообщений POSIX, доменные сокеты Unix, именованные каналы) по критериям: задержка, пропускная способность, сложность реализации, надежность.
  2. Обоснованная рекомендация с учетом указанных требований.
  3. Схема протокола: формат сообщений, синхронизация, обработка ошибок.
  4. Минимальный рабочий пример реализации на C.

Ограничения: объяснять компромиссы, а не просто называть "лучший вариант".

*****

Почему это работает:
Требование объяснять компромиссы, а не просто рекомендовать "лучший вариант", дает понимание, а не слепое следование совету – это критично при смене требований проекта.

6. Написание и отладка кода на ассемблере x86-64

Проблема:
Ассемблерный код сложно читать, еще сложнее отлаживать, а нейросеть без четкого контекста генерирует синтаксически правильный, но семантически сломанный код.

Решение:
Промпт с явным указанием синтаксиса, соглашения о вызовах и целевой задачи дает корректный ассемблерный код с подробными пояснениями каждой инструкции.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик низкоуровневого кода с глубоким знанием архитектуры x86-64 и соглашений вызовов System V AMD64 ABI”].

Напиши функцию на ассемблере x86-64 для следующей задачи:

Задача: [опишите задачу, например, “поиск первого нулевого байта в буфере памяти с использованием векторных инструкций SSE2 для ускорения”] Синтаксис: [укажите синтаксис, например, “AT&T синтаксис для GCC inline assembler” или “Intel синтаксис для NASM”] Соглашение о вызовах: [укажите соглашение, например, “System V AMD64: первый аргумент в rdi, второй в rsi, результат в rax”]

Требования:

  1. Каждая инструкция должна иметь комментарий на русском языке, объясняющий что и почему делается.
  2. Явно обозначь сохранение и восстановление регистров согласно соглашению о вызовах.
  3. Обработай граничные случаи: пустой буфер, буфер без нулевого байта.
  4. Приведи эквивалентный код на C для понимания логики.

Ограничения: не использовать инструкции новее SSE2 без явного указания, обеспечить корректное выравнивание стека.

*****

Почему это работает:
Явное требование приводить эквивалент на C позволяет немедленно проверить логику и убедиться, что ассемблерный код делает именно то, что задумано.

7. Анализ дампа памяти после аварийного завершения

Проблема:
Дамп памяти без правильного плана анализа превращается в часы бесплодного копания в шестнадцатеричных значениях вместо быстрого нахождения причины сбоя.

Решение:
Промпт создает структурированный план анализа с конкретными командами отладчика и объяснением того, что искать на каждом шаге.

Текст промпта:

*****

Ты – [укажите роль, например, “специалист по постмортем-анализу системных сбоев с опытом работы с GDB и анализа дампов ядра Linux”].

Помоги проанализировать аварийное завершение программы. Имеющиеся данные:

Сигнал завершения: [укажите сигнал, например, “SIGSEGV – обращение по недопустимому адресу”] Трассировка стека: [вставьте трассировку, например, “вывод bt в GDB с несколькими кадрами”] Контекст программы: [опишите контекст, например, “многопоточный сервер обработки запросов, сбой происходит под нагрузкой примерно через 2 часа работы”] Последние изменения в коде: [опишите изменения, например, “добавлен новый обработчик запросов три дня назад”]

Выполни анализ по плану:

  1. Интерпретируй трассировку стека: что делала программа в момент сбоя, какой поток, какая функция.
  2. Предложи гипотезы о причине с ранжированием по вероятности.
  3. Для каждой гипотезы дай конкретные команды GDB для проверки с объяснением что ищем.
  4. Укажи, какую дополнительную информацию нужно собрать при следующем воспроизведении.

Формат: структурированный план действий, команды в блоках кода, пояснения на русском.

*****

Почему это работает:
Ранжирование гипотез по вероятности направляет анализ от наиболее вероятных причин к редким, что экономит время при ограниченном количестве воспроизведений сбоя.

8. Проектирование системы управления памятью (аллокатор)

Проблема:
Стандартный аллокатор не всегда подходит для специфических паттернов выделения памяти в системном коде – это приводит к фрагментации и неприемлемым задержкам.

Решение:
Промпт помогает спроектировать специализированный аллокатор с учетом конкретных паттернов использования и требований к производительности.

Текст промпта:

*****

Ты – [укажите роль, например, “системный программист с опытом реализации специализированных аллокаторов памяти для встроенных систем и систем реального времени”].

Спроектируй специализированный аллокатор памяти для следующих условий:

Паттерн использования: [опишите паттерн, например, “выделение объектов одного размера (512 байт) в большом количестве с коротким временем жизни, частые выделение и освобождение”] Требования: [укажите требования, например, “детерминированное время выделения O(1), минимальная фрагментация, работа без системных вызовов после инициализации”] Среда: [опишите среду, например, “встроенная система, 4 МБ доступной памяти, однопоточная среда”]

Структура ответа:

  1. Выбор подходящего типа аллокатора (пул, стек, кольцевой буфер, битовая карта) с обоснованием.
  2. Схема организации памяти с объяснением каждого поля заголовка блока.
  3. Реализация основных функций: инициализация, выделение, освобождение.
  4. Анализ фрагментации и стратегия ее минимизации.
  5. Тест корректности и измерение производительности.

Ограничения: реализация на C, без использования стандартного malloc/free внутри аллокатора.

*****

Почему это работает:
Явное требование детерминированного времени выполнения O(1) сразу отсекает неподходящие алгоритмы и фокусирует нейросеть на правильном классе решений.

9. Настройка и анализ производительности с помощью системных счетчиков

Проблема:
Счетчики производительности процессора – мощный инструмент, но без понимания, что именно измерять и как интерпретировать результаты, они остаются набором непонятных цифр.

Решение:
Промпт создает конкретный план измерений с командами, объяснением метрик и интерпретацией типичных результатов для заданной задачи.

Текст промпта:

*****

Ты – [укажите роль, например, “специалист по анализу производительности системного программного обеспечения с опытом работы с perf и аппаратными счетчиками производительности”].

Помоги настроить и интерпретировать измерения производительности для следующей задачи:

Программа: [опишите программу, например, “обработчик сетевых пакетов на C, работающий в режиме ядра”] Наблюдаемая проблема: [опишите проблему, например, “пропускная способность на 30% ниже теоретической, загрузка CPU высокая, но пакеты обрабатываются медленно”] Оборудование: [укажите оборудование, например, “Intel Xeon E5-2680 v4, Linux 5.15”]

Создай план измерений:

  1. Какие счетчики производительности измерять (промахи кэша, неверные предсказания ветвлений, остановки конвейера) и почему именно эти.
  2. Конкретные команды perf для каждого измерения.
  3. Пороговые значения: что считать нормой, что – проблемой для данного типа нагрузки.
  4. Интерпретация возможных результатов: если высокий показатель X, то проблема в Y, решение Z.
  5. Последовательность действий по результатам измерений.

Формат: пошаговый план с командами и таблицей интерпретации метрик.
Ограничения: только инструменты, входящие в стандартный Linux (perf, ftrace, /proc), без внешних зависимостей.

*****

Почему это работает:
Требование указать пороговые значения и интерпретацию "если X, то Y" превращает набор цифр в actionable-план – это именно то, чего не хватает большинству руководств по профилированию.

10. Реализация механизма синхронизации без блокировок

Проблема:
Структуры данных без блокировок кажутся элегантным решением, но неправильная реализация создает тонкие ошибки, которые проявляются только на определенных процессорах или при определенной нагрузке.

Решение:
Промпт создает корректную реализацию с явным анализом модели памяти и обоснованием каждого барьера памяти.

Текст промпта:

*****

Ты – [укажите роль, например, “специалист по параллельному программированию с глубоким знанием моделей памяти процессоров и алгоритмов без блокировок”].

Реализуй следующую структуру данных без использования мьютексов:

Структура: [опишите структуру, например, “очередь MPSC (несколько производителей, один потребитель) для передачи указателей между потоками”] Требования: [укажите требования, например, “операции push и pop должны быть без блокировок, порядок FIFO, максимальный размер 1024 элемента”] Целевая платформа: [укажите платформу, например, “x86-64, компилятор GCC, стандарт C11 с поддержкой атомарных операций”]

Структура ответа:

  1. Анализ требований к порядку памяти: какие операции требуют барьеров памяти и почему.
  2. Реализация с явными атомарными операциями (_Atomic в C11 или _atomic* в GCC).
  3. Для каждого барьера памяти (memory_order_*) объясни: почему именно этот порядок, что произойдет при более слабом порядке.
  4. Тест корректности: как проверить правильность реализации под нагрузкой.
  5. Производительность: сравнение с эквивалентной реализацией на мьютексах.

Ограничения: не использовать внешние библиотеки, только стандартный C11 или GCC-специфичные расширения.

*****

Почему это работает:
Требование объяснить, что произойдет при более слабом порядке памяти, заставляет нейросеть обосновать каждое решение, а не просто написать код с произвольными барьерами памяти.

11. Разработка системного вызова для ядра Linux

Проблема:
Добавление системного вызова в ядро требует понимания множества деталей: от объявления до обработки аргументов из пространства пользователя – и одна ошибка открывает уязвимость.

Решение:
Промпт создает полный шаблон системного вызова с безопасной обработкой пользовательских данных и корректной интеграцией в таблицу системных вызовов.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик ядра Linux с опытом добавления системных вызовов и обеспечения их безопасности”].

Помоги реализовать новый системный вызов для ядра Linux:

Назначение системного вызова: [опишите назначение, например, “получение статистики использования памяти конкретным процессом с расширенными метриками, недоступными через /proc”] Аргументы: [опишите аргументы, например, “PID процесса, указатель на структуру для результата, флаги выбора метрик”] Версия ядра: [укажите версию, например, “Linux 6.1”]

Реализация должна включать:

  1. Объявление системного вызова через макрос SYSCALL_DEFINE с правильным количеством аргументов.
  2. Безопасное копирование данных из пространства пользователя (copy_from_user) и в него (copy_to_user) с проверкой всех возможных ошибок.
  3. Проверки привилегий и валидация входных данных.
  4. Регистрацию в таблице системных вызовов (с пояснением для архитектуры x86-64).
  5. Пример вызова из пространства пользователя через syscall().
  6. Список типичных уязвимостей при реализации системных вызовов и как их избежать.

Ограничения: все взаимодействия с пользовательским пространством только через безопасные функции ядра, никакого прямого разыменования пользовательских указателей.

*****

Почему это работает:
Явный запрос на список уязвимостей при реализации системных вызовов – это то, что отличает промпт для системного программиста от запроса новичка: безопасность закладывается с самого начала, а не добавляется потом.

12. Анализ и оптимизация работы с кэшем процессора

Проблема:
Промахи кэша могут замедлить программу в 10–100 раз по сравнению с теоретическим максимумом, но причина часто неочевидна без понимания того, как именно данные располагаются в памяти.

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

Текст промпта:

*****

Ты – [укажите роль, например, “специалист по оптимизации производительности с глубоким пониманием иерархии памяти и принципов работы кэша процессора”].

Проанализируй следующий код на предмет проблем с эффективностью работы с кэшем:

[вставьте код, например, “цикл обработки массива структур с несколькими полями разного размера”]

Характеристики кэша целевого процессора: [укажите характеристики, например, “кэш-линия 64 байта, L1 32 КБ 8-канальный, L2 256 КБ, L3 8 МБ”] Паттерн доступа: [опишите паттерн, например, “последовательный проход по массиву из 10 миллионов элементов, обращение только к двум полям структуры из восьми”]

Анализ должен включать:

  1. Вычисление текущей эффективности использования кэш-линий: сколько полезных байт из каждой загруженной кэш-линии.
  2. Диаграмму размещения структуры в памяти и кэш-линиях.
  3. Конкретные преобразования: разделение структуры (AoS → SoA), выравнивание, предвыборку данных.
  4. Оценку ожидаемого прироста производительности для каждого преобразования.
  5. Компромиссы: что ухудшится при каждом преобразовании.

Формат: текстовый анализ с ASCII-диаграммами размещения данных в памяти.

*****

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

13. Написание юнит-тестов для системного кода

Проблема:
Тестирование системного кода сложнее прикладного: нужно изолировать зависимости от оборудования, эмулировать условия ошибок и тестировать граничные состояния, которые в реальности воспроизвести трудно.

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

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик с опытом тестирования системного кода на C с использованием фреймворков проверки и техник подстановки зависимостей”].

Напиши набор тестов для следующего системного кода:

Код для тестирования: [вставьте код или опишите функцию, например, “функция чтения из символьного устройства с обработкой ошибок ввода-вывода и таймаутов”] Зависимости: [перечислите зависимости, например, “системные вызовы read(), select(), открытый файловый дескриптор устройства”] Фреймворк: [укажите фреймворк, например, “CMocka” или “Unity для встроенных систем”]

Тесты должны покрывать:

  1. Нормальный случай: успешное чтение данных.
  2. Граничные условия: пустой буфер, буфер ровно нужного размера, переполнение.
  3. Сценарии ошибок: устройство недоступно, прерывание сигналом (EINTR), таймаут.
  4. Состояния гонки: параллельные вызовы при наличии общего состояния.

Для каждого теста:
– Объясни что именно проверяется и почему это важно.
– Покажи как эмулировать поведение зависимостей (системных вызовов) без реального оборудования.
– Укажи что считается успехом теста.

Ограничения: тесты должны выполняться без привилегий суперпользователя и без реального оборудования.

*****

Почему это работает:
Требование тестировать прерывание сигналом EINTR – это именно тот граничный случай, который обычно пропускается и потом вызывает трудновоспроизводимые сбои в production-системах.

14. Проектирование встроенной файловой системы

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

Решение:
Промпт создает структурированный анализ требований и проектное решение с обоснованием каждого архитектурного выбора.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик встроенных систем с опытом проектирования и адаптации файловых систем для устройств с ограниченными ресурсами”].

Помоги спроектировать файловую систему для встроенного устройства:

Хранилище: [опишите хранилище, например, “NAND Flash 512 МБ, размер страницы 4 КБ, размер блока стирания 256 КБ, ресурс 100 000 циклов перезаписи блока”] Паттерн использования: [опишите паттерн, например, “частая запись небольших конфигурационных файлов до 4 КБ, редкое чтение, критична целостность данных при внезапном отключении питания”] Ограничения ресурсов: [укажите ограничения, например, “доступно 64 КБ ОЗУ для файловой системы, процессор ARM Cortex-M4”]

Анализ должен включать:

  1. Сравнение подходящих файловых систем (JFFS2, YAFFS2, LittleFS, SPIFFS) по критериям: расход ОЗУ, стойкость к отключению питания, выравнивание износа, сложность интеграции.
  2. Рекомендацию с обоснованием.
  3. Ключевые параметры конфигурации выбранной файловой системы с объяснением их влияния.
  4. Стратегию тестирования: как проверить стойкость к внезапному отключению питания.

Ограничения: не рекомендовать файловые системы, требующие аппаратного MMU, если он не указан в требованиях.

*****

Почему это работает:
Явное требование учитывать стойкость к внезапному отключению питания как критерий сравнения – это то, что отличает реальный выбор от теоретического: именно этот критерий часто определяет финальное решение во встроенных системах.

15. Реализация планировщика задач для операционной системы реального времени

Проблема:
Планировщик реального времени – это не просто "кто следующий выполняется", а сложная система с гарантиями по времени отклика, которые нарушить очень легко, а восстановить – крайне сложно.

Решение:
Промпт создает реализацию планировщика с явным анализом наихудшего времени выполнения и проверкой выполнимости расписания.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик систем реального времени с опытом реализации планировщиков задач для операционных систем реального времени”].

Реализуй планировщик задач для следующих условий:

Тип планирования: [укажите тип, например, “вытесняющий планировщик с фиксированными приоритетами, алгоритм Rate-Monotonic”] Задачи: [опишите задачи, например, “5 периодических задач с периодами от 1 до 100 миллисекунд и временем выполнения от 0.1 до 10 миллисекунд”] Платформа: [укажите платформу, например, “микроконтроллер ARM Cortex-M3, системный таймер SysTick, без аппаратной поддержки виртуальной памяти”]

Реализация должна включать:

  1. Проверку выполнимости расписания (тест загрузки процессора для Rate-Monotonic).
  2. Структуры данных для очереди задач и блоков управления задачами.
  3. Реализацию переключения контекста: сохранение и восстановление регистров.
  4. Обработчик таймера для вытеснения задач.
  5. Анализ наихудшего времени отклика для каждой задачи.

Ограничения: реализация на C, переключение контекста через обработчик прерывания PendSV, без использования динамического выделения памяти в планировщике.

*****

Почему это работает:
Требование провести проверку выполнимости расписания до реализации – это именно тот шаг, который пропускают при разработке и потом обнаруживают, что система не может выполнить все задачи в срок уже после написания тысяч строк кода.

16. Написание обработчика прерываний

Проблема:
Обработчик прерываний с ошибками – это не просто баг, это потенциальное зависание всей системы, и отлаживать его в условиях запрета на большинство стандартных операций крайне сложно.

Решение:
Промпт создает корректный обработчик прерываний с явным соблюдением всех ограничений контекста прерывания и правильным разделением работы между обработчиком и основным потоком.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик встроенных систем с опытом написания обработчиков прерываний для микроконтроллеров и ядра Linux”].

Напиши обработчик прерывания для следующей задачи:

Источник прерывания: [опишите источник, например, “прерывание от UART при получении байта данных, частота до 115200 бод”] Платформа: [укажите платформу, например, “микроконтроллер STM32F4, Cortex-M4, FreeRTOS”] Требования: [укажите требования, например, “минимальное время в обработчике, передача данных в основной поток через кольцевой буфер без блокировок”]

Реализация должна включать:

  1. Сам обработчик прерывания с атрибутами компилятора для правильного размещения в векторной таблице.
  2. Объяснение: что разрешено и запрещено делать в контексте прерывания (какие функции ОС можно вызывать).
  3. Механизм передачи данных в основной поток (кольцевой буфер с атомарными операциями).
  4. Обработку ошибок: переполнение буфера, ошибки UART.
  5. Измерение времени выполнения обработчика и обеспечение его соответствия требованиям.

Ограничения: в самом обработчике прерывания не использовать функции с блокировками, динамическое выделение памяти или длительные вычисления.

*****

Почему это работает:
Явное требование объяснить, что разрешено и запрещено в контексте прерывания, формирует правильное понимание ограничений, а не просто выдает шаблон кода без понимания почему он именно такой.

17. Реализация виртуальной памяти и управления страницами

Проблема:
Работа с таблицами страниц и механизмами виртуальной памяти требует точного понимания аппаратных структур, и одна ошибка в управлении страницами может привести к трудно воспроизводимым повреждениям памяти.

Решение:
Промпт создает реализацию с явным объяснением каждого уровня таблицы страниц и корректной обработкой исключений страничного нарушения.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик операционных систем с опытом реализации подсистем управления виртуальной памятью”].

Реализуй базовую подсистему управления страницами памяти:

Архитектура: [укажите архитектуру, например, “x86-64, четырехуровневые таблицы страниц (PML4, PDPT, PD, PT), размер страницы 4 КБ”] Задача: [опишите задачу, например, “реализация для учебной операционной системы: отображение физической памяти на виртуальную, обработка страничных нарушений”] Объем физической памяти: [укажите объем, например, “64 МБ, карта памяти получена от загрузчика”]

Реализация должна включать:

  1. Структуры данных для каждого уровня таблицы страниц с описанием каждого бита флагов.
  2. Функции создания отображения (map_page) и его удаления (unmap_page).
  3. Обход таблицы страниц для трансляции виртуального адреса в физический.
  4. Обработчик исключения страничного нарушения (#PF) с разбором кода ошибки.
  5. Простой физический аллокатор страниц (битовая карта свободных страниц).

Для каждой функции объясни: почему именно такой порядок операций, какие флаги TLB нужно сбрасывать и когда.
Ограничения: реализация на C с минимальными ассемблерными вставками только там, где без них невозможно.

*****

Почему это работает:
Требование объяснять порядок операций и необходимость сброса буфера трансляции адресов – это именно те детали, которые отсутствуют в большинстве учебных примеров и которые являются источником трудноуловимых ошибок.

18. Создание инструмента трассировки системных вызовов

Проблема:
Понять, что именно делает процесс в системе, без инструмента трассировки – это как чинить машину с завязанными глазами: теоретически возможно, но крайне неэффективно.

Решение:
Промпт создает инструмент мониторинга системных вызовов с фильтрацией, форматированием вывода и минимальным влиянием на производительность наблюдаемого процесса.

Текст промпта:

*****

Ты – [укажите роль, например, “системный программист с опытом разработки инструментов трассировки и мониторинга на базе механизмов ядра Linux”].

Создай инструмент трассировки системных вызовов:

Механизм: [укажите механизм, например, “ptrace для трассировки пользовательского процесса” или “eBPF для мониторинга с минимальными накладными расходами”] Требования: [укажите требования, например, “перехват и вывод системных вызовов с аргументами и возвращаемыми значениями, фильтрация по имени системного вызова”] Целевая среда: [укажите среду, например, “Linux 5.15, трассировка произвольного процесса по его PID”]

Реализация должна включать:

  1. Присоединение к процессу и перехват системных вызовов.
  2. Декодирование аргументов: числовые значения, строки из пространства пользователя, флаги (с расшифровкой битовых масок).
  3. Форматированный вывод: имя вызова, аргументы, возвращаемое значение, время выполнения.
  4. Фильтрацию по имени системного вызова или возвращаемому значению (только ошибки).
  5. Корректное отсоединение от процесса при завершении трассировщика.

Объясни: как работает выбранный механизм трассировки, каковы его ограничения и накладные расходы по сравнению с альтернативами.
Ограничения: реализация на C, без использования внешних библиотек трассировки.

*****

Почему это работает:
Требование декодировать битовые маски флагов в человекочитаемый вид – это то, что делает разницу между "видеть числа" и "понимать что происходит" при анализе поведения системы.

19. Оптимизация сетевого стека для высоконагруженной системы

Проблема:
Стандартные настройки сетевого стека Linux ориентированы на универсальность, а не на максимальную производительность, и без целенаправленной настройки система не использует и половины возможностей оборудования.

Решение:
Промпт создает конкретный план настройки с параметрами, объяснением их влияния и измеримыми результатами для заданного типа нагрузки.

Текст промпта:

*****

Ты – [укажите роль, например, “специалист по высоконагруженным сетевым системам с опытом оптимизации сетевого стека Linux для обработки миллионов пакетов в секунду”].

Разработай план оптимизации сетевого стека для следующей задачи:

Тип нагрузки: [опишите нагрузку, например, “обработка UDP-пакетов малого размера (64–256 байт) с интенсивностью 5 миллионов пакетов в секунду”] Оборудование: [опишите оборудование, например, “сетевая карта Intel X710 10 Гбит/с, сервер с 32 ядрами NUMA, Linux 5.15”] Текущая проблема: [опишите проблему, например, “потери пакетов при пиковой нагрузке, высокая задержка обработки”]

План оптимизации должен охватывать:

  1. Настройки ядра (параметры sysctl): размеры буферов сокетов, параметры очередей, настройки прерываний – с объяснением каждого параметра.
  2. Привязку прерываний сетевой карты к ядрам процессора с учетом топологии NUMA.
  3. Настройку многоочередного режима сетевой карты (RSS/RPS/RFS).
  4. Оценку применимости технологии обхода ядра (DPDK) для данной задачи.
  5. Методологию измерения результатов: какие метрики снимать до и после каждого изменения.

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

*****

Почему это работает:
Требование начинать с изменений без перекомпиляции ядра задает правильный порядок оптимизации: сначала "бесплатные" улучшения, потом более сложные – это экономит время и позволяет измерить вклад каждого изменения отдельно.

20. Реализация безопасного парсера бинарного протокола

Проблема:
Парсеры бинарных протоколов – традиционный источник уязвимостей: переполнение буфера, выход за границы массива, целочисленное переполнение при вычислении размеров – все это легко пропустить при написании.

Решение:
Промпт создает парсер с систематической проверкой всех входных данных и явным анализом потенциальных уязвимостей.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик безопасного системного кода с опытом написания парсеров бинарных протоколов и анализа уязвимостей”].

Реализуй безопасный парсер для следующего бинарного протокола:

Описание протокола: [опишите протокол, например, “протокол с заголовком фиксированного размера (тип сообщения 2 байта, длина данных 4 байта) и полезной нагрузкой переменного размера до 64 КБ”] Источник данных: [опишите источник, например, “сетевой сокет, данные приходят от внешних клиентов, считаются потенциально враждебными”] Платформа: [укажите платформу, например, “Linux, 64-битная, компилятор GCC с включенными санитайзерами”]

Реализация должна включать:

  1. Проверку каждого поля: диапазон значений, корректность размеров, соответствие типу сообщения.
  2. Защиту от целочисленного переполнения при вычислении размеров буферов.
  3. Защиту от чтения за пределами буфера при разборе переменных полей.
  4. Явное указание и обработку всех состояний ошибок с информативными кодами ошибок.
  5. Анализ: перечисли все места, где мог бы быть баг безопасности, и объясни как они закрыты.

Ограничения: не использовать небезопасные функции (strcpy, sprintf без ограничения длины), все индексы и размеры проверять перед использованием.

*****

Почему это работает:
Требование перечислить все потенциально уязвимые места и объяснить как они закрыты – это метод "доказательства безопасности", который переводит написание кода из интуитивного в систематическое.

21. Разработка системы логирования для ядра или встроенной системы

Проблема:
Логирование в контексте ядра или встроенной системы – это не просто fprintf, а сложная задача с ограничениями на выделение памяти, доступные функции и объем хранилища.

Решение:
Промпт создает систему логирования с кольцевым буфером, уровнями детализации и механизмом вывода без блокирующих операций.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик встроенных систем с опытом реализации систем диагностики и логирования для ресурсоограниченных платформ”].

Реализуй систему логирования для следующих условий:

Среда: [опишите среду, например, “модуль ядра Linux” или “встроенная система на ARM Cortex-M без операционной системы”] Ограничения: [укажите ограничения, например, “нельзя использовать динамическое выделение памяти, нельзя блокировать выполнение, объем буфера логов не более 16 КБ”] Требования: [укажите требования, например, “уровни детализации (ошибка, предупреждение, информация, отладка), временные метки с точностью до миллисекунды, атомарность записи”]

Реализация должна включать:

  1. Кольцевой буфер фиксированного размера с атомарными операциями записи.
  2. Форматирование сообщений без использования malloc (статические буферы или форматирование на месте).
  3. Механизм вывода: как читать буфер из пространства пользователя или через последовательный порт.
  4. Защиту от переполнения: стратегия при заполненном буфере (перезапись старых или отбрасывание новых).
  5. Макросы для удобного использования с автоматической подстановкой имени файла и номера строки.

Ограничения: реализация должна быть безопасна для вызова из контекста прерывания.

*****

Почему это работает:
Требование безопасности для вызова из контекста прерывания – это ключевое ограничение, которое определяет всю архитектуру системы логирования и которое легко упустить при проектировании.

22. Анализ и устранение взаимной блокировки

Проблема:
Взаимная блокировка в системном коде может заморозить не только отдельный поток, но и всю систему – а воспроизвести ее в отладчике часто невозможно из-за нестабильности временных условий.

Решение:
Промпт систематически анализирует граф зависимостей блокировок, находит циклы и предлагает реструктуризацию с сохранением корректности.

Текст промпта:

*****

Ты – [укажите роль, например, “специалист по отладке многопоточных систем с опытом анализа взаимных блокировок и реструктуризации кода синхронизации”].

Проанализируй следующий код на наличие потенциальных взаимных блокировок:

[вставьте код, например, “два потока, каждый из которых захватывает два мьютекса в разном порядке”]

Контекст: [опишите контекст, например, “серверное приложение, взаимная блокировка проявляется под нагрузкой примерно раз в несколько часов”]

Выполни анализ:

  1. Построй граф зависимостей блокировок: какой поток владеет каким мьютексом и ожидает какого.
  2. Найди все циклы в графе зависимостей (потенциальные взаимные блокировки).
  3. Для каждого найденного цикла опиши точную последовательность событий, приводящую к блокировке.
  4. Предложи варианты устранения с анализом компромиссов:
    – Упорядочивание захвата мьютексов
    – Использование trylock с повторной попыткой
    – Реструктуризация кода для устранения необходимости в нескольких блокировках
  5. Покажи исправленный код для рекомендованного варианта.

Ограничения: не предлагать глобальный мьютекс как решение – это устраняет симптом, но убивает параллелизм.

*****

Почему это работает:
Явный запрет предлагать глобальный мьютекс как решение отсекает самый распространенный "легкий" выход, который действительно решает проблему взаимной блокировки, но создает новую – последовательное выполнение там, где должен быть параллелизм.

23. Написание скрипта автоматической сборки и тестирования системного кода

Проблема:
Ручная сборка системного кода с разными конфигурациями компилятора, флагами санитайзеров и запуском тестов – это монотонная работа, которая пропускается при спешке именно тогда, когда нужна больше всего.

Решение:
Промпт создает автоматизированный сценарий сборки с несколькими конфигурациями, запуском тестов и понятным отчетом о результатах.

Текст промпта:

*****

Ты – [укажите роль, например, “инженер по автоматизации сборки системного программного обеспечения с опытом настройки конвейеров сборки для C/C++ проектов”].

Создай скрипт автоматической сборки и тестирования для следующего проекта:

Проект: [опишите проект, например, “модуль ядра Linux и пользовательская библиотека для работы с ним, исходный код в нескольких директориях”] Конфигурации сборки: [перечислите конфигурации, например, “отладочная (без оптимизации, с санитайзерами адресов и неопределенного поведения), релизная (O2, LTO), для встроенной платформы (кросс-компиляция arm-linux-gnueabihf)”] Тесты: [опишите тесты, например, “юнит-тесты через CMocka, статический анализ через cppcheck и clang-tidy, проверка утечек через Valgrind”]

Скрипт должен:

  1. Выполнять сборку для каждой конфигурации независимо.
  2. Запускать соответствующий набор тестов для каждой конфигурации.
  3. Собирать результаты и формировать итоговый отчет: что прошло, что упало, с указанием файла и строки.
  4. Возвращать ненулевой код завершения при любом сбое (для интеграции в автоматизированные системы).
  5. Поддерживать параметр для сборки только конкретной конфигурации.

Язык скрипта: [укажите язык, например, “Bash” или “GNU Make с дополнительными сценариями Bash”] Ограничения: скрипт должен работать без дополнительных инструментов кроме указанных, подробные комментарии на русском языке.

*****

Почему это работает:
Требование возвращать ненулевой код завершения при любом сбое – это маленькая деталь, которая определяет, можно ли интегрировать скрипт в автоматизированную систему сборки или он будет всегда "успешно завершаться" даже при ошибках.

24. Проектирование API системной библиотеки

Проблема:
Плохо спроектированный API системной библиотеки – это долгосрочная проблема: его используют другие разработчики, изменить обратно несовместимым образом сложно, а последствия ошибок проектирования ощущаются годами.

Решение:
Промпт создает продуманный API с явным анализом удобства использования, обработки ошибок и обратной совместимости.

Текст промпта:

*****

Ты – [укажите роль, например, “архитектор системных библиотек с опытом проектирования публичных API для системного программного обеспечения на C”].

Спроектируй API для следующей системной библиотеки:

Назначение библиотеки: [опишите назначение, например, “библиотека для работы с разделяемой памятью: создание, отображение, синхронизация доступа”] Целевые пользователи: [опишите пользователей, например, “разработчики системного ПО на C, опыт работы с POSIX API”] Требования к API: [укажите требования, например, “простота использования для типичных случаев, гибкость для сложных, четкая семантика ошибок”]

Проектирование должно включать:

  1. Заголовочный файл с полными объявлениями функций, типов и констант с документирующими комментариями.
  2. Для каждой функции: назначение, предусловия, постусловия, возможные ошибки.
  3. Стратегию обработки ошибок: через errno, коды возврата или структуру ошибки – с обоснованием выбора.
  4. Примеры типичного использования: минимальный пример и расширенный.
  5. Анализ потенциальных ловушек для пользователей API и как их предотвратить через дизайн.
  6. Стратегию версионирования для будущих изменений без нарушения обратной совместимости.

Ограничения: API должен следовать принципу наименьшего удивления, ошибки должны быть обнаружимы на этапе компиляции где это возможно.

*****

Почему это работает:
Требование анализировать "ловушки для пользователей API" и предотвращать их через дизайн – это переход от "что делает функция" к "как ее сложно использовать неправильно", что является ключевым критерием качества API.

25. Реализация механизма сторожевого таймера

Проблема:
Системы без механизма восстановления после зависания могут застревать в некорректном состоянии на неопределенное время – особенно критично для встроенных устройств без возможности ручного перезапуска.

Решение:
Промпт создает надежный механизм сторожевого таймера с корректной интеграцией в систему и обработкой различных сценариев сбоя.

Текст промпта:

*****

Ты – [укажите роль, например, “разработчик надежных встроенных систем с опытом реализации механизмов самовосстановления и сторожевых таймеров”].

Реализуй механизм сторожевого таймера для следующей системы:

Платформа: [укажите платформу, например, “микроконтроллер STM32 с аппаратным независимым сторожевым таймером (IWDG)” или “Linux-система с программным сторожевым таймером через /dev/watchdog”] Архитектура системы: [опишите архитектуру, например, “несколько независимых задач FreeRTOS, каждая должна сообщать о своей работоспособности”] Требования: [укажите требования, например, “сброс системы при зависании любой критической задачи, журналирование причины сброса в энергонезависимой памяти”]

Реализация должна включать:

  1. Инициализацию и настройку сторожевого таймера с выбором таймаута.
  2. Механизм "кормления" таймера: как каждая задача сообщает о работоспособности.
  3. Определение критических задач и стратегию: что считается зависанием.
  4. Сохранение диагностической информации перед сбросом: какая задача не ответила, состояние системы.
  5. Чтение и анализ причины предыдущего сброса при старте системы.

Объясни: почему выбранный таймаут является компромиссом между чувствительностью к зависаниям и ложными срабатываниями при высокой нагрузке.
Ограничения: механизм кормления таймера должен быть устойчив к ошибкам в логике самого механизма (не должен кормить таймер при зависшей задаче мониторинга).

*****

Почему это работает:
Требование обеспечить устойчивость самого механизма кормления таймера к зависанию – это нетривиальное требование, которое обычно упускается и которое превращает "красивую" реализацию в реально работающую защиту.

26. Написание документации к системному коду

Проблема:
Документация системного кода часто либо описывает очевидное ("функция возвращает значение"), либо упускает критически важные детали о предусловиях, владении памятью и потокобезопасности.

Решение:
Промпт создает содержательную документацию, которая отвечает на вопросы следующего разработчика до того, как он их задаст.

Текст промпта:

*****

Ты – [укажите роль, например, “технический писатель со специализацией в документировании системного программного обеспечения на C”].

Напиши документацию для следующего системного кода:

[вставьте код или описание модуля, например, “модуль управления пулом соединений: создание, получение, возврат, уничтожение”] Аудитория: [укажите аудиторию, например, “разработчики, которые будут использовать API, но не читали исходный код”] Формат: [укажите формат, например, “Doxygen-совместимые комментарии к функциям + README для модуля”]

Документация должна содержать для каждой функции:

  1. Краткое описание (одна строка) и подробное описание с примером использования.
  2. Предусловия: что должно быть выполнено до вызова.
  3. Постусловия: что гарантируется после успешного вызова.
  4. Параметры: тип, назначение, допустимые значения, владение памятью (кто освобождает).
  5. Возвращаемое значение и все возможные коды ошибок с объяснением причин.
  6. Потокобезопасность: можно ли вызывать из нескольких потоков одновременно.
  7. Ограничения: что нельзя делать (вызывать из контекста прерывания, держать блокировку при вызове и т.д.).

Ограничения: не документировать очевидное, фокусироваться на неочевидных деталях и потенциальных ловушках.

*****

Почему это работает:
Явное требование документировать владение памятью и потокобезопасность – это именно те аспекты, которые следующий разработчик не сможет вывести из кода без глубокого изучения всей реализации, и именно они чаще всего становятся источником ошибок.

27. Рефакторинг устаревшего системного кода

Проблема:
Рефакторинг системного кода без четкого плана и понимания рисков часто превращается в "починили одно – сломали другое", особенно когда код содержит неочевидные зависимости и побочные эффекты.

Решение:
Промпт создает структурированный план рефакторинга с явным анализом рисков и стратегией проверки корректности на каждом шаге.

Текст промпта:

*****

Ты – [укажите роль, например, “опытный разработчик системного программного обеспечения с опытом безопасного рефакторинга критически важного кода”].

Разработай план рефакторинга следующего устаревшего системного кода:

[вставьте код или описание модуля, например, “монолитный модуль обработки данных на 3000 строк, написанный 10 лет назад, без тестов, с глобальными переменными и смешанной ответственностью функций”] Цели рефакторинга: [укажите цели, например, “разделить на независимые модули, устранить глобальное состояние, добавить покрытие тестами”] Ограничения: [укажите ограничения, например, “нельзя менять публичный API, система работает в production, нельзя допустить регрессию поведения”]

План должен включать:

  1. Анализ текущего состояния: что именно делает код, какие есть скрытые зависимости и побочные эффекты.
  2. Стратегию рефакторинга: последовательность изменений от наименее рискованных к наиболее рискованным.
  3. Для каждого шага: что меняется, какой риск, как проверить что ничего не сломалось.
  4. Стратегию добавления тестов: как тестировать код без изменения его поведения (характеризующие тесты).
  5. Метрики успеха: как измерить что рефакторинг достиг целей.

Ограничения: каждый шаг должен оставлять систему в рабочем состоянии, никаких "больших взрывов" – только инкрементальные изменения.

*****

Почему это работает:
Требование инкрементальных изменений с проверкой работоспособности после каждого шага – это принципиальное отличие от "переписать с нуля", которое кажется привлекательным, но чаще всего заканчивается месяцами работы и новыми ошибками в старых местах.

Типичные ошибки при использовании нейросети в работе системного программиста

  1. Отправлять код без указания целевой платформы и версии ядра. Нейросеть может использовать API, устаревший три версии назад, и код будет выглядеть правильно, но не скомпилируется или сломается во время выполнения.
  2. Просить написать "безопасный код" без указания модели угроз. Безопасность от случайных ошибок и безопасность от намеренных атак – это разные задачи с разными решениями, и без уточнения нейросеть выберет произвольно.
  3. Принимать сгенерированный ассемблерный код без проверки соглашений о вызовах. Нейросеть может перепутать соглашения или пропустить сохранение регистров, что проявится как случайное повреждение данных в вызывающем коде.
  4. Не указывать ограничения контекста выполнения при запросе кода для ядра. Код, корректный в пользовательском пространстве, в контексте ядра может привести к панике из-за вызова функций, недопустимых в данном контексте.
  5. Запрашивать оптимизацию без данных профилировщика. Без реальных данных о том, где тратится время, нейросеть будет оптимизировать то, что выглядит медленным, а не то, что реально является узким местом – классическое преждевременное улучшение.
  6. Не проверять сгенерированный код на граничных условиях и путях ошибок. Нейросеть хорошо пишет "счастливый путь", но часто пропускает корректную обработку ошибок при выделении памяти, системных вызовах и граничных значениях входных данных.
  7. Запрашивать реализацию алгоритмов без блокировок без указания модели памяти. Алгоритм без блокировок, правильный на x86, может быть некорректен на ARM из-за более слабой модели памяти – это не теоретическая проблема, а реальный источник труднообнаруживаемых ошибок.
  8. Использовать сгенерированный код драйвера без проверки управления ресурсами в пути ошибки. Нейросеть часто корректно освобождает ресурсы при успешной инициализации, но пропускает правильную очистку при частичной инициализации – это приводит к утечкам в ядре.
  9. Не указывать требования к детерминированности при запросе кода для систем реального времени. Функция с недетерминированным временем выполнения (например, использующая динамическое выделение памяти) в системе реального времени нарушает временные гарантии, даже если в среднем работает достаточно быстро.

Сравнение слабых и сильных запросов к нейросети для задач системного программирования

Задача Слабый запрос Сильный запрос Почему важна разница
Анализ утечек памяти Найди утечки памяти в этом коде Проанализируй все пути выполнения функции, включая пути ошибок, найди места где выделенная через malloc память не освобождается, укажи номер строки и сценарий Без указания "все пути" нейросеть анализирует только основной путь и пропускает утечки при ошибках
Написание драйвера Напиши драйвер для Linux Напиши драйвер символьного устройства для Linux 5.15, используй cdev API, обеспечь корректное освобождение ресурсов в exit даже при частичной инициализации Без версии ядра используется устаревший API, без указания частичной инициализации пропускается критическая часть логики очистки
Оптимизация кода Оптимизируй эту функцию Оптимизируй функцию, вызываемую 10 млн раз/сек на Intel Core i7, данные профилировщика: 40% промахи кэша L1, анализируй по уровням от алгоритмического до инструкций Без данных профилировщика оптимизируется не то место, без уровней анализа упускается системный подход
Синхронизация потоков Исправь состояние гонки Найди все общие ресурсы, для каждого опиши конкретный сценарий гонки с последовательностью событий, предложи исправление сохраняющее параллелизм Без требования описать сценарий нейросеть дает теоретический анализ без проверяемого воспроизведения
Код для ядра Напиши обработчик прерывания Напиши обработчик прерывания UART для STM32F4 с FreeRTOS, передача данных через кольцевой буфер без блокировок, объясни что запрещено в контексте прерывания Без указания ОС и ограничений контекста нейросеть может использовать блокирующие функции, недопустимые в обработчике прерывания
Безопасность кода Сделай парсер безопасным Данные от внешних клиентов считать враждебными, защити от целочисленного переполнения при вычислении размеров, выхода за границы буфера, перечисли все потенциально уязвимые места Без явного указания "враждебные данные" нейросеть закрывает только случайные ошибки, игнорируя намеренные атаки
Документирование Задокументируй этот код Документируй для разработчиков-пользователей API: предусловия, постусловия, владение памятью, потокобезопасность, что нельзя делать – фокус на неочевидных деталях Без конкретных требований документация описывает очевидное и упускает критические детали о владении ресурсами и ограничениях использования

Советы по работе с нейросетью для системного программиста

  1. Всегда указывайте версию ядра или компилятора в запросах о системном коде. API ядра Linux меняется между версиями, и нейросеть без этой информации может сгенерировать синтаксически корректный код, который не скомпилируется на вашей версии из-за изменений в интерфейсах.
  2. Просите нейросеть перечислить все допущения, которые она сделала при генерации кода. Системный код критически зависит от предположений о среде выполнения, и скрытые допущения – это источник ошибок, которые проявляются только при изменении условий.
  3. Разделяйте запрос на "спроектируй" и "реализуй" как два отдельных обращения. Нейросеть, получившая сразу задачу на реализацию, пропускает этап проектирования и выдает первое пришедшее в голову решение – часто не оптимальное для системных задач.
  4. При запросе кода для работы с памятью отдельно просите перечислить все пути, где выделенная память освобождается. Это заставляет нейросеть явно проследить каждый путь выполнения вместо того, чтобы убедиться только в наличии вызовов освобождения памяти.
  5. Используйте итеративный подход: сначала получите скелет, затем уточняйте каждый компонент отдельно. Запрос "напиши полный драйвер" дает поверхностный результат, а "напиши только обработчик ioctl для драйвера с такими характеристиками" – детальный и проработанный.
  6. После получения кода отдельным запросом просите нейросеть сыграть роль злоумышленника и найти способы сломать написанный код. Смена роли с "автора" на "атакующего" активирует другой режим анализа и выявляет уязвимости, которые автор кода неосознанно игнорирует.
  7. Сохраняйте успешные промпты для системных задач в отдельный файл с пометкой о версии ядра и платформе. Запросы для системного программирования содержат много специфического контекста, и воссоздать точную формулировку, дающую нужный результат, значительно сложнее, чем в прикладных задачах – а удачные шаблоны для работы с нейросетью в области системного программирования экономят часы при следующей похожей задаче.
Бесплатно с ИИ Claude · ChatGPT
Баланс запросов: —