Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка к лабораторным работам (рус).doc
Скачиваний:
3
Добавлен:
15.11.2018
Размер:
353.79 Кб
Скачать

4.3.8. Синхронизация процессов

int MPI_Barrier( MPI_Comm comm)

  • comm - идентификатор группы

Блокирует работу процессов, вызвавших данную процедуру, до тех пор, пока все оставшиеся процессы группы comm также не выполнят эту процедуру.

4.3.9. Работа с группами процессов

int MPI_Comm_split( MPI_Comm comm, int color, int key, MPI_Comm *newcomm)

  • comm - идентификатор группы

  • color - признак разделения на группы

  • key - параметр, определяющий нумерацию в новых группах

  • OUT newcomm - идентификатор новой группы

Данная процедура разбивает все множество процессов, входящих в группу comm, на непересекающиеся подгруппы - одну подгруппу на каждое значение параметра color (неотрицательное число). Каждая новая подгруппа содержит все процессы одного цвета. Если в качестве color указано значение MPI_UNDEFINED, то в newcomm будет возвращено значение MPI_COMM_NULL.

int MPI_Comm_free( MPI_Comm comm)

  • OUT comm - идентификатор группы

Уничтожает группу, ассоциированную с идентификатором comm, который после возвращения устанавливается в MPI_COMM_NULL.

4.4. Задание на лабораторную работу

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

Вариант 1

MPI_Init, MPI_Finalize, MPI_Send, MPI_Recv, MPI_Get_count.

Вариант 2

MPI_Init, MPI_Finalize, MPI_Isend, MPI_Irecv, MPI_Wait.

Вариант 3

MPI_Init, MPI_Finalize, MPI_Isend, MPI_Irecv, MPI_Test, MPI_Testall.

Вариант 4

MPI_Init, MPI_Finalize, MPI_Send, MPI_Recv, MPI_Probe.

Вариант 6.

MPI_Init, MPI_Finalize, MPI_Isend, MPI_Irecv, MPI_Waitall.

Вариант 7.

MPI_Init, MPI_Finalize, MPI_Send_init, MPI_Recv_init, MPI_Startall.

Вариант 8.

MPI_Init, MPI_Finalize, MPI_Bcast, MPI_Gather.

Вариант 9.

MPI_Init, MPI_Finalize, MPI_Barrier.

4.5. Контрольные вопросы и задания

  1. Каково основное назначение интерфейса передачи сообщений?

  2. Какие группы функций существуют в библиотеке MPI?

  3. Чем отличаются прием/передача сообщений с блокировкой и без блокировки?

  4. Какие особенности имеет групповая передача данных? В каких случаях ее использование предпочтительно.

  5. Какие функции MPI организуют синхронизацию параллельно выполняемых процессов?

  6. Каким образом можно инициализировать библиотеку MPI, завершить ее работу?

  7. Какие функции MPI предназначены для организации групповой работы процессов?

5 ИЗМЕНЕНИЕ ФУНКЦИОНАЛЬНОСТИ WINDOWS-ПРИЛЖЕНИИЙ

5.1. Цель работы

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

5.2. Указания по подготовке к выполнению лабораторной работы

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

При подготовке к работе необходимо изучить конспект лекций по указанной теме, методические указания, а также разделы, указанные в [18, cc.478-580].

5.3. Обзор темы работы

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

В Windows 98 процессы фактически совместно используют 2 Гб адресного пространства (от 0x80000000 до 0xFFFFFFFF). На этот регион отображаются только системные компоненты и файлы, проецируемые в память.

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

Вот ситуации, в которых требуется прорыв за границы процессов и доступ к адресному пространству другого процесса:

  • создание подкласса окна, порожденного другим процессом;

  • получение информации для отладки (например, чтобы определить, какие DLL используются другим процессом);

  • установка ловушек (hooks) в других процессах.

В данной работе рассмотрим механизм установки ловушек как наиболее безопасный способ внедрения в чужой процесс. Чтобы они работали так же, как и в 16-разрядной Windows, Microsoft пришлось создать механизм, позволяющий внедрять DLL в адресное пространство другого процесса Рассмотрим его на примере

