Библиотека Интернет Индустрии I2R.ru |
|||
|
СинхронизацияЕсли вы работаете с тредами или процессами и используете какой-нибудь вид IPC, вам может потребоваться синхронизация этих тредов или процессов, чтобы они работали друг с другом согласованно. Для синхронизации мы можем использовать следующее:
Критические секции не являются объектами ядра, как вы можете видеть. Их нельзя использовать для синхронизации процессов, их можно использовать тольк для синхронизации тредов внутри одного процесса. Немного теории Хорошо, немного теории... хмм... я не хочу писать тяжелый для восприятия теоретический материал, но думаю, что будет неплохо сначала сказать несколько слов. Мы синхронизируем большей частью из-за доступов к ресурсам и некоторым другим вещам, таким как доступ к нереентерабельному коду. Если один тред собирается синхронизироваться с другим, он говорит операционной системе (OS), что хочет получить доступ к ресурсам, код или чему бы то ни было еще. OS помещает этот тред в спящее состояние, пока другой тред, у которого есть затребованный ресурс, не скажет OS, что этот ресурс свободен для других тредов. В этот момент ожидающий тред находится в критической секции (CS). Конечно, если ресурс свободен в момент запроса, тред получит доступ немедленно. Обратите внимание: Я использовал слова: 'OS помещает этот тред в спящее состояние', это значит, что тред не будет тратить системное время, пока он ожидает ресурс. Это обратно так называемому 'busy waiting', когда тред ждет, но на это потребляется системное время. Смотрите код:
CS может быть частью программы, которая работает с уникальными ресурсами, и если более, чем один тред работает с ней в одно и то же время, он может потерперь неудачу. Поэтому эта часть код 'критична', а треды, работающие с ней, должны 'взаимно исключать' друг друга при работе с этой критической секцией. При использовании IPC в вирусах, требуется синхронизировать каждый зараженный процесс. Представьте, что у нас есть два треда в каждой зараженной системе. Первый ищет на HDD файлы, которые можно заразит, а второй - заражает их. У нас есть разделяемая область памяти, где 'ищущий' тред сохраняет найденные имена файлов, а 'заражающий' тред загружает их из этой области. В момент времени у нас может быть любое количество этих тредов. Мы должны убедиться, что только один 'ищущий' тред будет писать в защищенную память и только один 'заражающий' тред будет ждать, пока новые имена не будут загружены в память. Windows - это преимущественная мультизадачная система, что означает то, что запущенные процессы переключаются тогда, когда им это говорит делать система. Зная это, мы никогда не можем знать, насколько быстры наши процессы. Создавая синхронизированный код, мы не можем предполагать скорость выполнения тредов. Я хочу показать здесь возможную проблему 'писателей и читателей'. Вы можете посмотреть примеры (такие как этот), поискать умные книги или вирусы, использующие IPC, их много. Я покажу вам, что предлагают Windows для осуществления синхронизации. Критические секции Как я сказал, критические секции не являются объектами ядра и не могут быть использованны для синхронизации процессов. Посмотрите выше на 'busy-waiting' код. Я покажу тот же код, который использует критические секции.
Итак, наша критическая секция создана, и мы можем использовать ее.
Код отличается от того, что бы приведен выше, только методо ожидания. Если в критической секции находится один тред, а другой хочет в нее попасть, OS помещает его в сон... Если критическая секция нам больше не нужна, мы удаляем ее:
Также существует путь, чтобы узнать, можно ли войти в критическую секцию, так, чтобы OS не поместила тред в сон:
Последняя функция, которая работает с CS - это SetCriticalSectionSpinCount. Если у вас есть мультипроцессорная система - идите и прочитайте ее описания. У меня такой системы нет, поэтому этот вопрос меня не волнует :). Я думаю, что для использования критических секций вышеприведенной информации более чем достаточно. Синхронизация через объекты ядра Предполагается, что все объекты ядра могут использоваться как синхронизационные. Это значит, что они могут находиться в сигнализирующем или несигнализирующем состоянии. Если объект не используется, то он находится в несигнализирующем состоянии. Любой тред, который хочет получить доступ к таком объекту, должен подождать, пока объект не будет просигнализирован (например, процессы и треды сигнализируются, когда оканчивают свою работу). Доступ к объектам ядра можно получить через хэндл, который вы получаете как результат работы какой-нибудь функции с примерным названием CreateXOBJECTX.
События События - это простые объекты ядра, у которых нет специальных условий, при которых они переключаются в сигнализирующее состояние. Представьте, что один из процессов ждет события. Другой процесс может переключить событие с помощью функции SetEvent. Итак, рассмотрим это шаг за шагом...
Если один процесс создает событие, другой может получить доступ к этому событию, используя его имя:
Есть три функции для работы с состоянием событий.
Мутексы Слово мутекс означает 'mutual exclusion' (взаимное исключение). Это один из легких в использовании и очень полезных синхронизационных объектов. Он похож на критические секции, но его можно использовать во взаимодействии между процессами. Мы можем создать мутекс следующим образом:
Существующий мутекс мы можем открыть так:
Обе эти функции возвращают хэндл мутекса, если вызов функции прошел успешно. Хорошо, предположим, что ваш тред создал мутекс и владеет им. Другие треды ждут мутекса одной из функций WaitX. Если мутекс вам больше не нужен - освободите его с помощью функции ReleaseMutex - один ждущий тред проснется и мутекс снова будет в несигнализированном состоянии. Вы можете освободить только тот мутекс, которым владеете.
Может случиться, что какой-то тред не освободит мутекс и закончит работу. Такой мутекс считается заброшенным, и через некоторое время система проверит его и освободит. Все о мутексах. Семафоры Семафоры - это очень мощные синхронизационные объекты. Сказано, что вы можете синхронизировать с их помощью все, что угодно. Как и мутексы, семафоры наблюдают за входом в критическую секцию, но разница заключается в том, что в одной критической секции может быть больше одного треда. Семафоры могут использоваться для ресурсов с ограниченным количеством. Мы можем создать семафор следующим образом:
Каждый раз, когда вход в критическую секцию осуществляется через семафоры, Windows уменьшает количество 'свободных ресурсов' - понижает количество доступов в критическую секцию. Если счетчик семафора равен нулю, вход в критическую секцию закрывается и входящий тред помещается в сон.
Если нет надобности в использовании ресурса, за которым наблюдает семафор, используйте функцию ReleaseSemaphore, чтобы увеличить количество возможных доступов к ресурсу.
Семафоры находятся в сигнализирующем состоянии, если значение его счетчика не равно нулю, в противном случае он устанавливается в несигнализирующее состоянии и входящий тред помещается в сон, как я говорил раньше... Все о семафорах. Ждущие таймеры Ждущие таймеры появились в Windows начиная с NT 4. До сих пор у нас были объекты, которые мы должны были вручную (как правило :) ) переключить в сигнализирующее состояние. Ждущие таймеры - это объекты, которые сигнализируют себя сами после некоторого периода времени. Давайте начнем...
Итак, мы создали или открыли ждущий таймер, а теперь настоло время установить его.
Все о ждущих таймерах. Напоследок Я думаю, что большинство новых вирусов будут использовать какой-нибудь вид IPC, а значит и один из видов синхронизации. Эта статья дает только обзор того, что Windows предлагает для синхронизации, эта тема довольно сложна и не может быть полностью объяснена в одной или двух статьях... идите и синхронизируйте... :) Ratter/29A, пер. Aquila |
|
2000-2008 г. Все авторские права соблюдены. |
|