next up previous contents
Next: Матричное умножение Up: PVM - параллельная виртуальная Previous: Точечное произведение   Contents

Пример с ошибкой

Пример с ошибкой демонстрирует, как кто-либо может принудительно завершать задачи и определять ситуации, когда задачи отрабатывают или завершаются ненормально. В данном примере порождаются несколько задач - так же, как это сделано в предыдущих примерах. Одна из них принудительно завершается предком. Поскольку интерес состоит в нахождении ненормальных завершений задач, после их порождения вызывается pvm_notify(). Вызовом pvm_notify() PVM приказывается передать вызывающей задаче сообщение о завершении работы определенных задач. В данном случае пользователя интересуют все потомки. Заметьте, что задача, вызывающая pvm_notify(), будет получать уведомления о ``прекращении существования'' задач, указанных в массиве их идентификаторов. Нет особого смысла передавать сообщение задаче, которая завершается. Вызов, связанный с извещениями, может также использоваться для информирования задач о том, что новый хост добавлен в виртуальную машину или удален из нее. Это применимо в ситуациях, когда программа стремится динамически адаптироваться к текущему состоянию сети.

После реализации запроса об уведомлениях задача-предок принудительно завершает работу одного из потомков. Вызовом
pvm_kill() принудительно завершается работа исключительно той задачи, чей идентификатор передан как параметр. После завершения одной из порожденных задач, предок с помощью
pvm_recv(-1, TASKDIED) ожидает сообщения, уведомляющего о
``смерти'' этой задачи. Идентификатор задачи, которая завершилась, передается в уведомительном сообщении в виде одного целого числа. Процесс распаковывает идентификатор ``мертвой'' задачи и выводит его на экран. Хорошим стилем так же считается и вывод заранее известного идентификатора завершаемой задачи. Эти идентификаторы должны быть идентичны. Задачи-потомки просто ждут примерно по минуте и затем спокойно завершаются.

Программа - пример failure.c:

/*

Пример уведомления о сбое

Демонстрируется, как сообщать о фактах завершения задач

*/

/* определения и прототипы библиотеки PVM */

#include <pvm3.h>

/* максимальное число потомков, которые

   будут порождаться этой программой */

#define MAXNCHILD 20

/* тег для использования в сообщениях, связанных

   с отработкой задач */

#define TASKDIED 11

int

main(int argc, char* argv[])

{

/* количество задач для порождения,

     3 используются по умолчанию */

int ntask = 3;

/* код возврата для вызовов PVM */

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;

}


next up previous contents
Next: Матричное умножение Up: PVM - параллельная виртуальная Previous: Точечное произведение   Contents
2004-06-22