Процесс А (вроде утилиты Spy++) устанавливает ловушку WH_GETMESSAGE и наблюдает за сообщениями, которые обрабатываются окнами в системе. Ловушка устанавливается вызовом SetWindowsHookEx

HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMbgProc, hiribtDll, 0);

Аргумент WH_GETMESSAGE определяет тип ловушки, а параметр GetMsgProc — адрес функции (в адресном пространстве Вашего процесса), которую система должна вызывать всякий раз, когда окно собирается обработать сообщение Параметр hinstDll идентифицирует DLL, содержащую функцию GetMsgProc В Windows значение htnstDll для DLL фактически задаст адрес в виртуальной памяти, по которому DLL спроецирована на адресное пространство процесса. И, наконец, последний аргумент, 0, указывает поток, для которого предназначена ловушка. Поток может вызвать tWindowsHookEx и передать ей идентификатор другого потока в системе Передавая 0, мы сообщаем системе, что ставим ловушку для всех существующих в ней GUI-потоков

Теперь посмотрим, как все это действует:

1. Поток процесса В собирается направить сообщение какому-либо окну.

2. Система проверяет, не установлена ли для данного потока ловушка WH_GETMESSAGE.

3. Затем выясняет, спроецирована ли DLL, содержащая функцию GctMsgProc, на адресное пространство процесса В

4. Если указанная DLL еще не спроецирована, система отображает ее на адресное пространство процесса В и увеличивает счетчик блокировок (lock count) проекции DLL в процессе В на 1

5. Система проверяет, не совпадают ли значения hinstDll этой DLL, относящиеся к процессам А и В Если hinstD!l в обоих процессах одинаковы, то и адрес GetMsgProc в этих процессах тоже одинаков Тогда система может просто вызвать GetMsgProc в адресном пространстве процесса А. Если же hinstDll различны, система определяет адрес функции GetMsgProc в адресном пространстве процесса В по формуле:

GetMsgProc В = histDll В + (GetMsgProc А - hinstDll А)

Вычитая hinstDll из GetMsgProcA, Вы получаете смещение (в байтах) адреса функции GetMsgProc. Добавляя это смещение к hinstDll В, Вы получаете адрес GetMsgProc, соответствующий проекции DLL в адресном пространстве процесса В

6. Счетчик блокировок проекции DLL в процессе В увеличивается на 1.

7. Вызывается GetMsgProc в адресном пространстве процесса В.

8. После возврата из GetMsgProc счетчик блокировок проекции DLL в адресном пространстве процесса В уменьшается на 1.

Кстати, когда система внедряет или проецирует DLL, содержащую функцию фильтра ловушки, проецируется вся DLL, а не только эта функция. А значит, потокам, выполняемым в контексте процесса В, теперь доступны все функции такой DLL.

Итак, чтобы создать подкласс окна, сформированного потоком другого процесса, можно сначала установить ловушку WH_GETMESSAGE для этого потока, а затем — когда будет вызвана функция GetMsgProc - обратиться к SetWindowLongPtr и создать подкласс Разумеется, процедура подкласса должна быть в той же DLL, что и GetMsgProc.

В отличие от внедрения DLL с помощью реестра этот способ позволяет в любой момент отключить DLL от адресного пространства процесса, для чего достаточно вызвать:

BOOL UnhookWindowsHookEx(HHOOK hHook);

Когда поток обращается к этой функции, система просматривает внутренний список процессов, в которые ей пришлось внедрить данную DLL, и уменьшает счетчик ее блокировок на 1 Как только этот счетчик обнуляется, DLL автоматически выгружается. Вспомните: система увеличивает его непосредственно перед вызовом GetMsgProc. Это позволяет избежать нарушения доступа к памяти Если бы счетчик не увеличивался, то другой поток мог бы вызвать UnhookWindowsHookEx в тот момент, когда поток процесса В пытается выполнить код GetMsgProc,

Все это означает, что нельзя создать подкласс окна и тут же убрать ловушку — она должна действовать в течение всей жизни подкласса.