Примером с ошибкой демонстрируется, как кто-либо может принудительно завершать задачи и определять ситуации, когда задачи отрабатывают или завершаются ненормально. В данном примере порождаются несколько задач - так же, как это сделано в предыдущих примерах. Одна из этих задач принудительно завершается предком. Поскольку интерес состоит в нахождении ненормальных завершений задач, после их порождения вызывается pvm_notify(). Вызовом pvm_notify() ПВМ приказывается передать вызывающей задаче сообщение о завершении работы определенных задач. В данном случае пользователя интересуют все потомки. Заметьте, что задача, вызывающая pvm_notify(), будет получать уведомления о "прекращении существования" задач, указанных в массиве идентификаторов задач. Нет особого смысла передавать сообщение задаче, которая завершается. Вызов, связанный с извещениями, может также использоваться для информирования задач о том, что новый хост добавлен в виртуальную машину или удален из нее. Это применимо в ситуациях, когда программа желает динамически адаптироваться к текущему состоянию машин.
После реализации запроса об уведомлениях, задача-предок принудительно завершает работу одного из потомков. Вызовом pvm_kill() принудительно завершается работа исключительно той задачи, чей идентификатор задачи передан как параметр. После завершения одной из порожденных задач, предок с помощью pvm_recv(-1, TASKDIED) ожидает сообщения, уведомляющего о "смерти" этой задачи. Идентификатор задачи, которая завершилась, передается в уведомительном сообщении в виде одного целого числа. Процесс распаковывает идентификатор "мертвой" задачи и выводит его на экран. Хорошим стилем так же считается и вывод заранее известного идентификатора завершаемой задачи. Эти идентификаторы должны быть идентичны. Задачи-потомки просто ждут примерно по минуте и, затем, спокойно завершаются.
Программа-пример failure_c:
Пример уведомления о сбое
Демонстрируется, как сообщать о фактах завершения задач
*/
/* определения и прототипы библиотеки ПВМ */
#include <pvm3.h>
/* максимальное число потомков, которые
будут порождаться этой программой */
#define MAXNCHILD 20
/* тег для использования в сообщениях, связанных с отработкой задач */
#define TASKDIED 11
int
main(int argc, char* argv[])
{
/* количество задач для порождения, 3 используются по умолчанию */
int ntask = 3;
/* код возврата для вызовов ПВМ */
int info;
/* свой идентификатор задачи */
int mytid;
/* свой идентификатор задачи-предка */
int myparent;
/* массив идентификаторов задач-потомков */
int child[MAXNCHILD];
int i, deadtid;
int tid;
char *argv[5];
/* поиск своего идентификатора задачи */
mytid = pvm_mytid();
/* проверка на ошибки */
if (mytid < 0) {
/* вывод на экран сообщения об ошибке */
pvm_perror(argv[0]);
/* выход из программы */
return -1;
}
/* нахождение числа-идентификатора задачи-предка */
myparent = pvm_parent();
/* выход, если есть ошибки, но не PvmNoParent */
if ((myparent < 0) && (myparent != PvmNoParent)) {
pvm_perror(argv[0]);
pvm_exit();
return -1;
}
/* если предка не найдено, то это и есть предок */
if (myparent == PvmNoParent) {
/* определение числа задач для порождения */
if (argc == 2) ntask = atoi(argv[1]);
/* удостоверение, что ntask - допустимо */
if ((ntask < 1) || (ntask > MAXNCHILD)) {pvm_exit(); return 0; }
/* порождение задач-потомков */
info = pvm_spawn(argv[0], (char**), PvmTaskDebug, (char*)0,
ntask, child);
/* удостоверение, что порождение произошло успешно */
if (info != ntask) { pvm_exit(); return -1; }
/* вывод на экран идентификаторов задач */
for (i = 0; i < ntask; i++) printf("t%x\t",child[i]); putchar('\n');
/* запрос об уведомлении о завершении потомка */
info = pvm_notify(PvmTaskExit, TASKDIED, ntask, child);
if (info < 0) { pvm_perror("notify"); pvm_exit(); return -1; }
/* уничтожение потомка со "средним" идентификатором */
info = pvm_kill(child[ntask/2]);
if (info < 0) { pvm_perror("kill"); pvm_exit(); return -1; }
/* ожидание уведомления */
info = pvm_recv(-1, TASKDIED);
if (info < 0) { pvm_ perror("recv"); pvm_exit(); return -1; }
info = pvm_upkint(&deadtid, 1, 1);
if (info < 0) pvm_perror("calling pvm_upkint");
/* должен быть потомок со "средним" номером */
printf("Задача t%x завершилась.\n", deadtid);
printf("Задача t%x является средним потомком.\n", child[ntask/2]);
pvm_exit();
return 0;
}
/* это потомок */
sleep(63);
pvm_exit();
return 0;
}