Все потоки
Поиск
Написать публикацию
Обновить
65.46

Системное программирование *

Обеспечение работы прикладного ПО

Сначала показывать
Порог рейтинга
Уровень сложности

Продолжаем написание операционок. Шаг за шагом

Время на прочтение2 мин
Количество просмотров8.2K
На написание этого поста меня подтолкнуло то, что посты iley прекратились, а хабралюди всё же хотели посты по осьдеву. Оговорюсь сразу, я сам изучаю и пишу небольшую ось, но изучаю, так что продвигаться будем вместе. Я собираюсь рассмотреть написание систем под защищённый режим для IA-32, рассказать о:
1) Проектировании;
2) Отладке;
3) Работе с графикой;
4) Работе с дисками;
5) Memory management;
6) Task management;
Возможно о чём-нибудь ещё, если это будет востребовано.
Читать дальше →

Беззамочные алгоритмы: ненастойчивый кэш

Время на прочтение5 мин
Количество просмотров2.9K
(Тот факт, что русского перевода понятию «lock-free» в литературе ещё не устоялось, — нисколько меня не убеждает, что такого перевода не должно быть.)

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

BOOL IsPrime(int n)
{
 static int nLast = 1;
 static BOOL fLastIsPrime = FALSE;

 // если значение параметра не изменилось с прошлого раза,
 // воспользуемся готовым результатом
 if (n == nLast) return fLastIsPrime;

 // вычислим и запомним новый результат
 nLast = n;
 fLastIsPrime = slow_IsPrime(n);
 return fLastIsPrime;
}

Само собой, этот код потоконебезопасен: если один поток находится внутри вызова slow_IsPrime(), то другой поток, вызвавший IsPrime(), застанет значения переменных nLast и fLastIsPrime несоответствующими одно другому.

Простое решение — заключить код в критическую секцию; но простота идёт в ущерб производительности: если, скажем, nLast = 5, fLastIsPrime = TRUE, и два потока одновременно вызывают IsPrime(5), то совершенно ни к чему им выстраиваться в очередь: ничего не мешает им одновременно воспользоваться кэшированным значением.

Посмотрим, как можно реализовать наш кэш беззамочно.
Читать дальше →

Беззамочные алгоритмы: модель «сделай, запиши,(попытайся снова)»

Время на прочтение4 мин
Количество просмотров2.1K
Реализованное нами в прошлый раз атомарное умножение является примером более общей модели, которую Реймонд назвал «сделай, запиши,(попытайся снова)».

for (;;) {
 // берём начальное значение общей переменной,
 // которую мы собираемся изменять
 oldValue = sharedVariable;

 ... берём начальные значения других параметров ...

 newValue = ... вычисляем новое значение, используя
                oldValue и копии остальных параметров ...

 // вместо Xxx может быть Acquire, Release, или ничего
 if (InterlockedCompareExchangeXxx(
            &sharedVariable,
            newValue, oldValue) == oldValue) {
  break; // запись удалась
 }

 ... удаляем newValue ...

} // попытаемся снова

Мы вычисляем новое значение, и затем вызовом InterlockedCompareExchange записываем его в общую переменную только в том случае, если её значение не изменялось. Если оно изменилось, значит другой поток нас опередил; в этом случае попытаемся выполнить операцию по-новой, с самого начала, — в надежде, что в следующий раз никто нас не «подрежет».
Читать дальше →

Потоко-безопасная ленивая инициализация в C++

Время на прочтение9 мин
Количество просмотров14K
Реймонд Чен написал занятную серию блогпостов о беззамочной синхронизации. Мне бы хотелось опубликовать эти заметки и для хаброчитателей. Данный пост — введение в серию, скомпилированное из трёх старых постов Чена.
  1. Ленивая инициализация встроенными средствами C++
  2. Беззамочная синхронизация
  3. Беззамочная потоко-безопасная ленивая инициализация


Ленивая инициализация встроенными средствами C++


Инициализация статических локальных переменных в C++ непотокобезопасна, причём намеренно!

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

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

int ComputeSomething()
{
  static int cachedResult = ComputeSomethingSlowly();
  return cachedResult;
}

(Примерно такой код советуют в популярном C++ FAQ, чтобы не зависеть от выбранного компилятором порядка инициализации глобальных статических переменных.)
Читать дальше →

Многопоточное программирование в Go

Время на прочтение10 мин
Количество просмотров8.9K
Возникла задача: у нас есть компилятор собственного языка программирования, которым мы компилируем некоторый диалект бейсика в исходник на C.

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

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

Несложная задача. Только есть одно «но». Количество исходников, которые планируется использовать как эталонные — около 15 тысяч файлов, суммарным объемом чуть меньше гига (для удобства они завернуты в один TAR). Подобный «прогон» может быть весьма долгим. И есть естественное желание сделать тест максимально быстрым, используя многопроцессорную машину, ибо задача прекрасно распараллеливается.

Как вариант — можно сделать Makefile и запускать его с ключом "-j" в GNU Make. Но если написать специализированную многопоточную программу, то можно достичь лучшей производительности.
Подробности

Пишем viewer почтовой базы MS Exchange (часть 2)

Время на прочтение13 мин
Количество просмотров2.9K

Здравствуйте, читатели Хабрахабр!

Это завершение поста начатого вот здесь.

В принципе, мы почти все уже сделали, осталось небольшое окончание. Напомню, мы взяли EDB базу, открыли ее, воспользовавшись технологией ESE, перечислили имеющиеся таблицы и начали перечислять колонки внутри этих таблиц. Нам осталось дополучить колонки, получить значения столбцов и вуаля, база прочитана.
Читать дальше →

Пишем viewer почтовой базы MS Exchange (часть 1)

Время на прочтение19 мин
Количество просмотров14K

В одной большой-пребольшой стране жили маленькие-премаленькие люди. И все было прекрасно пока не появилась глубокая-преглубокая яма прямо в центре этой большой, а точнее пребольшой страны. Ну, надо сказать, появилась она не одна и, конечно, не сразу, но никто об этом уже не вспомнит и никому это уже не важно.
Читать дальше →

xinetd + netcat → подводные камни

Время на прочтение3 мин
Количество просмотров4.7K
Если на удалённом сервере нужно делать какие-то действия, но лень возиться с написанием сетевого сервиса, на помощь приходит xinetd.

Лёгкость написания серверов для xinetd привлекательна, это действительно просто: пишем на любом языке простой скрипт, который работает с stdin и stdout (в простейшем случае это обычный REPL) и получаем одновременно консольную утилиту и сетевой сервер в одном флаконе.
После одной минуты на правку конфига xinetd получаем работающий сервер, к которому можно подключаться telnet-ом или netcat-ом и видеть результат на консоли.

image
Читать дальше →

Консервативная логика

Время на прочтение14 мин
Количество просмотров20K
Вооруженные жидким азотом оверклокеры неоднократно показывали, что современные чипы могут стабильно работать на частотах в разы выше номинальных, обеспечивая соответствующий рост производительности. Тем не менее, прогресс в области «гонки гигагерц» остановился давно и надежно. Первый «Pentium 4» с частотой больше 3 ГГц появился в далеком 2002 году, почти 10 лет назад. За прошедшие годы нормы техпроцессов уменьшились со 180 до 32 нм, но даже это не позволило существенно поднять штатные рабочие частоты. Все упирается в огромное тепловыделение элементов цифровой логики.

В основе «проблемы тепловыделения» лежит глубокая связь между информационной и термодинамической энтропией, а также второе начало термодинамики, запрещающее уменьшение общей энтропии замкнутой системы. Любое вычисление, уменьшающее энтропию информационную, обязано приводить к увеличению энтропии термодинамической, то есть к выделению тепла. Рольф Ландауэр в 1961 году показал [pdf], что уничтожение одного бита информации должно приводить к выделению не менее k∙T∙ln 2 джоулей энергии, где k – постоянная Больцмана и T – температура системы. Само по себе эта энергия невелика: для T=300K она составляет всего 0.017 эВ на бит, но в пересчете на процессор в целом суммарная энергия вырастает уже до величин порядка одного Джоуля за каждую секунду работы, то есть порядка одного Ватта [Компьютерра №538]. На практике этот теоретический минимум умножается на ненулевое сопротивление и прочие неидеальности реальных полупроводников. В результате мы получаем процессоры, которые по тепловыделению обгоняют утюги.
Читать дальше →

Чуть больше о загрузке самодельных ОС — пишем bootloader

Время на прочтение9 мин
Количество просмотров14K
Не так давно решил чуть получше изучить архитектуру IA-32. А что лучше всего для запоминания? Конечно же практика. Но программируя в ОС мы врядли получим самый низкий уровень доступ к железу без помех. Поэтому для этих целей будем писать собственное подобие операционной системы. То есть проще говоря будем выполнять свой код, сразу после загрузки BIOS'а.
Первой проблемой с которой столкнется желающий программировать на низком уровне — как же загрузить свой код?
Читать дальше →

Точки останова на ручной тяге (для архитектуры x86)

Время на прочтение9 мин
Количество просмотров5.8K
Любой программист хоть раз заглядывавший в отладчик знаком с понятием точки останова (aka бряк, breakpoint). Казалось бы нет ничего проще, чем поставить точку останова пара кликов мышкой в графическом интерфейсе или команда в консоли отладчика, но не всегда жизнь системного программиста столь проста и иногда возникает необходимость выставлять точки останова автоматически — изнутри самой программы.

Читать дальше →

Пишем свою ОС: Выпуск 1

Время на прочтение6 мин
Количество просмотров281K
Данный цикл статей посвящён низкоуровневому программированию, то есть архитектуре компьютера, устройству операционных систем, программированию на языке ассемблера и смежным областям. Пока что написанием занимаются два хабраюзера — iley и pehat. Для многих старшеклассников, студентов, да и профессиональных программистов эти темы оказываются весьма сложными при обучении. Существует много литературы и курсов, посвящённых низкоуровневому программированию, но по ним сложно составить полную и всеохватывающую картину. Сложно, прочитав одну-две книги по ассемблеру и операционным системам, хотя бы в общих чертах представить, как же на самом деле работает эта сложная система из железа, кремния и множества программ — компьютер.

Каждый решает проблему обучения по-своему. Кто-то читает много литературы, кто-то старается поскорее перейти к практике и разбираться по ходу дела, кто-то пытается объяснять друзьям всё, что сам изучает. А мы решили совместить эти подходы. Итак, в этом курсе статей мы будем шаг за шагом демонстрировать, как пишется простая операционная система. Статьи будут носить обзорный характер, то есть в них не будет исчерпывающих теоретических сведений, однако мы будем всегда стараться предоставить ссылки на хорошие теоретические материалы и ответить на все возникающие вопросы. Чёткого плана у нас нет, так что многие важные решения будут приниматься по ходу дела, с учётом ваших отзывов.
Читать дальше →

Ближайшие события

Пишем драйвер для USB девайса. Pipe 0: что такое usb?

Время на прочтение3 мин
Количество просмотров24K
Случилось так, что пришлось мне писать с нуля драйвер для usb дисплея под windows. Имея возможность — расскажу о деталях столь занимательного процесса.
image

USB – это simple

Несмотря на то, что написание драйверов считается достаточно трудным, в сравнении с прикладным программированием – и в этом низкоуровневом мире программисты не были обделены вниманием, большим шагом в упрощении создания драйверов стала разработка шины usb.
Итак, почему же шина usb так удобна, и что скрывает за собой слово Universal в расшифровке аббревиатуры.
Читать дальше →

Коварный и ужасный sndrec32.exe

Время на прочтение3 мин
Количество просмотров22K
Sound RecorderВ этом топике вы найдете немного ностальгии, каплю гнева и килограмм реверс-инжиниринга. Посвящается тем, кто знаком с программой «Звукозапись» не понаслышке :)

Когда небо было голубее, Солнце светило ярче, а Интернет был таким недоступным… Короче, в далеком детстве мне почему-то полюбилась стандартная программа «Звукозапись» из Windows 98. Не глядя на минимальную функциональность, я даже умудрялся делать в ней простейшие «ремиксы» ей же записанных мелодий из игр.

Шли годы. Железо становилось мощнее, а ОС функциональнее. Но «Звукозапись» не менялась. Даже в Windows XP она оставалась такой же, как и тогда. Пришло время обновить железо. 3 гигабайта оперативной памяти — раньше и мечтать о таком не приходилось. Этого уж точно должно хватить всем! Так и было, пока дело не дошло до той самой «Звукозаписи». После попытки записать небольшой звук программа невозмутимо возразила, что ей недостаточно оперативной памяти.
Читать дальше →

IPC: сокеты против именованных каналов

Время на прочтение6 мин
Количество просмотров32K
Абсолютные числа большого смысла не имеют, но как сравнение информация представляет некоторую ценность

Условия


Windows 7 x64 с обновлениями
AMD Athlon X2 4600+ (2.41ГГц)
DDR2 2Гб
.Net Framework 3.5, классы из FCL.
Два 64-битных процесса без дополнительных привилегий.
Антивирус Касперского выключен. С ним результаты сокетов существенно хуже.
Сокеты и именованные каналы в асинхронном режиме.
Размеры буферов подбирались оптимальные, эксперементально для каждого вида IPC.
Читать дальше →

Расширение функциональности готовых программ

