|
Программирование >> Структура ядра и системные вызовы
пользователя. Она не может позволить себе приостановиться в вызове thr Join и ожидать завершения других потоков. При вызове функций collecthosts и displayJiosts аргументы не указываются. Функция getcmd получает от пользователя команду shell и имя хост-машины. Затем она создает поток для выполнения функции exec shell. Фактическое значение, передаваемое в функцию execjshell,- символьная строка, завер-шаюшаяся символом NULL и содержащая команду, знак / и имя хост-машины, на которой должна быть выполнена команда. Например, если в функцию execshell передан аргумент cal 1995 > foo/fruit ТО она попросит выполнить команду cal 1995 > foo на машине fruit. Перечень хост-машин, на которых инсталлирован демон shell svc, определяется функцией collecthosts и сообшается пользователю функцией displayhosts. Определения функций collect hosts, display hosts и exec shell содержатся в файле shellcls.C: tinclude tinclude tinclude tinclude tinclude tinclude tinclude tinclude tinclude tinclude <iostream.h> <fstream.h> <strstream.h> <stdio.h> <netdir.h> <rpc/rpc.h> <string.h> mshell.h <thread.h> RPC.h tdefine MAXHOSTe fdefine TMPFILE /tmp/hosts static char *hostlist[MAXHOSTS]; static int numhosts; extern rwlock t rwlck; определяется и инициализируется в main shell.C /* RPC-вызов сервера для выполнения одной команды */ int exec host( const char* cmd, char* host } < .1. ГЧ Static int res=0; RPC cls cl( host, SHELLPR06,eHELLVEA; netpath*)-; if (Icl.goodO) return 1; .JS- ч cl.set auth( AUTH SYS }; if (cl.calK EXECSHELL, (xdrproc t)xdr string, (caddr t}scmd, (xdrproc t)xdr int, (caddr t)sres) != RPC SUCCESS} return 2; if (res!=0) ( cerr clnt: exec cmd failsNn ; return 4; return 0; /* проверка наличия RPC-сервера на указанной хост-машине */ int check host( const char* hostnm ) if (rw rdlock(srwlck}) perror( rw rdlock ); int i; for (i=0; i < numhosts; i++} if (Istrcmp(hostlistfi],hostnm)} break; if (rw unlock(srwlck)) perror( rw unlock }; return (i < numhosts) ? 1 : 0; /* выполнить команду на удаленной хост-машине */ void* exec shell( void* argp } static int rc = 0; char* cmd = (char*)argp; /* the input string syntax is: <cmd>/<host> */ char* host = strrchr(cmd,/}; *host++ = \0; if (!check host(host)) ( cout Invalid host: host \n flush; rc = 1; thr exit(src); rc = exec host( cmd, host ); thr exit(src); return 0; /* вывести список всех доступных хост-машин */ void* display hosts( void* argp } int rc 0; if (rw tryrdlock(srwlck}} ( cout Host table in processed, please waite...\n ; if (rw rdlock(srwlck)) perror( rw rdlock ); if (Inumhosts) { cout Host table is empty!\n flush; cout please select Collect hosts info optionNn flush; rc = -1; else { char buf[256];- ostrstream(buf,256) TMPFILE . thr self(); .ofstream ofs (buf); if (!ofs) cerr Create temp file buf failedVn ; else ( int i; for ( i=0; i < numhosts; i++) ofs i : hostlist[i) endl; ofs.close 0; char cmd[256); ostrstream(cmd,256) xterm -title Hosts -e view buf; if (system(cmd)) perror( system ); if (unlink(buf)) perror ( unlink ); if (rw unlock(Srwlck)) perror( rw unlock ); thr exit(&rc); return 0; /* записать имя удаленной хост-машины в таблицу */ int add host( const char* hostnm ) int new entry = 1; if (rw wrlock(Srwlck)) perror( rw wrlock ); int i; for ( i=0; i numhosts; i++) if (!strcmp(hostlist[i),hostnm)) break; if (i >= numhosts) ( if (numhosts >= MAXHOSTS) cerr Too many remote hosts detectedXn ; else { hostlist[numhosts] = new char[strlen(hostnm)+1); strcpy(hostlist[numhosts++],hostnm); else new entry =0; if (rw unlock(&rwlck)) perror( rw unlock ); return new entry; /* клиентская широковещательная функция обратного вызова */ bool t callme (caddr t res p, struct netbuf* addr, struct netconfig *nconf) int i; struct nd hostservlist *servp; if (netdir getbyaddr(nconf,Sservp,addr)) perror( netdir getbyaddr ); else for ( i=0; i < servp->h cnt; i++) if (!add host( servp->h hostservs[i].h host )) return TRUE; /* закончить широковещательную рассылку, если имя хост-машины встретилось дважды */ retuicn FALSE; /* определить удаленные хост-машины, на которых работает RPC-сервер */ void* collect hosts ( void* argp ) /* клиент посылает широковещательный запрос и ждет ответа */ int rc = RPC cls: :broadcast( SHELLPROG, SHELLVER, 0, (resultproc t)callme, (xdrproc t)xdr void, (caddr t)NULL, (xdrproc t)xdr void, (caddr t)NULL); switch (rc) { case RPC SUCCESS: break; case RPC TIMEDOUT: if (numhosts) break; default: cerr RPC broadcast failed\n ; rc = 1; thr exit(&rc); return 0; Функция collecthosts выполняет широковещательный RPC-вызов для опроса всех демонов shell svc в сети. Каждый ответ демона на RPC-вызов регистрируется функцией callme. Эта функция извлекает имя сервера с помощью функции netdir getbyaddr и добавляет это имя в таблицу hostlist с помощью функции addhost, которая возвращает 1 в случае успеха. В противном случае возвращается 0. Функция callme завершает широковещательный RPC, если видит, что одна и та же хост-машина ответила на запрос дважды. Это означает, что новых ответов нет и процесс широковещательной передачи повторяется. По завершении широковещательной передачи RPC-функция collectjiosts проверяет результат и закрывает свой поток. В случае успеха она возвращает RPC SUCCESS, а в случае неудачи - ненулевое значение. Контроль доступа к таблице hostlist выполняется с помощью блокировки чтения-записи rwlck. Это необходимо потому, что к таблице hostlist обращаются все потоки, созданные для выполнения функций collectJosts, displayjiosts к execshell. Важно, чтобы потоки записи (выполняющие функцию collectJosts) не обращались к таблице hostlist одновременно с потоками чтения (выполняющими функции display hosts и exec shell). Активизированная функция display Josts отображает все имена, имеющиеся в таблице hostlist (это имена хост-машин, на которых работает демон shell svc). Функция display Josts устанавливает блокировку чтения-записи перед обращением к таблице hostlist и снимает ее, завершив обращение, чтобы потоки collect Josts не могли внести изменения в таблицу во время чтения. Чтобы отделить вывод списка хост-машин от отображения меню главного потока, функция display hosts сохраняет список имен во временном файле и вызывает программу xtem для выполнения команды view <fempJile > в отдельном окне. Это окно исчезает, когда пользователь завершает работу программы view и временный файл удаляется. В случае успешного выполнения функция закрывает поток с кодом возврата О, а в случае неудачи - с ненулевым кодом. Входным аргументом при вызове команды exec shellявляется символьная строка, которая содержит определенную пользователем команду, имя хост-машшы и завершается симюлом NULL. Функция вызывает команду clreclc Jiost, которая проверяет, находится ли указанное имя в таблице. Если имени в таблице нет, поток закрывается с кодом 1 (неудача). Если имя в таблице есть, функция вызывает функцию execjiost, которая создает объект RPC cls для установления соединения с демоном sliell svc на указанной хост-машине. Функция execjiost вызывает RPC-функцию execshell, которая выполняет пользовательскую команду на указанной машине. Функция ехес /го5;и поток exec shell завершаются с нулевым значением, если команда на удаленной машине выполнена нормально; в противном случае возвращается ненулевое значение. Наша интерактивная программа состоит из файлов mainjshell.Cu shell els. С. Ниже показано, как она компилируется и запускается. В приведенном примере и veggie - имена хост-машин, на которых инсталлирован демон shell svc. -о shell els -Ithread -Insl % CC -DSYSV4 shell cls.C main shell.C % shell cls 0: Collect hosts names 1: Display hosts names 2: Execute command 3:.- Quit Selection> 0 0: Collect hosts names 1: Display hosts names 2: Execute command 3: Quit Selection> 1 <B окне программы xterm выводится список: 0:fruit l:veggie> 0: Collect hosts names 1: Display hosts names 2: Execute command 3: Quit Selection> 2 shell cmd> cal 1995 > foo host> fruit 0: Collect hosts names 1: Display hosts names 2: Execute command 3: Quit \ Selection>\3 13.9. Заключение в этой главе рассмотрены методы многопотокового программирования, основанные на библиотеке потоков ОС Solaris фирмы Sun Microsystems и стандарте POSIX.Ic. И в библиотеке Sun, и в стандарте POSIX.Ic есть набор многопотоковых библиотечных функций, которые позволяют пользователям создавать в своих программах потоки выполнения и управлять ими. Кроме того, в распоряжении пользователей имеются различные объекты синхронизации: взаимоисключаюшие блокировки, условные переменные и семафоры,- с помощью которых пользователи могут синхронизировать доступ потоков к общим данным в одном процессе. Среди других средств системной поддержки многопотоковых программ - специальные API, которые Позволяют модифицировать сигнальные маски отдельных потоков, и реентерабельные версии основных библиотечных функций. Ожидается, что все эти средства будут присутствовать и в других платформах, поддерживающих многопотоковые программы. Многопотоковое программирование особенно полезно для объектно-ориентированных приложений, выполняемых на многопроцессорных машинах. В этом можно убедиться на примере распределенной многопотоковой интерактивной программы, которая приведена в последнем разделе. Взяв ее за основу, пользователи могут создавать собственные приложения, используя многопроцессорные и сетевые вычислительные ресурсы, которыми обладают машины, выполняющие их приложения.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |