Программирование >>  Структура ядра и системные вызовы 

1 ... 91 92 93 [ 94 ] 95 96 97 98


пользователя. Она не может позволить себе приостановиться в вызове 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, которые Позволяют модифицировать сигнальные маски отдельных потоков, и реентерабельные версии основных библиотечных функций. Ожидается, что все эти средства будут присутствовать и в других платформах, поддерживающих многопотоковые программы.

Многопотоковое программирование особенно полезно для объектно-ориентированных приложений, выполняемых на многопроцессорных машинах. В этом можно убедиться на примере распределенной многопотоковой интерактивной программы, которая приведена в последнем разделе. Взяв ее за основу, пользователи могут создавать собственные приложения, используя многопроцессорные и сетевые вычислительные ресурсы, которыми обладают машины, выполняющие их приложения.



1 ... 91 92 93 [ 94 ] 95 96 97 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика