Программизм
 
Программизм
На главную | Графомания | Программизм | Книги | Всячина | Скачать | Ъ?  

Batch-файлы в Windows NT, часть 3 — синхронизация

Возвращаюсь к своей излюбленной теме — автоматизация нелёгкой трудовой деятельности программиста при помощи подручных средств, а именно — командного процессора Windows NT.

Я намеренно пишу «Windows NT» вместо «Windows 2000» или, не к ночи будь помянута, «Windows XP» — то, что я предлагаю, вполне может работать и в NT, а исключения оговариваются отдельно. Тестируется и используется всё это в Windows 2000, причём ещё и русской. Если кого интересуют мои личные предпочтения, то из всего оконного семейства я предпочитаю Windows 2000 английскую. Но — к делу.

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

echo. | time | find "."
program
echo. | time | find "."

Такой способ будет работать везде — хоть в Windows 9×, хоть в DOS. Однако есть существенный недостаток — наша программа может выдать что-нибудь на консоль, сделав её содержимое плохо читаемым. Пытливый ум спросит ещё, зачем я использую столь сложную конструкцию вместо time /t? А затем, отвечу я ему, что в этом случае я получаю время с большей точностью. К тому же на консоль выводится строчка «текущее время», что несколько облегчает поиск таких строк в логе фильтрами типа find или grep. Впрочем, если точности до минуты достаточно, а регулярные выражения не являются чем-то экзотическим, time /t, естественно, лучше.

Следующий способ более изощрён, но всё равно прост:

echo. | time | find "."
start /min /wait program
echo. | time | find "."

Ключ /min запускает программу минимизированной и спасает нас от полного паралича пользовательского интерфейса, который наступает, если консольное приложение начинает что-то быстро-быстро выводить на консоль.

А теперь задача, ради которой и была написана вся эта заметка. Надо запустить несколько процессов, дождаться их окончания и двигаться дальше. Скорее всего, всё движение дальше будет состоять в том, чтобы записать в log время завершения и звуком из динамика позвать оператора. Очевидно, что эта задача стандартными средствами Windows NT не решается, поэтому снова придётся писать маленькую, но очень полезную утилиту.

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

Семафор допускает две операции над собой: увеличить счётчик и уменьшить счётчик. В Win32 эти операции реализуются функциями ReleaseSemaphore() и WaitForSingleObject() соответственно. Семафор считается открытым (т.е. WaitForSingleObject() возвращает управление), когда его счётчик не равен нулю (то есть хотя бы раз была вызвана ReleaseSemaphore()). Подробнее об объектах синхронизации вообще и их реализации в Win32 в частности можно прочитать в одной из статей, ссылки на которые приведены внизу.

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

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

Чтобы предусмотреть запуск нескольких групп параллельных процессов, в командной строке можно передавать имя группы — оно будет использоваться для формирования имён объектов синхронизации. Вот пример такого batch-файла:

echo. | time | find "."
start sync s sample 3
start /min program1 ^& sync f sample
start /min program2 ^& sync f sample
start /min program3 ^& sync f sample
sync w sample
echo. | time | find "."

Программа sync выполняет три действия:

  1. s[tart] — создаёт семафор и пытается захватить его нужное количество раз (в данном случае — 3);
  2. f[inish] — сигнализирует о том, что один из параллельных процессов завершился;
  3. w[ait] — ждёт завершения процесса-мастера.

Обратите внимание на ^& в команде start — птичка позволяет передать & в качестве параметра, чтобы sync выполнился после program1.

Скачать программу можно, как обычно, в соответствующем разделе. Обратите внимание, что для синхронизации ожидающего процесса и процесса-мастера используется дополнительный объект — флаг (event). Ожидающий процесс пытается создать флаг уже взведённым, и если это удаётся, тут же завершается. Если это не удаётся, значит, такой флаг уже создан мастером, и надо просто дождаться его установки.

Ссылки по теме (открываются в новом окне):

11.03.2003

Поиск
См. также

Надо запустить несколько процессов, дождаться их окончания и двигаться дальше... »»»

Очевидно, что char поместится в int. Во многих моделях памяти размер указателя также равен размеру int. Следовательно, структуру можно заменить массивом... »»»

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

Рекомендую

e.g.Orius’
Игорь Иртеньев
Вячеслав Шевченко

Copyright notice

ъ) Все материалы, размещённые на странице, являются неотъемлемой собственностью автора с вытекающими отсюда правами, как ©, так и (ъ). Некоммерческое их распространение всячески приветствуется, разумеется, при условии сохранения ссылки на оригинал. Что касается коммерческого использования — пишите письма, договориться можно всегда.

Удивительное рядом

lj userhardsign
Закладки Карта Королёва

Пишите письма

Счётчики

XPEHOMETP™ Рейтинг@Mail.ru