Время на прочтение11 мин
Количество просмотров43K
В мире ПО существует огромное количество программ, забытых своими разработчиками. Хорошо, когда уже есть хорошая альтернатива. А если ее нет? В программе может катастрофически не хватать каких-то мелочей, некоторые досадные ошибки могут годами доставлять массу неудобств пользователям, а на новых версиях ОС программа и вовсе может отказаться работать. Далеко не всегда имеются исходные коды, чтобы привести программу в порядок. Если программа простая — не составит труда за короткий срок создать альтернативу. Но если программа большая и сложная, что же делать в таком случае? Не всегда рационально тратить время и деньги на разработку полного аналога, ведь расширить в разумных рамках функциональность и исправить большинство ошибок можно уже в готовом исполняемом файле.
В этой статье будут продемонстрированы методики модификации исполняемых файлов на примере расширения функциональности легендарной игры Age of Empires II (стратегия реального времени).
Читать дальше →

Маленькая, но очень коварная засада с программированием в kernelspace-е в ОС MS Windows

Время на прочтение1 мин
Количество просмотров3.8K
На днях отлаживал драйвер, при использовании которого возникали хаотические и, на первый взгляд, какие-то магические BSoD-ы. Все вызовы функций были правильные, никаких ошибок с нулевыми указателями и прочего распространенного гемороя не наблюдалось. Так и не поняв, что же могло случиться с этим драйвером я попросил более опытного коллегу посмотреть что же не так. Через несколько часов он сказал, что понял в чем причина бага. Результат обескуражил нас обоих.
Что же я услышал

Crash dump'ы и KeCapturePersistentThreadState

Время на прочтение2 мин
Количество просмотров2.1K
Я тут обнаружил очень занятную недокументированную функцию, экспортируемую ядром, на которую нет ссылок внутри ядра, но которая делает весьма занятную вещь. А именно, записывает в переданный кусок памяти полноценный minidump на данный момент времени.
Весьма полезно с учетом того, что там (в дампе) есть оффсеты неэкспортируемых структур типа PsLoadedModuleList, которые могут пригодиться.
Спасибо Freeman за помощь)

ULONG
NTAPI
KeCapturePersistentThreadState(
PCONTEXT Context,
PKTHREAD Thread,
ULONG BugCheckCode,
ULONG BugCheckParameter1,
ULONG BugCheckParameter2,
ULONG BugCheckParameter3,
ULONG BugCheckParameter4,
PVOID VirtualAddress
);


Входные параметры:
Context — текущий контекст (можно от балды, нужно лишь заполнить EIP & ESP)
Thread — текущий поток. можно указать NULL, тогда она сама возьмет текущий
BugCheckCode, ParametersX — багчек код и аргументы, которые она запишет в дамп.
VirtualAddress — адрес выделенных 16 страниц памяти (64кб), куда она положит аккуратно готовенький крешдамп.

Пример:

Заголовок дампа:
typedef struct _DUMP_HEADER {
/* 00 */ ULONG Signature;
/* 04 */ ULONG ValidDump;
/* 08 */ ULONG MajorVersion;
/* 0c */ ULONG MinorVersion;
/* 10 */ ULONG DirectoryTableBase;
/* 14 */ PULONG PfnDataBase;
/* 18 */ PLIST_ENTRY PsLoadedModuleList;
/* 1c */ PLIST_ENTRY PsActiveProcessHead;
/* 20 */ ULONG MachineImageType;
/* 24 */ ULONG NumberProcessors;
/* 28 */ ULONG BugCheckCode;
/* 2c */ ULONG BugCheckParameter1;
/* 30 */ ULONG BugCheckParameter2;
/* 34 */ ULONG BugCheckParameter3;
/* 38 */ ULONG BugCheckParameter4;
/* 3c */ CHAR VersionUser[32];
/* 5c */ UCHAR PaeEnabled;
UCHAR NotUsed[3];
/* 60 */ PVOID KdDebuggerDataBlock;
} DUMP_HEADER, *PDUMP_HEADER;


Использование функции: www.everfall.com/paste/id.php?mkgmkfg1a057

Кодес получает дамп, показывает адерса MmPfnDatabase, PsActiveProcessHead, PsLoadedModuleList и сбрасывает дамп на диск. Дамп можно спокойно запихать в WinDbg и изучать

Вообщем, весьма занятная штуковина…

Надо будет переписать свой gr8lkd (http://gr8lkd.googlecode.com/) с использованием этой функции.

Пишем свой первый Windows-драйвер

Время на прочтение5 мин
Количество просмотров136K
Итак, после моей предыдущей статьи я понял что тема про программирование драйверов Windows интересна хабровчанам, поэтому продолжу. В этой статье я решил разобрать простую программу-драйвер, которая делает только то, что пишет отладочное сообщение «Hello world!» при старте драйвера и «Goodbye!» при завершении, а также опишу те средства разработки, которые нам понадобятся для того, чтобы собрать и запустить драйвер.

Читать дальше

Вклад авторов