Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
UNIVERSIDADE LUTERANA DO BRASIL
CENTRO DE CIÊNCIAS NATURAIS E EXATAS
DEPARTAMENTO DE INFORMÁTICA
AMBIENTE DE MULTIPROCESSAMENTO PARA UMA REDE DE MÁQUINAS UNIX:
MANUAL DE IMPLEMENTAÇÃO
por
ELGIO SCHLEMER
Prof. Roland TeodorowitschOrientador
Canoas, dezembro de 1996
Agradeço à meus pai s, Erno e Eroni , pel oapoio i ncondi ci onal em todos osmomentos; aos meus prof essores, emespecial a Roland Teodorowi tsch, pel adedi cada ori entação; a M iguel RobertoBorges, por sua i ncansável col aboração ecessão de recursos; e acima de tudo,agradeço à Deus, por ter col ocado essaspessoas em meu caminho.
“ Senhor, deste−me tanto! Dá−me umacoi sa a mai s: um coração agradecido” .(George Herbert)
SUMÁRIO
LISTA DE FIGURAS
RESUMO
Este trabalho descreve a implementação de um ambiente que transf orma
uma rede UNI X em um mul t i processador vi rtual , assim como f az o PVM .
Basi camente, o ambiente é composto de uma bi bl i oteca, l i ncada com
programas dos usuári os e de um processo que control a a execução e
comuni cação entre processos no si stema.
ABSTRACT
Thi s work descri bes the implementati on of a envi ronment that turns a
UNI X network i nto a vi r tual mul ti processor, l i ke PVM does.
Basi cal l y, the envi ronment i s i ntegrated by a l i brary l i nked wi th the
users’ programs and a process that control s the executi on and communi cati ons
between process i n the system.
1INTRODUÇÃO
Ambientes mul ti processados baseados em UNI X são, do ponto de vi sta
didáti co, di f ícei s de entender em f unção de sua complexi dade e da escassa
l i teratura em rel ação ao seu f unci onamento i nterno. O A mbiente
impl ementado f ornece f erramentas de estudo bastante práti cas, f aci l i tando o
aprendi zado.
O AMRU (Ambi ente de Mul ti processamento para uma Rede de máquinas
Uni x) ut i l i za, basi camente, chamadas de RPC (Remote Procedure Cal l )
di sponívei s no UNI X e roti nas bási cas do C. Fornece todas as roti nas
necessári as à cri ação de uma máqui na paral el a vi rtual , como, por exemplo,
servi ços de “ send” e “ recei ve” (envi o e recepção de mensagens entre
processos) e manipulação de processos.
Um ambi ente paral el o vi rtual é aquele que permi te programar como se
est i vesse uti l i zando uma máquina paral el a, quando na verdade estamos
simulando−a. O Ambiente de Mul ti processamento para uma Rede de máquinas
Uni x (AMRU), f az esta simul ação em cima de uma rede rodando UNI X ou
compatível .
Este si stema f ornece roti nas de cri ação e comuni cação de processos,
possibi l i tando rodar vár i os processos ao mesmo tempo, di vi di dos entre as
máquinas da rede, e control á−los como se esti vessem rodando em um
processador l ocal .
Para i sso ser possível , f az−se uso de chamadas RPC (Remote Procedure
Cal l ) [ SUN 90] , pacote de comuni cação exi stente no UNI X , à um processo
anteri ormente i ni ci al i zado nas máqui nas da rede (chamado de daemon), e,
através dele, executa−se os servi ços necessári os.
Estes servi ços podem ser: i nseri r uma nova máquina no si stema,
tornando−a um “ processador v i rtual ” ; cri ar um novo processo em uma
máquina especi f i cada; envi ar um mensagem para um processo do si stema ou
receber uma mensagem de um processo do si stema.
Para tanto, o capítul o 2 f ornece uma vi são geral do ambi ente. Em
seguida o capítul o 3 descreve com detal hes a implementação de cada f unção
do ambi ente. Duas apl i cações são di scut i das no capítul o 4. Por f im, o capítul o
5 apresenta as conclusões.
9
2PROGRAMAÇÃO PARALELA
Máquinas paral el as são aquelas que possuem doi s ou mai s processadores
e são capazes de executar pel o menos doi s processos simul taneamente. Ou
sej a, em determinado momento, duas i nstruções estão sendo executadas ao
mesmo tempo. Essas máquinas são caras, e portanto, di f ícei s de serem
encontradas. Em f unção di sto, al ternati vas mai s econômicas f oram
desenvol vi das.
Uma destas al ternati vas é a uti l i zação de uma rede de computadores
como se f osse uma úni ca máquina com vári os processadores (f i gura 2.1). Um
si stema rodando nesta rede seri a capaz de mascara−l a, possi bi l i tando aos
processos “ enxergá−la” como uma máquina paral el a.
Figura 2.1− Ilustração de uma rede
Neste caso, cada máquina é vi sta como se f osse um processador de uma
máquina paral el a vi rtual , e pode−se, portanto, uti l i zá−la como tal . Este é o
pri nci pal obj eti vo deste trabal ho de conclusão, desenvol ver um ambi ente que
explore os recursos de uma rede, no qual pode−se i ni ci ar a execução de
múl ti pl os processos e através do qual estes processos possam se comuni car .
Um exemplo das possibi l i dades do si stema proposto neste trabalho é
mostrado na f i gura 2.2. A través de uma séri e de chamadas à uma bi bl i oteca de
f unções, o usuári o pode: agregar uma máqui na da rede ao seu
mul t i processador vi rtual (am_addhost()), i ni ci ar um processo em al guma
máquina da rede (am_star tproc()) e envi ar (am_send() ) ou receber (
am_recei ve()) mensagens.
11
#i ncl ude " am_l i b. c"mai n( ){ i nt aux; l ong i nt t i d; char msg[ 100] ; i nt m1, m2, p1, p2;
m1=am_i ni t ( ) ; / * i ni c i al i za o si st ema par el el o vi r t ual * / i f ( m1==−1)
exi t ( 0) ; m1=am_addhost ( " ver di " ) ; / * i nser e a maqui na ver di no si st ema * / i f ( m1==−1)
exi t ( 0) ; m2=am_addhost ( " vi val di " ) ; / * i nser e a maqui na vi val di no si st ema * / i f ( m2==−1)
exi t ( 0) ; p1=am_st ar t pr oc( m1, " exempl o2" ) ; / * i ni c i a o pr ocesso exempl o2 na
maqui na ver di * / i f ( p1==−1)
exi t ( 0) ; p2=am_st ar t pr oc( m2, " exempl o2" ) ; / * i ni c i a o pr ocesso exempl o2 na
maqui na vi val di * / i f ( p1==−1)
exi t ( 0) ;
am_send( p1, " Quer i da Ver di . . . " ) ; / * envi a msg par a pr ocesso na maq 1* /
am_send( p2, " Quer i da Vi val di . . . " ) ; / * envi a msg par a pr ocesso na maq 2* /
t i d=am_r ecei ve( −1, msg) ; / * r ecebe uma msg de qual quer pr ocesso* /
t i d=am_r ecei ve( −1, msg) ;/ * r ecebe uma msg de qual quer pr ocesso* /
}
Figura 2.2− Programa exemplo1.c
Neste exemplo são cri ados doi s processos “ exemplo2” , um executará na
máquina verdi e o outro na máquina vi val di . Envia−se, em seguida, uma
mensagem para cada um e espera−se pel as respostas.
#i ncl ude " am_l i b. c"
mai n( ){ l ong i nt t i d; char msg[ 100] , nome[ 30] ;
get host name( nome, 64) ; / * obt em o nome dest a máqui na* / t i d=am_r ecei ve( −1, msg) ; / * r ecebe mensagem de qual quer pr ocesso * / f pr i nt f ( st der r , " Recebi mensagem ’ %s’ do pr ocesso %d\ n" , msg, t i d) ;
/ * i mpr i me a mensagem na t el a* / spr i nt f ( msg, " Eu sou a maqui na %s" , nome) ; am_send( t i d, msg) ; / * envi a mensagem* /
}
Figura 2.3− Programa exemplo2.c
Na f i gura 2.3 temos o código do programa exemplo2. Sua f unção é
receber mensagem de qual quer processo e enviar uma resposta.
12
3IMPLEMENTAÇÃO
O A mbiente Mul ti processado para uma Rede de máquinas Uni x
(AM RU), f oi total mente desenvol vi do em C sobre o si stema operaci onal
L I NUX (compatível com UNI X) versão 2.2. Foram uti l i zadas, para tanto, as
máquinas verdi e vi val di do L aboratóri o de I nf ormát i ca da UL BRA .
Foi implementada uma bi bl i oteca contendo as f unções necessári as à
uti l i zação do “ A MRU” (am_l i b.c) e um programa daemon (amrud.c). Um
programa daemon é um processo resi dente que permanece em execução
conti nua.
3.1Bibl ioteca am_l ib.c
Esta bi bl i oteca contém as f unções necessári as à manipulação do
Ambiente M ul ti programado. Deve ser i ncl uída na implementação que use as
característi cas deste si stema.
Estruturas e Var iáveis Globais
A bibl i oteca cri a duas estruturas para manipular processos e máquinas
instal adas.
A estrutura AM_LI STHOST manipula a l i sta de máquinas que estão
di sponívei s no si stema. Sua def i ni ção pode ser vi sta na f i gura 2.1.
st r uct AM_LI STHOST{char nome[ 20] ;i nt numer o;char st at us;} ;/ * Li st a das host s par t i c i pant es do si st ema nome= nome da host ( ex. ver di ) numer o= numer o pel o qual ser a r econheci da no si st ema st at us= 0 se campo di sponi vel , 1 se ocupado por host at i va* /
Figura 2.1− Estrutura AM_LISTHOST
O regi stro nome corresponde ao nome da máquina, através da qual el a é
i denti f i cada e ref erenciada (por exemplo: verdi , vi val di , mozart, etc). O
regi stro numero é o número pel o qual el a é conhecida no si stema. Este
número é i ncrementado a cada chamada de am_addhost() , sendo armazenado
na vari ável gl obal am_nummaq. Desta f orma a primei ra máquina a ser
i nseri da receberá o número zero, a segunda um, e assim sucessi vamente. Por
úl t i mo, o regi stro status f ornece i nf ormações sobre o regi stro dentro da
estrutura. Se status está em zero, si gni f i ca que aquel a posi ção está di sponível
para ser usada por uma nova máquina, se f or um, i ndi ca a presença de uma
máquina ati va. Esta estrutura é usada pela vari ável gl obal am_hostl i st, que é
um vetor de AM_MAXMAQ posi ções (def i ni do como constante) .
A estrutura AM_LI STPROC manipula i nf ormações sobre os processos
instal ados pelo si stema. Sua def i ni ção pode ser vi sta na f i gura 2.2.
st r uct AM_LI STPROC{l ong i nt npr oc;i nt nmaq;char st at us;char nome[ 20] ;} ;/ * Li st a das pr ocessos i ni ci al i zados por st ar t pr oc npr oc= numer o do pr ocesso dado pel o si st ema ( uma composi cao
do numer o da host e o i d do pr ocesso nmaq= numer o da host onde encont r a−se est e pr ocesso nome= nome do pr ocesso.* /
Figura 3.2− Estrutura AM_LISTPROC
O regi stro nproc guarda o número do processo cri ado. Este número é
gerado pelo própri o si stema e di f ere do número de processo (i d) usado
14
i nternamente pelo si stema operaci onal . O regi stro nmaq contém a i nf ormação
do número da máquina à qual pertence o ref eri do processo, número este que
coi nci de com o regi stro numero em am_hostl i st. Status pode ser zero ou um.
Zero i ndi ca que este regi stro não está ocupado por nenhum processo e um que
exi ste um processo ati vo e pronto para ser mani pulado. E, por f im, o campo
nome contém uma str i ng designando o nome do processo. A vari ável gl obal
am_l i stpr oc ut i l i za esta estrutura, para declarar um vetor de AM_MAXPROC
posi ções (def i ni da como constante) .
A vari ável am_servi dor i ndi ca se este processo é ou não o processo
servi dor, setada para zero caso af i rmati vo e para um caso contrár i o. Torna−se
servi dor o processo que executar a f unção am_ini t( ) .
Função am_init()
Uti l i zada para i ni ci al i zar o processo corrente como servi dor, i ni ci al i za
as l i stas de máqui nas e de processos, seta a vari ável i ndi cadora de servi dor
para zero e j á i nsere a própri a máquina no si stema se regi strando como
apl i cação servi dora j unto ao amrud. Se a apl i cação não executar esta f unção,
el a será considerada como uma apl i cação cl i ente, não control ará os processos
(manipulação das l i stas) e não poderá i nseri r máquinas no si stema e nem
ini ci al i zar processos, poi s são caracter ísti cas excl usi vas do processo servi dor.
O código desta f unção pode ser v i sto na f i gura 3.3.
15
i nt am_i ni t ( ){ char nome[ 50] , envi a[ 100] , r ecebe[ 25] ; i nt cont a; char * env, * pr ecebe; i nt st at ; f or ( cont a=0; cont a<AM_MAXMAQ; cont a++)
am_l i st maq[ cont a] . st at us=0; f or ( cont a=0; cont a<AM_MAXPROC; cont a++)
am_l i st pr oc[ cont a] . st at us=0; get host name( nome, 64) ; am_ser vi dor =0; cont a=am_addhost ( nome) ; spr i nt f ( envi a, " 8#%d#" , get pi d( ) ) ; env=envi a; pr ecebe=r ecebe; st at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; am_l i st pr oc[ am_numpr oc] . st at us=1; am_l i st pr oc[ am_numpr oc] . nmaq=am_myhost ( ) ; am_l i st pr oc[ am_numpr oc] . npr oc=am_myt i d( ) ;
r et ur n( cont a) ;}
Figura 3.3− Função am_init()
Função am_hostname()
Obtém o nome da máquina cuj o número é maq. Recebe um i ntei ro com o
número da máquina, e uma str i ng para armazenar o nome obti do. O código
desta f unção pode ser vi sto na f i gura 3.4.
É necessári o, às vezes conhecer o nome de determi nada máqui na (para
usar este nome em uma chamada RPC, por exempl o). A l i sta de máquinas é
control ada e conhecida apenas pelo servi dor . Deve−se, portanto, requi si tar ao
servi dor que consul te sua base de dados e retorne o número desta máquina.
Entretanto, para se f azer uma chamada de RPC, preci sa−se i nf ormar o nome
da máquina, e uma vez que a apl i cação cl i ente não tem esta i nf ormação
(apenas seu daemon possui ), deve−se dei xar que o daemon l ocal execute esta
taref a que é real i zada da seguinte f orma:
− obtém−se através da f unção gethostname o nome da máquina l ocal ;
16
− prepara−se a str i ng de envio composta de duas partes: o número 6
i ndi cando que o amr ud (daemon) deve executar o servi ço 6, seguido do dado
ref erente ao número da máquina para qual desej a−se obter o nome;
− f az−se uma chamada RPC ao amr ud l ocal , passando a str i ng e
recebendo outra str i ng;
− o amrud retornará um entre três padrões de resposta. Se a str i ng
retornada possui r o caracter ‘1’ em sua primei ra posi ção, i ndi ca que o amrud
retornou o nome da máquina requi si tada, nome este que segue após o caracter
‘#’ na str i ng. Se, porém, a str i ng retornada começar com ‘ 0’ , o amrud l ocal
não teve condi ções de l ocal i zar a máquina porque el a não está i nseri da no
si stema, ou sej a, não exi ste. O caracter ‘ 2’ na primei ra posi ção i ndi ca que o
amrud l ocal não teve condi ções de l ocal i zar a máquina porque el e não é o
servi dor e não conhece a l i sta de máquinas. Neste caso, segue−se após o
caracter ‘#’ o nome da máqui na que possui o amrud servi dor, devendo a
f unção f azer uma nova chamada de RPC, desta vez, porém, desti nada ao
amrud servi dor. Nesta chamada, se a str i ng retornada não i ni ci ar com ‘1’ ,
certamente esta máquina não exi ste.
− retorna−se 1, caso a máquina tenha si do encontrada, ou −1 caso
contrári o.
É i nteressante sal i entar o f ato de todas as chamadas de RPC serem
através da troca de str i ngs. Optou−se por str i ngs pelo f ato das chamadas
envol verem i ntei ros e str i ngs simul taneamente, e i ntei ros podem f aci lmente
ser converti dos para str i ngs e vi ce−versa.
17
i nt am_host name( i nt maq, char * nome)/ * Est a f uncao r et or na o nome da maqui na cuj o numer o e maq * /{ char nome2[ 20] , * env, envi a[ 20] , r ecebe[ 20] , * pr ecebe, st at ;
/ * nome=usada par a guar dar o nome da host , cont a=cont ador f or * / get host name( nome, 64) ;
/ * obt em o nome da host no l aco a segui r , pr ocur ar a pel a ocor r enci a do nome da host na l i st a de host s do si st ema r et or nando o numer o dest a* /
pr ecebe=r ecebe; spr i nt f ( envi a, " 6#%d#" , maq) ; env=envi a; st at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( r ecebe[ 0] ==’ 0’ )
r et ur n( −1) ; i f ( r ecebe[ 0] ==’ 1’ ) { spr i nt f ( nome, " %s" , r ecebe+2) ; r et ur n( 1) ; } i f ( r ecebe[ 0] ==’ 2’ ) { spr i nt f ( envi a, " 6#%d#" , maq) ; env=envi a; st at = cal l r pc ( r ecebe+2, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( r ecebe[ 0] ==’ 1’ ) { spr i nt f ( nome, " %s" , r ecebe+2) ; r et ur n( 1) ; } } r et ur n( −1) ;}
Figura 3.4− Função am_hostname()
Função am_myhost()
Uti l i zada para obter o número da máquina l ocal . Retorna o número desta
ou −1 se ocorreu erro (máquina não está no si stema). Para obter o número da
máquina l ocal , deve−se requi si tar o servi ço 5 ao daemon de sua própri a
máquina (env recebe ‘5’ na sua declaração), poi s el a “ sabe” o seu número, que
lhe é passado quando o am_addhost() é executado. A f unção am_str i nt() é
executada para ret i rar um i ntei ro da str i ng. Na f i gura 3.5 temos o código da
f unção am_myhost( ).
18
i nt am_myhost ( )/ * Est a f uncao r et or na o numer o da maqui na que o r equi si t ou ou −1 caso haj a al gum er r o ( est a maqui na nao t em pr ocesso daemon, por exempl o* /{ char nome[ 20] , * env=" 5" , r ecebe[ 50] , * pr ecebe, st at ;
/ * nome=usada par a guar dar o nome da host , cont a=cont ador f or * / i nt maq=0;
get host name( nome, 64) ; / * obt em o nome da host no l aco a segui r , pr ocur ar a pel a ocor r enci a do nome da host na l i st a de host s do si st ema r et or nando o numer o dest a* /
pr ecebe=r ecebe; st at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( r ecebe[ 0] ==’ 1’ ) { am_st r i nt ( r ecebe) ; maq=am_st r i nt ( r ecebe) ; r et ur n( maq) ; } r et ur n( −1) ;}
Figura 3.5− Função am_myhost()
Função am_mytid()
Esta f unção retorna o número pelo qual este processo é conheci do no
si stema (am_pid) podendo ser vi sta na f i gura 3.6. Uma vez que este número é
uma composi ção do número da máquina com o i denti f i cador do processo,
basta obter estas duas i nf ormações para gerar o am_pid do si stema.
O número da máquina pode ser obti do pela f unção am_myhost() e o
i denti f i cador do processo pela f unção do UNI X getpi d() . Um deslocamento à
esquerda de 12 posi ções no número da máquina, adi ci onado através de “ OU”
l ógi co ao i denti f i cador retornado pela getpi d() compõe o número do processo
no si stema (am_pid) .
19
l ong i nt am_myt i d( )/ * Obt em o numer o pel o qual o pr ocesso e conheci do no si st ema Est e numer o e uma comnposi cao bi nar i a descr i t a em am_st ar t pr oc* /{ l ong i nt maq; pi d_t pi d; maq=am_myhost ( ) ;
/ * ot em o numer o da host * / maq=maq<<12;
/ * compoe o numer o da maqui na * / pi d=get pi d( ) ;
/ * obt em o numer o do pr ocesso ( no SO) * / maq=maq| pi d; r et ur n( maq) ;}
Figura 3.6− Função am_mytid()
Função am_converte()
Esta f unção tem como objeti vo receber o número de uma máquina e o
número de um processo (seu i denti f i cador) e retornar o número am_pid deste
processo. Pode ser vi sta na f i gura 3.7.
Para gerar o am_pid (número pel o qual este processo será conheci do no
si stema) deve−se f azer um deslocamento à esquerda de 12 posi ções do número
da máquina. Para um número de máquina i gual a doi s, um deslocamento a
esquerda de 12 posi ções resul tará em 8192. Este número deverá ser
adi ci onado (através da operação ou l ógi co) ao i denti f i cador de processo no
si stema para f ormar o número am_pi d do processo, que é retornado pela
f unção.
l ong i nt conver t e ( i nt maq, l ong i nt t i d){ l ong i nt aux; aux=maq<<12; r et ur n( aux| t i d) ; }
Figura 3.7− Função am_converte()
20
Função am_strint()
Esta f unção reti ra uma parte numéri ca da str i ng data, conver te−a para
i ntei ro e devol ve à vari ável data o que sobrou. O número i ntei ro gerado é
retornado à f unção que o chamou. Na f i gura 3.8 temos seu código.
l ong i nt am_st r i nt ( char * am_dat a){ char * am_aux; l ong i nt am_t ot al =0; i nt am_si nal =1;
f or ( am_aux=am_dat a; ( * am_aux<’ 0’ ) | | ( * am_aux>’ 9’ ) ; am_aux++){ i f ( am_aux==NULL) r et ur n( −1) ; i f ( * am_aux==’ −’ ) am_si nal =−1;}
f or ( ; ( * am_aux>=’ 0’ ) &&( * am_aux<=’ 9’ ) ; am_aux++)am_t ot al =( am_t ot al * 10) + ( * am_aux−’ 0’ ) ;
spr i nt f ( am_dat a, " %s" , am_aux) ; r et ur n( am_t ot al * am_si nal ) ;}
Figura 3.8− Função am_strint()
Função am_addhost()
Tem o objeti vo de i nseri r uma nova máqui na no si stema, retornando o
seu número (apenas a apl i cação servi dora pode executar esta taref a). Esta
i nserção é f ei ta envi ando−se uma mensagem de teste e al gumas i nf ormações
ao amrud j á i nstal ado na máquina (a i nstal ação deste amrud deve ser f ei ta
expl i ci tamente) .
I ni ci almente é f ei ta uma veri f i cação para determinar se esta é a
apl i cação servi dora ou não. I sto é f ei to através da veri f i cação da var i ável
am_servi dor , que deve ser zero (esta vari ável é resetada quando am_ini t() f or
executado). Se não f or zero, si gni f i ca que esta apl i cação não é a servi dora,
por tanto não pode i nseri r máquinas no si stema e a f unção am_addhost()
retornará −1 si nal i zando um erro.
Caso sej a o servi dor, f az−se uma veri f i cação na l i sta de máquinas para
ver se j á não exi ste esta máquina no si stema, se exi sti r apenas retorna seu
21
número. Caso não exi sta, prepara−se a mensagem que será enviada ao amrud.
Esta mensagem é composta do número 1, i ndi cando tratar−se do servi ço 1,
seguido do número que esta máqui na receberá e o nome da máquina servi dora.
Desta f orma o amrud desti no saberá a quem reportar as chamadas de RPC.
Envia−se então esta str i ng ao amrud devendo este retornar 1, caso não haja
erro. Procede−se então ao cadastramento desta nova máqui na na l i sta de
máquinas do si stema. Após al terar esta l i sta, deve−se comuni car ao amrud
servi dor esta nova adesão, para que el e possa responder à pedidos como
am_hostname. I sto é real i zado si nal i zando o servi ço número 7, envi ando−se o
número e o nome da nova máquina ao amrud servi dor que no caso encontra−se
nesta máqui na, o que i ndi ca que a chamada de RPC deve ser f ei ta à máquina
retornada pela f unção gethostname(). Estas i nf ormações são empacotadas em
uma str i ng.
Após i sto, f i nalmente retorna−se o número da máquina i nseri da, ao
mesmo tempo em que i ncrementa−se o contador de máquinas.
O códi go completo desta f unção pode ser vi sto na f i gura 3.9.
22
i nt am_addhost ( char * maqui na){ / * Est e pr ogr ama f az uma chamada RPC par a o pr ogr ama AMRUD em execucao na maqui na r emot a. Se est e pr ogr ama est i ver at i vado el e r esponder a conf or me sol i c i t ado. Ret or na o numer o da host ou −1 se houve er r o * /
i nt st at , cont a; char r ecebe[ 2] , buf [ 30] , nome[ 20] ; char * envi a, * pr ecebe;
i f ( am_ser vi dor ) r et ur n( −1) ; / * Ver i f i ca se a maqui na j a nao est a i nser i da no si st ema * / f or ( cont a=0; cont a<am_nummaq; cont a++)
i f ( st r cmp( maqui na, am_l i st maq[ cont a] . nome) ==0) { am_l i st maq[ cont a] . st at us=1; r et ur n( am_l i st maq[ cont a] . numer o) ; }
pr ecebe=r ecebe; envi a=buf ; get host name( nome, 64) ; spr i nt f ( buf , " 1#%d#%s" , am_nummaq, nome) ; / * envi a o nome e o numer o de sua host par a a host i nser i da saber quem a cr i ou * / st at = cal l r pc ( maqui na, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &envi a, xdr _wr apst r i ng, &pr ecebe ) ; i f ( st at ! = 0 ) { f pr i nt f ( st der r , " ERRO: ’ amr ud’ nao est a execucao na maqui na
%s. \ n" , maqui na) ; r et ur n( −1) ; } el se i f ( st r cmp( " 1" , r ecebe) ==0)
/ * pr ocur a por uma posi cao di sponi vel na l i st a de host s, a posi caoe
consi der ada di sponi vel se st at us f or 0* /f or ( cont a=0; cont a<AM_MAXMAQ; cont a++) i f ( ! am_l i st maq[ cont a] . st at us)
{ st r cpy( am_l i st maq[ am_nummaq] . nome, maqui na) ;/ * cadast r a a nova host i nser i da na l i st a de host s * /
am_l i st maq[ cont a] . numer o=am_nummaq; am_l i st maq[ cont a] . st at us=1; spr i nt f ( buf , " 7#%d#%s" , am_nummaq, maqui na) ; get host name( nome, 64) ; envi a=buf ; st at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
xdr _wr apst r i ng, &envi a, xdr _wr apst r i ng, &pr ecebe ) ; i f ( st at ! = 0 ) { f pr i nt f ( st der r , " ERRO: ’ amr ud’ nao est a execucao na
maqui na %s. \ n" , nome) ; r et ur n( −1) ;
} r et ur n( am_nummaq++) ;
} r et ur n( −1) ;}
Figura 3.9− Função am_addhost()
23
Função am_startproc()
I ni ci a um processo na máquina especi f i cada e retorna o am_pid dele
(f i gura 3.10). Somente a apl i cação servi dora pode executar esta f unção.
Portanto, assi m como na f unção am_addhost() , deve−se pri mei ramente testar
se trata−se da apl i cação servi dora através da veri f i cação da vari ável
am_servi dor . Após i sto, se tratar−se da apl i cação servi dora, ver i f i ca−se a
exi stênci a da máquina especi f i cada consul tando−se a l i sta de máquinas. No
caso de não exi sti r, retorna−se uma mensagem de erro (−1) .
Deve−se então empacotar a str i ng a ser envi ada ao amrud da máquina
desti no. Esta str i ng é composta de duas partes: o caracter ‘ 4’ ( i ndi cando
tratar−se do servi ço 4) e o nome do processo, separados pelo caracter ‘#’ .
Executa−se então uma chamada RPC à máquina especi f i cada, envi ando−se a
stri ng empacotada.
Após a chamada RPC, veri f i ca−se o val or retornado. Se este f or “ −1” ,
si gni f i ca que não f oi possível i ni ci ar o processo (por moti vos que serão vi stos
na expl i cação deste servi ço) , caso contrári o a str i ng terá então o número do
processo cri ado, que no caso é o i denti f i cador gerado pelo SO na máquina
local . Faz−se então a conversão para am_pi d através da f unção am_conver te() .
Com o processo cri ado, seu am_pid gerado, f az−se então o
cadastramento deste processo na l i sta de processos exi stente, retornando−se o
número (am_pi d) deste à f unção que o executou.
24
l ong i nt am_st ar t pr oc( i nt maq, char * nomep){ / * I ni c i a o pr ocesso de nome nomep na maqui na maq, r et or na o numer o do pr ocesso cr i ado ou −1 se houve er r o. O numer o do pr ocesso e uma composi cao f ei t a a par t i r do numer o da host com o i p do pr ocesso da segui nt e f or ma: f az−se um shi f t l ef t do numer o da host em 12
posi coes como exempl o, se f or maqui na 1, expr esso como 0000 0000 0000 0001b, ao f azer esse shi f t , f i ca 0001 0000 0000 0000b, ou sej a, 4096 em deci mal , soma−se ent ao a est e numer o o i d do pr ocesso, por exempl o, pr ocesso 240, expr esso como 0000 0000 1111 0000b, r esol t ando em 4336 ( 0001 0000 1111 0000b) . Assi m sendo, como o l ong i nt e expr esso em 4 byt es, usamos o pr i mei r o byt e par a numer o da host ( t ot al de 256) e
os out r os t r es par a pr ocessos ( 4096) . Ver i f i cou−se que os i ps cr i ados pel o Li nux nao ul t r apassam est e l i mi t e. * / i nt st at , numer o=−1, cont a; char envi a[ 20] , r ecebe[ 5] , * pr ecebe, * env; l ong i nt pr oc;
i f ( am_ser vi dor ) r et ur n( −1) ; / * pr ocur a pel a host na l i st de host s * / f or ( cont a=0; cont a<AM_MAXMAQ; cont a++)
i f ( ( maq==am_l i st maq[ cont a] . numer o) &&( am_l i st maq[ cont a] . st at us) ) numer o=cont a;
i f ( numer o==−1){ f pr i nt f ( st der r , " numer o de maqui na nao exi st e\ n" ) ;r et ur n( −1) ;
} spr i nt f ( envi a, " 4#%s" , nomep) ;
/ * Ger a st r i ng a ser envi ada ao Deamon na host , 4 i ndi ca ser vi code am_st ar t pr oc segui do do nome do pr ocesso que deve sr cr i ado * / pr ecebe=r ecebe; env=envi a; st at = cal l r pc( am_l i st maq[ numer o] . nome, RUSERSPROG, RUSERSVERS,
RUSERSPROC_NUM, xdr _wr apst r i ng, &env,xdr _wr apst r i ng, &pr ecebe ) ;
i f ( st at ! = 0 ) { f pr i nt f ( st der r , " ERRO: ’ amr ud’ nao est a execucao na maqui na %s. \ n" ,
am_l i st maq[ numer o] . nome) ; r et ur n( −1) ; } i f ( st r cmp( r ecebe, " −1" ) ==0)
{ pr i nt f ( " Nao f oi possi vel i ni c i ar pr ocesso %s\ n" , nomep) ; r et ur n( −1) ; }
pr oc=am_st r i nt ( r ecebe) ; pr oc=am_conver t e( maq, pr oc) ; / * em r ecebe exi st e o numer o i d ( do SO) do pr ocesso cr i ado, obt em−se
agor a o numer o do pr ocesso no si st ema * / f or ( cont a=0; cont a<AM_MAXPROC; cont a++)
/ * Cadast r a o pr ocesso cr i ado na l i st a de pr ocessos * /i f ( ! am_l i st pr oc[ cont a] . st at us) { am_l i st pr oc[ cont a] . st at us=1; st r cpy( am_l i st pr oc[ cont a] . nome, nomep) ; am_l i st pr oc[ cont a] . npr oc=pr oc; am_l i st pr oc[ cont a] . nmaq=maq; r et ur n( pr oc) ; }
r et ur n( −1) ;}
Figura 3.10− Função am_startproc()
25
Função am_send()
Envia uma mensagem msg ao processo proc, ambos passados como
parâmetros. Seu código pode ser vi sto na f i gura 3.11.
Como este processo pode estar em qualquer máqui na parti ci pante do
si stema, não é possível usar as rot i nas padrões de troca de mensagens entre
processos j á exi stentes no UNI X . Portanto, cada amrud é responsável pel a
buf eri zação das mensagens de seus f i l hos, devendo as mensagens ser
endereçadas ao amrud da máquina à qual o processo dest i no é f i l ho.
Começa−se descobri ndo qual é a máquina à qual pertence este processo.
Um deslocamento à di rei ta de 12 posi ções na vari ável proc f ornece o número
da máquina e um “ E” l ógi co com 4095 o i denti f i cador do processo.
Prepara−se então a str i ng que deverá ser envi ada ao amrud. Ela é
composta do caracter ‘2’ , i ndi cando o servi ço de send, mai s o am_pid do
processo que envia a mensagem, obti do pel a f unção am_myti d() o
i denti f i cador do processo desti no, e pela mensagem propri amente di ta. Todos
estes parâmetros são empacotados na str i ng envia, e separados um do outro
pelo caracter ’#’ .
Procede−se então à chamada de RPC à máquina onde se encontra o
processo desti no, cuj o nome f oi anteri ormente obti do pel a f unção
am_hostname() e ver i f i ca−se o val or retornado. Se este f or “ −1” , si gni f i ca que
não exi ste o processo desti no, caso contrári o a mensagem f oi envi ada com
sucesso e a f unção retornará 1.
26
i nt am_send( l ong i nt pr oc, char * msg){ / * Envi a uma mensagem par a o pr ocesso especi f i cado * /
i nt st at , cont a, numer o=−1; char envi a[ 100] , nome[ 30] ; char r ecebe[ 20] , * pr ecebe, * env; numer o=pr oc>>12; st at =am_host name( numer o, nome) ; i f ( st at ==−1)
r et ur n( −1) ; pr oc=pr oc&4095;
/ * Obt em o r eal numer o do pr ocesso, seu i d, o numer o pel o qual el e e conheci do pel o SO de sua maqui na * /
spr i nt f ( envi a, " 2#%d#%d#%s" , am_myt i d( ) , pr oc, msg) ;/ * Ger a a st r i ng a ser envi ada ao Daemon da maqui na que possue est e pr ocesso. O numer o 2 i ndi ca que t r at a−se do ser vi co 2. Segue−se o numer o do pr ocesso que execut ou o ser vi co e o numer o do pr ocesso par a quem desej a−se envi ar a mensagem. * /
pr ecebe=r ecebe; env=envi a; st at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( st at ! = 0 ) { f pr i nt f ( st der r , " ERRO: ’ amr ud’ nao est a execucao na maqui na %s. \ n" ,
nome) ; r et ur n( −1) ; } i f ( st r cmp( r ecebe, " −1" ) ==0)
{ pr i nt f ( " Nao f oi possi vel achar pr ocesso %s\ n" , pr oc) ;r et ur n( −1) ;
} r et ur n( 1) ;}
Figura 3.11− Função am_send()
Função am_receive()
Recebe uma mensagem do processo especi f i cado (proc), retornando seu
número. Se o parâmetro passado em proc f or −1, am_recei ve receberá
mensagem de qualquer processo. V eja código na f i gura 3.12.
Em pri mei ro l ugar gera−se a str i ng que será enviada ao amrud l ocal
( i sto porque cada amrud gerencia as mensagens dos processos da sua
máquina). Esta str i ng começa com o i denti f i cador do servi ço, que no caso é
‘3’ ( recei ve), segui da do número i dent i f i cador do processo que desej a receber
a mensagem e do am_pid do processo de quem se deseja receber a mensagem.
27
Envia−se esta str i ng ao amrud l ocal conti nuamente até que exi sta uma
mensagem para este processo (espera ocupada).
Depoi s que amrud retornar a str i ng, procede−se à conversão dos
parâmetros, poi s esta str i ng contém o número do processo que enviou a
mensagem seguido da mensagem enviada.
28
i nt am_r ecei ve( i nt pr oc, char * msg){ / * Recebe uma mensagem do pr ocesso especi f i cado, Se pr oc f or −1, i ndi ca que a mensagem pode ser de qual quer pr ocesso * / i nt st at , cont a, numer o=−1; char envi a[ 20] , r ecebe[ 100] , nome[ 20] , * pr ecebe, * env;
spr i nt f ( envi a, " 3#%d#%d#" , get pi d( ) , pr oc) ;/ * Not e que aqui , ao i nves de envi ar o numer o do pr ocesso no si st ema, envi a−se o seu i d apenas. I sso por que quem f ar a o t r at ament o de mensagens e o Daemon dest a maqui na ( est a pr opr i a que execut ou o am_r ecei ve) , e est e daemon
conhece seus " f i l hos" pel o seu i d.* /
pr ecebe=r ecebe; env=envi a; get host name( nome, 64) ;
/ * O buf f er de msgs e cont r ol ado pel o Daemon de cada host , cada Daemon cont r ol a as msgs de seus f i l hos. Por i sso est a chamada de RPC e par a a pr opr i a host que execut ou est a f uncao.* /
f or ( ; r ecebe[ 0] ! =’ 1’ ; ) { st at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( st at ! = 0 ) { f pr i nt f ( st der r , " ERRO: ’ amr ud’ nao est a execucao nest a maqui na
\ n" ) ; r et ur n( −1) ; } } am_st r i nt ( r ecebe) ; numer o=am_st r i nt ( r ecebe) ; spr i nt f ( msg, " %s" , r ecebe+1) ; r et ur n( numer o) ;}
Figura 3.12− Função am_receive()
3.2Programa Daemon (amr ud.c)
Este programa deve ser anteri ormente i nstal ado em cada máquina que
part i ci pará do si stema. A tri bui−se o nome de amrud a todo o daemon do
si stema rodando nas máquinas i nseri das por am_addhost() e chama−se de
amrud servi dor o daemon da máqui na servi dora, ou sej a, aquela responsável
pela i nstal ação do si stema e que executou a f unção am_ini t( ) .
Cada amrud é responsável em atender as chamadas RPC desti nadas à sua
máquina, bem como manter e gerenciar as mensagens desti nadas à seus f i l hos.
29
Estruturas e var iáveis globais
Amrud cri a as mesmas duas estruturas para manipular processos e
máquinas i nstal adas exi stente na bi bl i oteca AM_L I B, porém com algumas
inf ormações di f erentes. Sua def i ni ção encontra−se na f i gura 3.13.
Na estrutura AM _L I STHOST não exi ste o campo status e na
AM_L I STPROC não exi ste o campo nome e nmaq, e exi stem outros três
campos: msg, ori gem e espera.
O campo msg é um vetor de caracteres bi−di reci onal de AM _MSGMAX
posi ções, cada uma com A M_TAM MSG caracteres. Este campo serve como
buf f er de mensagens recebidas, podendo, portanto, armazenar até
AM_MSGMAX mensagens para cada processo, cada mensagem podendo
conter AM_TAMMSG caracteres.
O campo or i gem é um vetor de i ntei ros de AM_MSGMAX posi ções.
Nel e é armazenado o número am_pid de cada processo que enviou uma
mensagem. É mant i da uma rel ação entre a posi ção do vetor or i gem, com a
posi ção do vetor msg, ou sej a, o processo de am_pi d ori gem[ 0] gravou sua
mensagem no campo msg[ 0] .
O campo espera armazena o am_pid do processo de quem se espera uma
mensagem, e também serve para testar a di sponibi l i dade do regi stro, i sto é, se
espera t i ver −3, i ndi ca que todo aquel e regi stro não pertence ai nda à nenhum
processo, podendo ser usado quando um servi ço de star tproc f or requi si tado;
se possui r −2, este regi stro j á pertence à um processo e este no momento não
aguarda mensagens. Se, no entanto possui r −1, o processo espera qualquer
mensagem. Outro val or i ndi ca o am_pi d do processo de quem se aguarda
mensagem.
30
O campo status tem uma f unção di f erente que na AM_L I B. Aqui el e
serve apenas para contar o número de mensagens exi stentes no momento para
aquel e processo.
31
st r uct AM_LI STHOST{char nome[ 20] ;i nt numer o;} am_l i st maq[ AM_MAXPROC] ;/ * Li st a das host s par t i c i pant es do si st ema nome= nome da host ( ex. ver di ) , −1 r egi st r o di sponi vel numer o= numer o pel o qual ser a r econheci da no si st ema * /
st r uct AM_LI STPROC {l ong i nt npr oc;char st at us;char msg[ AM_MSGMAX] [ AM_TAMMSG] ;i nt or i gem[ AM_MSGMAX] ;i nt esper a;} am_l i st pr oc[ AM_MAXPROC] ;/ * Li st a de pr ocessos. Di f er e−se um pouco da l i st a exi st ent e na bi bl i ot eca, pel o f at o de aqui nao exi st i r o nome do pr ocesso,
npr oc e o i d del e do SO e t er campos par a buf er i zar as msg.
npr oc=numer o do pr ocesso msg= buf f er s de mensagem pendent es, cada pr ocesso pode t er at e
AM_MSGMAX mensagens esper ando, cada uma de at e AM_TAMMSG car act er es.
st at us= 0= sem msg par a el e, >0=numer o de msg r ecebi das esper a= −3 campo di sponi vel , −2 ocupado−pr ocesso nao esper a
msg, −1 ocupado, pr ocesso esper a msg de qual quer pr o− cesso, >=0 = numer o do pr ocesso de quem est a esper ando
uma mensagem. or i gem=pr ocessos que envi ar am mensagem, −1=di sponi vel .* /
char am_mi nhahost =0;/ * se =0, est e e o ser vi dor , >0 desi gna o numer o dest a host * /
char am_ser ver name[ 30] ;/ * nome da host ser vi dor a * /
Figura 3.13− Estruturas e Variáveis do amrud
Exi stem apenas quatro vari ávei s gl obai s: am_minhahost, que armazena o
número da sua própri a máquina; a str i ng am_servername, que guarda o nome
da máquina que possui o amrud servi dor; am_l i stmaq, uma estrutura que
armazena i nf ormações sobre as máquinas i nseri das e a vari ável am_l i stpr oc
que armazena i nf ormações dos processos i nseri dos no si stema.
Função am_msgrec()
A f unção am_msgrec() é responsável pel o tratamento i nterno de
mensagens. Veri f i ca i ni ci almente se exi ste no buf f er al guma mensagem do
pid_msg para o pi d_req. Se exi sti r, empacota−a na vari ável msg passada por
parâmetro e retorna 1. Senão, retorna −1.
32
Primei ramente percorre−se a l i sta de processos à procura do processo
número pid_req. Tão l ogo a mesma seja l ocal i zada, f az−se um teste com a
vari ável status, poi s se esta f or zero, não exi stem mensagens para este
processo e j á se pode retornar −1.
De posse da posi ção no regi stro pertencente ao processo que requi si tou
ao pedido, procura−se pela mensagem vi nda do processo pi d_msg no buf f er.
Se pi d_msg f or −1, então pega−se a primei ra mensagem buf eri zada. Após
gerar a str i ng de retorno (j á empacotada com o i denti f i cador de sucesso, 1, o
i denti f i cador do processo que enviou a mensagem e a mensagem enviada)
deve−se aj ustar os dados no buf f er, ou sej a, decrementar a var i ável status
(contadora de mensagens) e l impar o campo de onde el a f oi extraída.
Observe que o número do processo que enviou a mensagem é retornado
ao processo que a requi si tou, i sto porque caso pi d_msg tenha si do −1, o
processo pi d_req terá meios de saber de quem realmente vei o a mensagem.
33
i nt am_msgr ec( i nt am_pi dr eq, i nt am_pi dmsg, char * am_msg){ / * Ser vi co de r ecebi ment o de mensagens, se exi st i r mensagem de am_pi dmsg par a am_pi dr eq, est a ser a ar mazenada em am_msg e a f uncao r et or na 1, senao a f uncao r et or na −1 ( o ser vi co de send e r ecei ve e si ncr ono, mas a deci sao de por o pr ocesso par a dor mi r e do am_r ecei ve e nao do
Daemon est e ul t i mo apenas i nf or ma ao am_r ecei ve pel o r et or no do RPC que nao exi st e a am_msg r equi si t ada) . Se am_pi dmsg f or −1, i ndi ca r eceber msg de qual quer pr ocesso. * /
i nt cont a, cont a2;
/ * pr ocur a a posi cao do buf f er per t encent e ao pr ocesso que r equi si t ou o pedi do de r ecei ve * / f or ( cont a=0; cont a<AM_MAXPROC; cont a++) i f ( am_l i st pr oc[ cont a] . npr oc==am_pi dr eq)
{ i f ( am_l i st pr oc[ cont a] . st at us==0)/ * se st at us e zer o, nao ha msg par a est e pr ocesso * /r et ur n( −1) ;
i f ( am_pi dmsg==−1) / * −1 i ndi ca r eceber de qual quer pr ocesso * / f or ( cont a2=0; cont a2<AM_MSGMAX; cont a2++)
i f ( am_l i st pr oc[ cont a] . or i gem[ cont a2] ! =−1) { spr i nt f ( am_msg, " 1#%d#%s" , am_l i st pr oc[ cont a] .
or i gem[ cont a2] , am_l i st pr oc[ cont a] . msg[ cont a2] ) ;/ * mont a a st r i ng de r et or no, 1 i ndi ca sucesso, segue o numer o do pr ocesso qeu envi ou a msg ( ut i l caso am_pi dmsg f osse −1) e em segui da a mensagem * /
am_l i st pr oc[ cont a] . or i gem[ cont a2] =−1; / * di sponi bi l i za a posi cao do buf f er * /
am_l i st pr oc[ cont a] . st at us−−; r et ur n( 1) ; }
f or ( cont a2=0; cont a2<AM_MSGMAX; cont a2++) i f ( am_l i st pr oc[ cont a] . or i gem[ cont a2] ==am_pi dmsg)
{ spr i nt f ( am_msg, " 1#%d#%s" , am_pi dmsg, am_l i st pr oc[ cont a] .
msg[ cont a2] ) ; am_l i st pr oc[ cont a] . or i gem[ cont a2] =−1; am_l i st pr oc[ cont a] . st at us−−; r et ur n( 1) ;}
} r et ur n( −1) ;}
Figura 3.14− Função am_msgrec()
Função am_msgsend()
Esta f unção armazena no buf f er uma mensagem msg do processo ori gem
para o processo desti no. Para processo ori gem deve−se f ornecer o val or de
seu am_pid e para o desti no apenas o val or de seu i denti f i cador. I sto porque a
manipul ação de mensagens é f ei ta por cada amrud, sendo que el e conhece seus
f i l hos pelo i denti f i cador de processo gerado pelo si stema operaci onal .
34
Primei ramente f az−se uma busca na l i sta de máquinas à procura do
regi stro pertencente ao processo desti no. A pós achar este regi stro, procura−se
uma posi ção l i vre no buf f er (campo ori gem e msg). E cadastra−se a
mensagem, buf er i zando−a em msg, al terando o campo ori gem para que
contenha o am_pid do processo ori gem e i ncrementando a vari ável status.
i nt am_msgsend( i nt or i gem, i nt dest i no, char * am_msg){ / * Col oca mensagem no buf f er r et or na 1 se sucesso, ou −1 se er r o
( buf f er chei o, por exempl o * /
i nt cont a, cont a2;
f or ( cont a=0; cont a<AM_MAXPROC; cont a++) / * pr ocur a posi cao de buf f er do pr ocesso dest i no * / i f ( am_l i st pr oc[ cont a] . npr oc==dest i no)
/ * pr ocur a no buf f er espaco di sponi vel par a ar mazenar a msg * /f or ( cont a2=0; cont a2<AM_MSGMAX; cont a2++) { i f ( am_l i st pr oc[ cont a] . or i gem[ cont a2] ==−1) { / * buf er i za a mensagem * /
am_l i st pr oc[ cont a] . or i gem[ cont a2] =or i gem;am_l i st pr oc[ cont a] . st at us=am_l i st pr oc[ cont a] . st at us++;st r cpy( am_l i st pr oc[ cont a] . msg[ cont a2] , am_msg) ;r et ur n( 1) ;}
} r et ur n( −1) ;}
Figura 3.15− Função am_msgsend()
Função am_strint()
Função i dênti ca à am_str i nt() da bi bl i oteca am_l i b. Ret i ra um número
intei ro de uma str i ng.
Função **am_server()
A f unção am_server ( ) é a f unção mai s importante do si stema. É el a que
atende as chamadas de RPC e executa os servi ços requi si tados retornando um
apontador de caracteres. Of erece oi to servi ços bási cos que serão vi stos
i ndi vi dual mente. El es são sel eci onados através de uma sel eção (do t i po
35
swi tch−case) na qual é testado o primei ro caracter do parâmetro passado na
vari ável i ndata.
char * * am_ser ver ( char * * i ndat a){ / * Pr ogr ama r esponsavel pel o at endi ment o das chamadas de RPC, at r aves das st r i ngs envi adas pel as chamadas, det er mi na o t i po de ser vi co r equi zi t ado e exet ua−o * / st at i c char dat a[ AM_TAMMSG] ; st at i c char * pd, * r d; i nt st at , pi d, am_pi dr eq, am_pi dmsg; r d=* i ndat a;
swi t ch ( * * i ndat a) { case . . .
}}
Figura 3.16− Função **am_server()
Serviço am_addhost
Este servi ço só pode ser requi si tado pela apl i cação servi dora, e serve
para testar se o amrud está devi damente i nstal ado nesta máqui na, e para
i nf ormá−l o que está parti ci pando do si stema, bem como passar−lhe o seu
número e o nome da máquina servi dora. Se o amrud est i ver i nstal ado, deve
apenas retornar a str i ng “ 1” à apl i cação servi dora.
case ’ 1’ : / * Test e, usado pel o addhost * /am_st r i nt ( r d) ;am_mi nhahost =( char ) am_st r i nt ( r d) ;spr i nt f ( am_ser ver name, " %s" , r d+1) ;
dat a[ 0] =’ 1’ ;dat a[ 1] =’ \ 0’ ;br eak;
Figura 3.17− Serviço am_addhost
Serviço am_send
Este servi ço obtém, através de duas chamadas à f unção am_str i nt() , o
número dos processos envol vi dos no servi ço, e os envia à f unção
am_msgsend() . Prepara a str i ng data com a i nf ormação “ 1” para retorná−la ao
processo servi dor .
36
case ’ 2’ : / * Send * /dat a[ 0] =’ 1’ ;dat a[ 1] =’ \ 0’ ;am_st r i nt ( r d) ;am_pi dr eq=am_st r i nt ( r d) ;am_pi dmsg=am_st r i nt ( r d) ;am_msgsend( am_pi dr eq, am_pi dmsg, r d+1) ;r eak;
Figura 3.18− Serviço am_send
Serviço am_receive
Este servi ço, da mesma f orma que o send, apenas obtém o número dos
processos envol vi dos e os passa à f unção am_msgrec(). Se esta f unção achar a
mensagem sol i ci tada, a str i ng data j á estará f ormatada para envi o ao processo
servi dor, caso contrári o, será preci so f ormatá−la si nal i zando o erro, o que é
f ei to pela f unção spr i nt f .
case ’ 3’ : / * Recei ve * /am_st r i nt ( r d) ;am_pi dr eq=am_st r i nt ( r d) ;am_pi dmsg=am_st r i nt ( r d) ;st at =am_msgr ec( am_pi dr eq, am_pi dmsg, dat a) ;i f ( st at ==−1)
{ dat a[ 0] =’ 0’ ; dat a[ 1] =’ \ 0’ ;}
br eak;
Figura 3.19− Serviço am_receive
Serviço am_star tproc
Este servi ço é responsável pel a i ni ci al i zação de processos. Para i sto,
f az−se uso de duas f unções do UNI X . A primei ra é a f unção fork(), que cri a
uma nova cópia do processo que a executou. Assim, ao executar−se fork() ,
temos duas cópias do processo amrud, uma considerada pai e a outra f i l ho. As
duas cópias segui rão sua execução normalmente a parti r deste ponto, uma
independente da outra (se o pai morrer, o f i l ho também morre) .
A f unção fork() retorna o número do processo f i l ho ao pai e zero ao
f i l ho. Com i sto é possível real i zar um teste para determi nar quem é o f i l ho e
37
quem é o pai . Se pi d f or 0, a negação em pid f ará com que a sentença seja
verdadei ra, portanto apenas o f i l ho executará o comando após o i f e apenas o
pai executará os comandos do el se. O f i l ho executará a chamada de si stema
execv() .
A f unção execv() executa o programa cujo nome é passado por
parâmetro e subst i tui a imagem do processo que o executou pela imagem do
processo que deseja−se executar. Assim sendo, o amrud f i l ho não conti nuará a
executar depoi s de chamar a f unção execv() terminado quando o processo
cri ado terminar. O segundo parâmetro de execv() é os parâmetros passados à
f unção que se deseja cri ar, como se t i vessem si do passados na l i nha de
comando.
Após ser i ni ci al i zado o processo desejado, o mesmo é cadastrado (pelo
amrud pai , j á que o f i l ho anteri ormente cri ado não chegará a executar esta
parte do códi go) na l i sta de processos do amrud. Esta l i sta, como j á f oi di to
anteri ormente, guarda apenas dados dos processos f i l hos de cada amrud. Em
seguida, uma str i ng de retorno é f ormatada para si nal i zar ao processo servi dor
seu sucesso na i ni ci al i zação. Esta si nal i zação é o número i denti f i cador do
processo cri ado ou ‘−1’ se houve erro.
38
case ’ 4’ : / * St ar t pr oc * /pi d=f or k( ) ;i f ( ! pi d) {
execv( &r d[ 2] , NULL) ; exi t ( 0) ; }
spr i nt f ( dat a, " %d" , pi d) ;f or ( st at =0; st at <AM_MAXPROC; st at ++)i f ( am_l i st pr oc[ st at ] . esper a==−3)
{ am_l i st pr oc[ st at ] . esper a=−2; am_l i st pr oc[ st at ] . npr oc=pi d; f or ( pi d=0; pi d<AM_MSGMAX; pi d++)
am_l i st pr oc[ st at ] . or i gem[ pi d] =−1; st at =AM_MAXPROC+1;}
i f ( st at ==AM_MAXPROC){ spr i nt f ( dat a, " %d" , −1) ; br eak;}
br eak;
Figura 3.20− Serviço am_startproc
Serviço am_myhost
Este servi ço é bastante simples e út i l , el e apenas retorna o número da
máquina l ocal .
case ’ 5’ : / * Myhost * /spr i nt f ( dat a, " 1#%d" , am_mi nhahost ) ;br eak;
Figura 3.21− Serviço am_myhost
Serviço am_hostname
Este servi ço f ornece, à quem o requi si tou, o nome da máqui na cuj o
número é passado por parâmetro. Entretanto, apenas o amrud servi dor mantém
o cadastro das máquinas parti ci pantes do si stema, e se o amrud em questão
não f or o servi dor, el e não será capaz de determinar o nome da máquina que
se pede.
Deve−se, por tando, f azer um teste para saber se este amrud é o servi dor ,
i sto é f ei to pela var i ável am_minhahost que será zero se este f or o servi dor.
Caso sej a, f ornece−se o nome da máquina requi si tada ou “ 0” se esta não
exi sti r .
39
Porém, se este não f or o amrud servi dor, el e não terá condi ções de
ef etuar a taref a pedida, mas também não pode si nal i zar que não exi ste tal
máquina. Neste caso, então, o amrud si nal i zará com o caracter ‘ 2’ seguido do
nome da máquina que contém o amrud servi dor , devendo o processo que
requi si tou este servi ço vol tar a f azê−lo, só que desta vez ao amrud servi dor .
case ’ 6’ : / * am_host name * /am_st r i nt ( r d) ;pi d=am_st r i nt ( r d) ;spr i nt f ( dat a, " 0" ) ;i f ( am_mi nhahost ==0) { f or ( st at =0; st at <AM_MAXPROC; st at ++)
i f ( am_l i st maq[ st at ] . numer o==pi d) spr i nt f ( dat a, " 1#%s" , am_l i st maq[ st at ] . nome) ;}
el se spr i nt f ( dat a, " 2#%s" , am_ser ver name) ;br eak;
Figura 3.22− Serviço am_hostname
Serviço cadastr a
Este servi ço é requi si tado apenas pelo processo servi dor toda vez que
uma f unção am_addhost() é executada. Tem como obj eti vo i nf ormar ao amrud
servi dor que uma nova máqui na f oi i nseri da, bem como o número e o nome
desta. Se este cadastramento não f osse f ei to, o amrud servi dor não teri a
condi ções de responder aos servi ços de am_hostname porque o regi stro das
máquinas exi stentes estari a apenas no processo servi dor, i nati ngível por
chamadas de RPC.
case ’ 7’ : / * cadast r a nova host * /am_st r i nt ( r d) ;pi d=am_st r i nt ( r d) ;f or ( st at =0; st at <AM_MAXPROC; st at ++) i f ( am_l i st maq[ st at ] . numer o==−1)
{ am_l i st maq[ st at ] . numer o=pi d; spr i nt f ( am_l i st maq[ st at ] . nome, " %s" , r d+1) ; st at =AM_MAXPROC; spr i nt f ( dat a, " %s" , " 1" ) ;}
br eak;
Figura 3.23− Serviço cadastra
40
Serviço registr a
Este servi ço é requi si tado apenas pel o processo servi dor uma úni ca vez,
durante o am_ini t() . Tem como objeti vo i nf ormar ao amrud servi dor o
i denti f i cador do processo servi dor, j á que o amrud não o conhece por não
tratar−se de seu f i l ho. Se este cadastramento não f osse f ei to, o processo
servi dor não poderi a receber mensagens, poi s o amrud servi dor não teri a nem
ao menos espaço no buf f er reservado para el e e responderi a com erro à
qualquer pedi do de envio de mensagem desti nado ao processo servi dor .
case ’ 8’ : / * r egi st r a o pr ocesso ser vi dor * /am_st r i nt ( r d) ;pi d=am_st r i nt ( r d) ;am_l i st pr oc[ 0] . esper a=−2;am_l i st pr oc[ 0] . npr oc=pi d;f or ( pi d=0; pi d<AM_MSGMAX; pi d++)
am_l i st pr oc[ 0] . or i gem[ pi d] =−1;br eak;
Figura 3.24− Serviço registra
Após este servi ço, termi na o comando swi tch−case. Por tanto, a str i ng
gerada em algum ponto anteri or da execução contém os val ores que devem ser
retornados ao processo que executou a chamada. Retorna−se, por f im, esta
str i ng.
Função main()
A f unção pri nci pal do amrud f az a i ni ci al i zação das vari ávei s usadas
pel o amrud, o regi stro da f unção am_server ( ) no RPC e a i nstal ação do RPC.
Seu código pode ser vi sto na f i gura 3.25.
A f unção regi ster rpc() [ SCH 96] recebe sei s parâmetros, sendo que três
del es f oram manti dos em def aul t por não serem rel evantes neste trabalho
(RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM ). O quarto é o
41
endereço da f unção que atenderá as chamadas de RPC, que no caso é a f unção
am_server ( ) .
O quinto e o sexto parâmetros i ndi cam os ti pos de dados que o processo
receberá e que envi ará, que no caso é wrapstri ng para os doi s.
Em seguida é chamada a f unção svc_run() do pacote RPC. Esta f unção
instal a o processo am_server ( ) como responsável pel o atendimento das
chamadas e não retorna mai s. Se esta f unção retornar houve al gum erro.
mai n( ){ i nt aux=0; f or ( aux=0; aux<AM_MAXPROC; aux++)
/ * i ni c i al i za campos da l i st a de am_l i st pr oc * /{ am_l i st pr oc[ aux] . esper a=−3; am_l i st pr oc[ aux] . st at us=0; am_l i st maq[ aux] . numer o=−1;}
r egi st er r pc( RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, am_ser ver , xdr _wr apst r i ng, xdr _wr apst r i ng) ; svc_r un( ) ; f pr i nt f ( st der r , " Er r o: svc_r un r et or nou! \ n" ) ; exi t ( 1) ;}
Figura 3.25− Função main()
42
4EXEMPLOS DE UTILIZAÇÃO
São vári os os exempl os que podem ser uti l i zados neste si stema. Mui tos
dos i mplementados em PVM podem, com f aci l i dade, ser mi grados para este
ambiente. Não todos, porque cer tamente o PVM é bem mai s completo e, em
alguns pontos, mai s ef i ci ente que este ambiente. Substi tuí−l o nunca f oi a
pretensão deste t rabalho. Neste capí tul o serão apresentados doi s exemplos:
desempenho e o cl ássi co f i l ósofos j antadores.
4.1Desempenho de tr oca de mensagens
Este exemplo consi ste de doi s processos cuj a f i nal i dade é testar o tempo
necessári o ao envio e recebimento de mensagens no si stema. Chamaremos o
primei ro processo de “ desempenho” e o segundo de “ responde” .
A f unção do processo desempenho é cri ar no ambiente o processo
responde, envi ar uma mensagem qualquer a este e receber uma outra de vol ta,
contabi l i zando o tempo l evado. I sto será f ei to n vezes, e, ao f i nal das
i terações, será cal cul ado o tempo médio, mínimo e máximo do envio das
mensagens.
Já o processo “ responde” terá a úni ca f unção de responder à todas as
mensagens recebidas do desempenho. O código do responde pode ser vi sto na
f i gura 4.1.
Note que não exi ste complexi dade al guma neste processo, el e apenas
recebe uma mensagem qualquer e a envia de vol ta ao mesmo processo que a
enviou, f az i sso até que receba a mensagem ‘0’ .
/ * Est e pr ocesso r ecebe uma mensagem e a envi a de vol t a * /
#i ncl ude "am_lib.c"
mai n( ){ l ong i nt t i d; char msg[ 100] ;
t i d=am_receive( −1, msg) ; f or ( ; msg[ 1] ! =’ 0’ ; )
{f pr i nt f ( st der r , " Recebeu msg %s do pr ocesso %d\ n" , msg, t i d) ;am_send( t i d, msg) ;t i d=am_receive( −1, msg) ;}
}
Figura 4.1− Exemplo responde
O processo desempenho é um pouco mai s compl exo e seu código pode
ser vi sto na f i gura 4.2.
Primei ramente i ni ci al i za−se o ambiente através de f unção am_ini t( ) , que
retornará o número da máquina servi dora ou −1 se houve erro (o amrud deve
ser i nstal ado previ amente pel o usuár i o). I ni ci al i za−se então o processo
“ responde” na máquina servi dora, cuj o número será guardado na vari ável p1.
Dentro de um l aço de NMAX posi ções (def i ni do com constante), f az−se
vári os envios e recebimentos, sempre guardando o tempo l evado (deve−se ter
cui dado ao def i ni r a constante NMAX, poi s um número excessi vo de i terações
pode causar sobrecarga na vari ável total ) .
Para obter o tempo, f az−se uso da f unção gettimeofday() , decl arada na
bibl i oteca t ime.h. El a al tera duas estruturas também def i ni das nesta
bibl i oteca, uma é usada para armazenar o tempo atual (struct t imeval ) e a
outra não será uti l i zada pela apl i cação (struct t imezone). Na estrutura
timeval , exi stem doi s regi stros: tv_sec e tv_usec, que armazenam,
respecti vamente o tempo em segundos e mi crossegundos. Foram usadas duas
vari ávei s do ti po desta estrutura para guardar o tempo. Com a primei ra, tpi ,
guarda−se o tempo i ni ci al e com a segunda, tpf , o f i nal .
44
Após o término da i teração, dimi nuí−se o val or f i nal em segundos
(tpf .u_sec) do val or i ni ci al em segundos ( tpi .tv_sec) armazenado este val or no
própri o campo tvf .tv_sec. Segue−se o mesmo procedimento com os
microssegundos, armazenado o resul tado em tpf .tv_usec. Converte−se, em
seguida, o val or em segundos para mi crossegundos mul ti pl i cando−o por
1.000.000 e o somando este val or ao val or em microssegundos tem−se o val or
total da i teração, tempo de i da e vol ta da mensagem, por i sso é necessári o
di vi di r este val or por doi s para obter o tempo da transmissão.
Acumula−se o val or obti do na vari ável total , e veri f i ca−se este tempo
obti do para saber se corresponde ao tempo mínimo ou máximo até então.
Procede−se então à uma nova i teração.
45
/ * Pr ocesso desempenho * /
#i ncl ude " am_lib.c"#i ncl ude <sys/ t i me. h>#def i ne NMAX 10
mai n( ){ char msg[ 100] ; unsi gned char n; st r uct t i meval t pi , t pf ; st r uct t i mezone t zpi , t zpf ; unsi gned l ong t empo, t mi n=0, t max=0, t ot al ; i nt m1, m2, p1, p2, t i d;
m1=am_init( ) ; i f ( m1==−1)
exi t ( 0) ; m1=am_addhost( " ver di " ) ; i f ( m1==−1)
exi t ( 0) ; m2=am_addhost( " vi val di " ) ; i f ( m2==−1)
exi t ( 0) ; p1=am_startproc( m2, " r esponde" ) ; i f ( p1==−1)
exi t ( 0) ;f or ( n=0; n<NMAX; n++)
{ spr i nt f ( msg, " %s" , " Ol a" ) ; get t i meof day( &t pi , &t zpi ) ; am_send( p1, msg) ; am_receive( p1, msg) ; get t i meof day( &t pf , &t zpf ) ; t pf . t v_sec= t pf . t v_sec−t pi . t v_sec; t pf . t v_usec= t pf . t v_usec−t pi . t v_usec; t empo=( ( t pf . t v_sec* 1000000) +t pf . t v_usec) / 2;
f pr i nt f ( st der r , " Tempo da i t er acao %2d f oi %u\ n" , n, t empo) ; t ot al =t ot al +t empo; i f ( t max==0)
t max=t mi n=t empo; el se
{ i f ( t empo<t mi n) t mi n=t empo;
i f ( t empo>t max) t max=t empo;
}}
am_send( p1, ” 000” ) ; t ot al =t ot al −t mi n−t max; n=NMAX−2; t ot al =t ot al / n; f pr i nt f ( st der r , " Tempo medi o f oi de %u\ n" , t ot al ) ; f pr i nt f ( st der r , " Tempo mi ni mo f oi de %u\ n" , t mi n) ; f pr i nt f ( st der r , " Tempo maxi mo f oi de %u\ n" , t max) ;}
Figura 4.2− Exemplo desempenho
No f i nal das i terações, reti ra−se o tempo máximo e o tempo mínimo da
vari ável total ( i sso porque os extremos podem i nf l uenci ar negat i vamente a
média) e di vi de−se o total por NMAX−2 (j á que f oram reti rados o resul tado
de duas i terações) .
46
I mprime−se então o resul tado médio, míni mo e máximo.
4.2Filósofos Jantadores
Cinco f i l ósof os estão reunidos em uma mesa para j antar, di spondo de
cinco garf os. Cada um preci sa de doi s garf os para j antar. Como não há garf os
suf i ci entes (seri am necessári os 10 gar f os), el es di vi dem os garf os entre si , na
manei ra mostrada na f i gura 4.3. Desta f orma, o Fi l ósof o f 1 usará os garf os g1
e g5, o f i l ósof o g2 os gar f os g1 e g2 e assim sucessi vamente. Os f i l ósof os ora
j antam, ora pensam e cada f i l ósof o, assim que consegui r pegar os doi s garf os,
j anta e os devol ve à mesa.
Figura 4.3− Ilustração Filósofos Jantadores
Resol ver este problema por paral el i smo, si gni f i ca cri ar ci nco processos
garf os e ci nco processos f i l ósof os. Quando um garf o esti ver sendo usado por
um f i l ósof o, não poderá ser usado por nenhum outro até que este o l i bere, e
i sto só ocorrerá quando o f i l ósof o esti ver sati sf ei to. I mpl ementar este
algori tmo requer uma séri e de cui dados. Um deles é ref erente à possi bi l i dade
47
do si stema todo entrar em deadlock. I magine que cada f i l ósof o, assim que f or
i ni ci al i zado, tentará pegar o garf o da sua di rei ta, e que todos consigam. Para
que possam j antar, devem também possui r o garf o à sua esquerda, só que o
garf o à sua esquerda é também o garf o à di rei ta do f i l ósof o anteri or e,
por tanto, j á está reservado à este, o que f ará que o f i l ósof o que requi si tou
este garf o f i que aguardando. Contudo, percebe−se que todos os f i l ósof os estão
aguardando a l i beração do garf o à sua esquerda, o que resul ta que nenhum
f i l ósof o j amai s consegui rá pegá−lo, caracter i zando deadlock. Para resol ver
este problema, é tomada uma precaução simples: o úl t imo f i l ósof o tentará
pegar o garf o à sua esquerda antes do da di rei ta. Assim, o primei ro f i l ósof o
será o pr imei ro a j antar, porque somente el e consegui rá pegar o garf o da sua
di rei ta e o da sua esquerda.
O processo que i nstal a os f i l ósof os e os garf os cuj o código pode ser
vi sto na f i gura 4.4 será anal i sado a segui r .
48
#i ncl ude " am_lib.c"
mai n( ){ l ong i nt m1, m2, t i dg[ 5] , t i df [ 5] , cc, aux, f ; char msg[ 40] ;
m1=am_init( ) ; i f ( m1==−1) exi t ( 0) ; m1=am_addhost( " ver di " ) ; i f ( m1==−1) exi t ( 0) ; m2=am_addhost( " vi val di " ) ; i f ( m2==−1) exi t ( 0) ; f or ( aux=0; aux<5; aux++) { t i dg[ aux] =am_startproc( m1, " gar f o" ) ; i f ( t i dg[ aux] ==−1)
exi t ( 0) ; } f or ( aux=0; aux<5; aux++) { t i df [ aux] =am_startproc( m2, " f i l osof o" ) ; i f ( t i df [ aux] ==−1)
exi t ( 0) ; } f pr i nt f ( st der r , " I ds dos f i l osof os: " ) ; f or ( aux=0; aux<5; aux++) f pr i nt f ( st der r , " %d " , t i df [ aux] ) ; f pr i nt f ( st der r , " \ nI ds dos gar f os: " ) ; f or ( aux=0; aux<5; aux++) f pr i nt f ( st der r , " %d " , t i dg[ aux] ) ; f pr i nt f ( st der r , " \ n" ) ; f or ( f =0; f <5; f ++) { spr i nt f ( msg, " 0%d" , f ) ; am_send( t i df [ f ] , msg) ; i f ( f ==4)
spr i nt f ( msg, " %d" , t i dg[ 0] ) ; el se
spr i nt f ( msg, " %d" , t i dg[ f ] ) ; am_send( t i df [ f ] , msg) ; i f ( f ==4)
spr i nt f ( msg, " %d" , t i dg[ f ] ) ; el se
spr i nt f ( msg, " %d" , t i dg[ f +1] ) ; am_send( t i df [ f ] , msg) ; } f or ( f =1; f <=5; f ++) { cc=am_receive( −1, msg) ; f pr i nt f ( st der r , " \ n* * * * Fi l osof o %d est a sat i sf ei t o\ n" , cc) ; }}
Figura 4.4− Processo jantar
I ni ci ci al i za−se o si stema pelo comando am_ini t() , at r i bui ndo−se o val or
da máquina servi dora à vari ável m1. V eri f i ca−se se houve erro, sai ndo do
programa em caso af i rmati vo (a mensagem de erro j á é gerada pelo
am_addhost()). I nsere−se a máqui na verdi e a v i val di (uma delas j á havi a si do
49
i nseri da pelo comando am_ini t()) atr i bui ndo seus val ores à vari ável m1 e m2,
respecti vamente.
Cri a−se com a f unção am_star tproc() ci nco processos garf o na máquina
m1 (verdi ) e armazena seus am_pids no vetor t i dg, f azendo−se o mesmo com
os processos f i l ósof os, porém cri ando−os na máquina m2 (vi val di ) e
armazenando seus am_pids no vetor t i df . I mprime−se na tel a o val or am_pid
de todos os processos cr i ados, para veri f i cação do usuári o.
Após serem cri ados os processos, envi a−se a cada f i l ósof o o número que
cada um recebeu (segundo f i gura 4.3, números de 0−4) e o número
identi f i cador de seus doi s garf os, para que el e possa enviar−l hes mensagens.
Neste ponto é necessári o tomar as medi das para evi tar deadlock. Para todo
ti df [ aux] envi a−se os am_pids dos garf os ti dg[ aux] e t i dg[ aux+1] , exceto para
o f i l ósof o ti df [ 4] (o úl t imo), onde esta ordem é i nverti da, poi s dever i a−se
enviar t i dg[ 4] e t i dg[ 0] , mas envia−se pr imei ro o t i dg[ 0] e depoi s o t i dg[ 4] .
Após enviar os am_pids dos garf os, este processo f i ca esperando o
retorno dos f i l ósof os di zendo que estão sati sf ei tos, e termina sua execução.
O processo f i l osof o tem como objet i vo requi si tar doi s gar f os à mesa,
usá−los por um determinado tempo (def i ni da pela constante TEMPO) e
devol vê−l os, vol tando a repeti r este processo por n vezes (def i ni do na
constante N).
50
#i ncl ude " am_lib.c"
#def i ne N 2 / * Numer o de vezes que j ant ar am* /#def i ne TEMPO 31000 / * Tempo que f i car am com os gar f os* /
mai n( ){ i nt t i dp, t i dg1, t i dg2, cc, dat a=0, cont a1, cont a2, nf ; char msg[ 40] ; t i dp=am_receive( −1, msg) ; nf =st r _i nt ( msg) ; t i dp=am_receive( −1, msg) ; t i dg1=st r _i nt ( msg) ; t i dp=am_receive( −1, msg) ; t i dg2=st r _i nt ( msg) ; spr i nt f ( msg, " %s" , " 1" ) ; am_send( t i dp, msg) ;
f or ( cont a1=1; cont a1<=N; cont a1++){ spr i nt f ( msg, " %s" , " 1" ) ; am_send( t i dg1, msg) ; cc=am_receive( t i dg1, msg) ; i f ( * msg==’ 0’ ) cont a1−−; el se
{ f pr i nt f ( st der r , " Fi l osof o %d t em gar f o 1 ( %d) \ n" , nf , t i dg1) ; spr i nt f ( msg, " %s" , " 1" ) ; am_send( t i dg2, msg) ; cc=am_receive( t i dg2, msg) ; i f ( * msg==’ 0’ )
{ spr i nt f ( msg, " %s" , " 0" ) ; am_send( t i dg1, msg) ;
f pr i nt f ( st der r , " Fi l osof o %d l i ber ou gar f o 1 ( %d) \ n", nf , t i dg1) ;
cont a1−−; } / * Nest e pont o o f i l osof o j a t em os doi s gar f os
a sua di sposi cao * / el se { f pr i nt f ( st der r , " Fi l osof o %d t em gar f o 2 ( %d) \ n" , nf , t i dg2) ;
f or ( cont a2=0; cont a2<TEMPO; cont a2++) ; spr i nt f ( msg, " %s" , " 1" ) ;
am_send( t i dg1, msg) ; am_send( t i dg2, msg) ;
f pr i nt f ( st der r , " Fi l osof o %d j a usou os gar f os\ n" , nf ) ; }}
}
spr i nt f ( msg, " %s" , " 1" ) ;am_send( t i dp, msg) ;}
Figura 4.5− Exemplo filosofo.c
Cri ou−se uma pequena f unção neste processo denominada str _i nt() que
apenas converte uma str i ng passada por parâmetro para um i ntei ro, de f orma
idênti ca à f unção am_str i nt() estudada anteri ormente. Esta f unção se f az
necessári a j á que nosso si stema permi te troca apenas de str i ngs, devendo o
usuári o preocupar−se com possívei s empacotamentos e desempacotamentos.
51
O código completo do processo f i l osof o pode ser v i sto na f i gura 4.5.
Em primei ro l ugar, recebe−se uma mensagem de um processo qualquer
(somente o pai i rá envi á−la). Def i ne−se o processo que a enviou como ti dp.
Esta mensagem recebi da corresponde ao am_pid do primei ro garf o, sendo
portanto convert i da para i ntei ro e atr i buída à vari ável t i dg1, o mesmo
acontece com a segunda mensagem recebida pelo processo pai , só que seu
val or será atr i buído à vari ável t i dg2. De posse dos am_pids de seus doi s
garf os, o processo f i l osof o responde com a str i ng “ 1” ao seu pai , i nf ormando−
o que está pronto para trabalhar .
O f i l ósof o pode, então, começar a requi si tar seus garf os. Dentro de um
laço de N vezes (número de vezes que i rá j antar), el e envia uma mensagem
com o texto “ 1” ao pr imei ro garf o, na tentat i va de usá−lo, este, por sua vez
i rá retornar uma mensagem de conf i rmação. A mensagem recebida por
am_recei ve() do garf o pode ser “ 1” , se o garf o agora per tence a este f i l ósof o
ou ‘0’ se o garf o não está di sponível para este processo. Se esta úl t ima
si tuação ocorrer , o processo f i l osof o decrementa a vari ável contadora dos
laços, para desconsiderar esta úl t ima i teração, e repete o processo. Mas, se o
garf o1 respondeu “ 1” , ou sej a, el e está, agora, di sponível para este f i l ósof o,
tenta−se então pegar o garf o2.
Para obter o garf o2, o procedimento é i dênti co ao uti l i zado para obter o
garf o1, com a di f erença que se desta vez el e não consegui r pegar este garf o,
el e envi a uma mensagem “ 0” ao garf o1, di spensando−o − para evi tar deadl ock
− e repete todo o l aço novamente desconsiderando a úl t ima i teração.
Caso tenha, f i nalmente, di sponibi l i zado os seus doi s garf os, f az−se um
laço de TEM PO vezes para si mular o tempo gasto na j anta e depoi s de
52
terminado este l aço, envi a−se uma mensagem “ 1” para os doi s garf os,
i nf ormando−os que não mai s preci sa deles.
Depoi s que o f i l ósof o j á j antou todas as vezes def i ni das na constante N,
este envia uma mensagem ao seu pai , i nf ormando estar sati sf ei to.
#i ncl ude " am_lib.c"
mai n( ){ l ong i nt t i df , t i da, chega; char msg[ 20] ;
f or ( ; ; ){ t i df =am_receive( −1, msg) ; i f ( * msg==’ 1’ )
{ am_send( t i df , msg) ; chega=0; f or ( ; chega! =1; ) { t i da=am_receive( −1, msg) ; i f ( t i da! =t i df )
am_send( t i da, " 0" ) ; el se chega=1; }}
}}
Figura 4.6− Processo garfo
O úl t imo processo envol vi do na sol ução deste problema é o processo
garf o. A f unção dele é acei tar o pedido de requi si ção do primei ro f i l ósof o, e
rej ei tar qualquer outro pedido que venha até que o primei ro o di spense. O
código compl eto deste processo pode ser vi sto na f i gura 4.6.
O processo i ni ci a acei tando mensagem de qualquer outro processo,
sabe−se que, pel a manei ra como este probl ema f oi impl ementado, o úni co que
enviará esta mensagem é o f i l ósof o que o usará. A rmazena−se o am_pid do
processo que enviou esta mensagem na vari ável t i df e veri f i ca−se se a
mensagem tem em sua primei ra posi ção o caracter ‘1’ , i ndi cando um f i l ósof o
querendo usar este garf o. O processo gar f o responde, então com a str i ng “ 1” ,
envi ando a mesma msg recebida, para i ndi car ao f i l ósof o que agora pertence a
ele.
53
Processo garf o entra agora em um l aço até que a vari ável achei sej a
di f erente de 1. Dentro deste l aço, el e recebe mensagem de qualquer processo,
compara o am_pid deste com o am_pi d do seu f i l ósof o. Se f orem i guai s, é
si nal que trata−se do f i l ósof o, à qual pertence atualmente, querendo i nf ormar
que não mai s o está usando. Deve−se, portanto, setar a vari ável achei para 1,
i ndi cando que o processo f i l osof o di spensou este garf o, podendo o mesmo ser
requi si tado por outro f i l osof o. Mas se não f or o mesmo f i l osof o, garf o então
envia a str i ng “ 0” para i ndi car ao processo que tenta requi si tá−l o que este
garf o j á per tence à um outro processo e não pode, no momento, atendê−lo.
54
5CONCLUSÃO
A gama de uso deste ambiente não é, obvi amente, tão ampla quanto a do
PVM, mas mui tos exemplos cri ados em PVM podem, com extrema f aci l i dade,
ser mi grados para esta i nterf ace. No entanto, por ser mai s simples, este
si stema é bem mai s f áci l de usar que o PVM, poi s não necessi ta de al guns
comandos burocráti cos usados no PVM (pvm_ini tsend(), pvm_pkint(),
pvm_upkint(), por exempl o). Seu estudo é extremamente simpl es, e f aci lmente
alunos poderão implementar processos em ambiente mul ti programado sem a
necessi dade de se f ami l i ari zar com a extensa gama de comandos do PVM .
Uma das maiores vantagens do AMRU está, no entanto, no f ato de que
ele usa pr imi ti vas bási cas de comuni cações do UNI X e é rel at i vamente
pequeno. O que f aci l i ta não só a sua uti l i zação, mas também o entendimento
da sua estrutura i nterna.
I sto o torna, sem dúvida, uma f erramenta extremamente rel evante do
ponto de vi sta di dáti co.
ANEXOS
ANEXO 1 AM_LIB.C
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * AM_LI B. C * // * AMBI ENTE DE MULTI PROCESSAMENTO PARA UMA REDE DE MÁQUI NAS UNI X * // * El gi o Schl emer 11/ 12/ 96 * // * * // * Bi bl i ot eca Pr i nc i pal * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
#i nc l ude <st di o. h>#i ncl ude <ut mp. h>#i ncl ude <r pc/ r pc. h> #i nc l ude <r pcsvc/ r user s. h>#i ncl ude <st r i ng. h>
#def i ne AM_MAXMAQ 4 / * Numer o maxi mo de host s compor t adas * /#def i ne AM_MAXPROC 20 / * Numer o maxi mo de pr ocessos compor t ados * /
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * Def i ni cao de est r ut ur as * / s t r uct AM_LI STHOST{
char nome[ 20] ;i nt numer o;char st at us;} ;/ * Li s t a das host s par t i c i pant es do s i s t ema nome= nome da host ( ex. ver di ) numer o= numer o pel o qual ser a r econheci da no s i s t ema s t at us= 0 se campo di sponi vel , 1 se ocupado por host at i va* /
s t r uct AM_LI STPROC{l ong i nt npr oc;i nt nmaq;char st at us;char nome[ 20] ;} ;/ * Li s t a das pr ocessos i ni c i al i zados por st ar t pr oc npr oc= numer o do pr ocesso dado pel o s i s t ema ( uma composi cao
do numer o da host e o i d do pr ocesso nmaq= numer o da host onde encont r a−se est e pr ocesso nome= nome do pr ocesso.* /
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_nummaq=0, am_numpr oc=0; / * am_nummaq=cont ador de host ex i s t ent es
am_numpr oc=cont ador de pr ocessos cr i ados* /st r uct AM_LI STHOST am_l i s t maq[ AM_MAXMAQ] ;st r uct AM_LI STPROC am_l i s t pr oc[ AM_MAXPROC] ;char am_ser v i dor =1;
/ * Pr ot ot ypes das f uncoes * /i nt am_i ni t ( ) ;i nt am_host name( i nt , char * ) ;i nt am_myhost ( ) ;l ong i nt am_myt i d( ) ;l ong i nt am_conver t e ( i nt , l ong i nt ) ;i nt am_addhost ( char * ) ;l ong i nt am_st ar t pr oc( i nt , char * ) ;i nt am_send( l ong i nt , char * ) ;i nt am_r ecei ve( i nt , char * ) ;l ong i nt am_st r i nt ( char * ) ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /l ong i nt am_st r i nt ( char * am_dat a){ char * am_aux; l ong i nt am_t ot al =0; i nt am_si nal =1;
f or ( am_aux=am_dat a; ( * am_aux<’ 0’ ) | | ( * am_aux>’ 9’ ) ; am_aux++){ i f ( am_aux==NULL) r et ur n( −1) ; i f ( * am_aux==’ −’ ) am_si nal =−1;}
f or ( ; ( * am_aux>=’ 0’ ) &&( * am_aux<=’ 9’ ) ; am_aux++)am_t ot al =( am_t ot al * 10) + ( * am_aux−’ 0’ ) ;
spr i nt f ( am_dat a, " %s" , am_aux) ; r et ur n( am_t ot al * am_si nal ) ;}
57
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_i ni t ( ){ char nome[ 50] , envi a[ 100] , r ecebe[ 25] ; i nt cont a; char * env, * pr ecebe; i nt s t at ; f or ( cont a=0; cont a<AM_MAXMAQ; cont a++)
am_l i s t maq[ cont a] . s t at us=0; f or ( cont a=0; cont a<AM_MAXPROC; cont a++)
am_l i s t pr oc[ cont a] . s t at us=0; get host name( nome, 64) ; am_ser v i dor =0; cont a=am_addhost ( nome) ; spr i nt f ( envi a, " 8#%d#" , get pi d( ) ) ; env=envi a; pr ecebe=r ecebe; s t at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; am_l i s t pr oc[ am_numpr oc] . s t at us=1; am_l i s t pr oc[ am_numpr oc] . nmaq=am_myhost ( ) ; am_l i s t pr oc[ am_numpr oc] . npr oc=am_myt i d( ) ;
r et ur n( cont a) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_host name( i nt maq, char * nome)/ * Est a f uncao r et or na o nome da host cuj o numer o e maq * /{ char nome2[ 20] , * env, envi a[ 20] , r ecebe[ 20] , * pr ecebe, st at ;
/ * nome=usada par a guar dar o nome da host , cont a=cont ador f or * /
get host name( nome, 64) ; / * obt em o nome da host no l aco a segui r , pr ocur ar a pel a ocor r enci a do nome da host na l i s t a de host s do s i s t ema r et or nando o numer o dest a* /
pr ecebe=r ecebe; spr i nt f ( envi a, " 6#%d#" , maq) ; env=envi a; s t at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( r ecebe[ 0] ==’ 0’ )
r et ur n( −1) ; i f ( r ecebe[ 0] ==’ 1’ ) { spr i nt f ( nome, " %s" , r ecebe+2) ; r et ur n( 1) ; } i f ( r ecebe[ 0] ==’ 2’ ) { spr i nt f ( envi a, " 6#%d#" , maq) ; env=envi a; s t at = cal l r pc ( r ecebe+2, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( r ecebe[ 0] ==’ 1’ ) {
spr i nt f ( nome, " %s" , r ecebe+2) ; r et ur n( 1) ; } } r et ur n( −1) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_myhost ( )/ * Est a f uncao r et or na o numer o da host que o r equi s i t ou ou −1 caso haj a al gum er r o ( est a maqui na nao t em pr ocesso daemon, por exempl o* /{ char nome[ 20] , * env=" 5" , r ecebe[ 50] , * pr ecebe, st at ;
/ * nome=usada par a guar dar o nome da host , cont a=cont ador f or * /
58
i nt maq=0;
get host name( nome, 64) ; / * obt em o nome da host no l aco a segui r , pr ocur ar a pel a ocor r enci a do nome da host na l i s t a de host s do s i s t ema r et or nando o numer o dest a* /
pr ecebe=r ecebe; s t at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( r ecebe[ 0] ==’ 1’ ) { am_st r i nt ( r ecebe) ; maq=am_st r i nt ( r ecebe) ; r et ur n( maq) ; } r et ur n( −1) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /l ong i nt am_myt i d( )/ * Obt em o numer o pel o qual o pr ocesso e conheci do no s i s t ema Est e numer o e uma comnposi cao bi nar i a descr i t a em am_st ar t pr oc* /{ l ong i nt maq; pi d_t pi d; maq=am_myhost ( ) ;
/ * ot em o numer o da host * / maq=maq<<12;
/ * compoe o numer o da maqui na * / pi d=get pi d( ) ;
/ * obt em o numer o do pr ocesso ( no SO) * / maq=maq+pi d; r et ur n( maq) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /l ong i nt am_conver t e ( i nt maq, l ong i nt t i d)
{ l ong i nt am_aux; am_aux=maq<<12; r et ur n( am_aux+t i d) ; }/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_addhost ( char * maqui na){ / * Est e pr ogr ama f az uma chamada RPC par a o pr ogr ama AMRUD em execucao na maqui na r emot a. Se est e pr ogr ama est i ver at i vado el e r esponder a conf or me sol i c i t ado. Ret or na o numer o da host ou −1 se houve er r o * /
i nt s t at , cont a; char r ecebe[ 2] , buf [ 30] , nome[ 20] ; char * envi a, * pr ecebe;
i f ( am_ser v i dor ) r et ur n( −1) ; / * Ver i f i ca se a maqui na j a nao est a i nser i da no s i s t ema * / f or ( cont a=0; cont a<am_nummaq; cont a++)
i f ( s t r cmp( maqui na, am_l i s t maq[ cont a] . nome) ==0) { am_l i s t maq[ cont a] . s t at us=1; r et ur n( am_l i s t maq[ cont a] . numer o) ; }
pr ecebe=r ecebe; envi a=buf ; get host name( nome, 64) ; spr i nt f ( buf , " 1#%d#%s" , am_nummaq, nome) ; / * envi a o nome e o numer o de sua host par a a host i nser i da saber quem acr i ou * / s t at = cal l r pc ( maqui na, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &envi a, xdr _wr apst r i ng, &pr ecebe ) ; i f ( s t at ! = 0 ) { f pr i nt f ( s t der r , " ERRO: ’ amr ud’ nao est a execucao na maqui na %s. \ n" , maqui na) ;
59
r et ur n( −1) ; } el se i f ( s t r cmp( " 1" , r ecebe) ==0)
/ * pr ocur a por uma posi cao di sponi vel na l i s t a de host s, a posi cao e consi der ada di sponi vel se st at us f or 0* /f or ( cont a=0; cont a<AM_MAXMAQ; cont a++) i f ( ! am_l i s t maq[ cont a] . s t at us)
{ st r cpy( am_l i s t maq[ am_nummaq] . nome, maqui na) ;/ * cadast r a a nova host i nser i da na l i s t a de host s * /
am_l i s t maq[ cont a] . numer o=am_nummaq;am_l i s t maq[ cont a] . s t at us=1;spr i nt f ( buf , " 7#%d#%s" , am_nummaq, maqui na) ;get host name( nome, 64) ;envi a=buf ;s t at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
xdr _wr apst r i ng, &envi a, xdr _wr apst r i ng, &pr ecebe ) ; i f ( s t at ! = 0 ) { f pr i nt f ( s t der r , " ERRO: ’ amr ud’ nao est a execucao na maqui na%s. \ n" , nome) ; r et ur n( −1) ; } r et ur n( am_nummaq++) ;
} r et ur n( −1) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /l ong i nt am_st ar t pr oc( i nt maq, char * nomep){ / * I ni c i a o pr ocesso de nome nomep na maqui na maq, r et or na o numer o do pr ocesso cr i ado ou −1 se houve er r o. O numer o do pr ocesso e uma composi cao f ei t a a par t i r do numer o da host com o i p do pr ocesso da segui nt e f or ma: f az−se um shi f t l ef t do numer o da host em 12 posi coes como exempl o, se f or maqui na 1, expr esso como 0000 0000 0000 0001b, ao f azer esse shi f t , f i ca 0001 0000 0000 0000b, ou sej a, 4096 em deci − mal , soma−se ent ao a est e numer o o i d do pr ocesso, por exempl o, pr ocesso 240, expr esso como 0000 0000 1111 0000b, r esol t ando em 4336 ( 0001 0000 1111 0000b) . Assi m sendo, como o l ong i nt e expr esso em 4 byt es, usamos o pr i mei r o byt e par a numer o da host ( t ot al de 256) e os out r os t r es par a pr ocessos ( 4096) . Ver i f i cou−se que os i ps cr i ados pel o Li nux nao ul t r apassam est e l i mi t e. * /
i nt s t at , numer o=−1, cont a; char envi a[ 20] , r ecebe[ 5] , * pr ecebe, * env; l ong i nt pr oc;
i f ( am_ser v i dor ) r et ur n( −1) ; / * pr ocur a pel a host na l i s t de host s * / f or ( cont a=0; cont a<AM_MAXMAQ; cont a++)
i f ( ( maq==am_l i s t maq[ cont a] . numer o) &&( am_l i s t maq[ cont a] . s t at us) ) numer o=cont a;
i f ( numer o==−1){ f pr i nt f ( s t der r , " numer o de maqui na nao exi st e\ n" ) ;r et ur n( −1) ;
}
spr i nt f ( envi a, " 4#%s" , nomep) ; / * Ger a st r i ng a ser envi ada ao Deamon na host , 4 i ndi ca ser v i co de
am_st ar t pr oc segui do do nome do pr ocesso que deve sr cr i ado * /
pr ecebe=r ecebe; env=envi a; s t at = cal l r pc ( am_l i s t maq[ numer o] . nome, RUSERSPROG, RUSERSVERS,RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( s t at ! = 0 ) { f pr i nt f ( s t der r , " ERRO: ’ amr ud’ nao est a execucao na maqui na %s. \ n" ,
am_l i s t maq[ numer o] . nome) ; r et ur n( −1) ; } i f ( s t r cmp( r ecebe, " −1" ) ==0)
{ pr i nt f ( " Nao f oi possi vel i ni c i ar pr ocesso %s\ n" , nomep) ;r et ur n( −1) ;
}
60
pr oc=am_st r i nt ( r ecebe) ; pr oc=am_conver t e( maq, pr oc) ;
/ * em r ecebe exi st e o numer o i d ( do SO) do pr ocesso cr i ado, obt em−se agor a o numer o do pr ocesso no s i s t ema * / f or ( cont a=0; cont a<AM_MAXPROC; cont a++)
/ * Cadast r a o pr ocesso cr i ado na l i s t a de pr ocessos * /i f ( ! am_l i s t pr oc[ cont a] . s t at us) { am_l i s t pr oc[ cont a] . s t at us=1; s t r cpy( am_l i s t pr oc[ cont a] . nome, nomep) ; am_l i s t pr oc[ cont a] . npr oc=pr oc; am_l i s t pr oc[ cont a] . nmaq=maq; r et ur n( pr oc) ; }
r et ur n( −1) ;}/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_send( l ong i nt pr oc, char * msg){ / * Envi a uma mensagem par a o pr ocesso especi f i cado * /
i nt s t at , cont a, numer o=−1; char envi a[ 100] , nome[ 30] ; char r ecebe[ 20] , * pr ecebe, * env; numer o=pr oc>>12; s t at =am_host name( numer o, nome) ; i f ( s t at ==−1)
r et ur n( −1) ; pr oc=pr oc&4095;
/ * Obt em o r eal numer o do pr ocesso, seu i d, o numer o pel o qual el e e conheci do pel o SO de sua maqui na * /
spr i nt f ( envi a, " 2#%d#%d#%s" , am_myt i d( ) , pr oc, msg) ;/ * Ger a a st r i ng a ser envi ada ao Daemon da maqui na que possue est e pr ocesso. O numer o 2 i ndi ca que t r at a−se do ser v i co 2. Segue−se o numer o do pr ocesso que execut ou o ser v i co e o numer o do pr ocesso par a quem desej a−se envi ar a mensagem. * /
pr ecebe=r ecebe; env=envi a; s t at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( s t at ! = 0 ) { f pr i nt f ( s t der r , " ERRO: ’ amr ud’ nao est a execucao na maqui na %s. \ n" ,
nome) ; r et ur n( −1) ; } i f ( s t r cmp( r ecebe, " −1" ) ==0)
{ pr i nt f ( " Nao f oi possi vel achar pr ocesso %s\ n" , pr oc) ;r et ur n( −1) ;
} r et ur n( 1) ;}/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_r ecei ve( i nt pr oc, char * msg){ / * Recebe uma mensagem do pr ocesso especi f i cado, Se pr oc f or −1, i ndi ca que a mensagem pode ser de qual quer pr ocesso * / i nt s t at , cont a, numer o=−1; char envi a[ 20] , r ecebe[ 100] , nome[ 20] , * pr ecebe, * env;
spr i nt f ( envi a, " 3#%d#%d#" , get pi d( ) , pr oc) ;/ * Not e que aqui , ao i nves de envi ar o numer o do pr ocesso no s i s t ema, envi a−se o seu i d apenas. I sso por que quem f ar a o t r at ament o de mensagens e o Daemon dest a maqui na ( est a pr opr i a que execut ou o am_r ecei ve) , e est e daemon
conhece seus " f i l hos" pel o seu i d.* /
pr ecebe=r ecebe; env=envi a; get host name( nome, 64) ;
/ * O buf f er de msgs e cont r ol ado pel o Daemon de cada host , cada Daemon cont r ol a as msgs de seus f i l hos. Por i sso est a chamada de RPC e par a a pr opr i a host que execut ou est a f uncao.* /
f or ( ; r ecebe[ 0] ! =’ 1’ ; ) {
s t at = cal l r pc ( nome, RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, xdr _wr apst r i ng, &env, xdr _wr apst r i ng, &pr ecebe ) ; i f ( s t at ! = 0 ) { f pr i nt f ( s t der r , " ERRO: ’ amr ud’ nao est a execucao nest a maqui na \ n" ) ; r et ur n( −1) ; } } am_st r i nt ( r ecebe) ; numer o=am_st r i nt ( r ecebe) ; spr i nt f ( msg, " %s" , r ecebe+1) ; r et ur n( numer o) ;}/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
ANEXO 2 AMRUD.C
58
59
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // * AMRUD. C * // * AMBI ENTE DE MULTI PROCESSAMENTO PARA UMA REDE DE MÁQUI NAS UNI X * // * El gi o Schl emer 11/ 12/ 96 * // * * // * Pr ogr ama Daemon * // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
#i nc l ude <st di o. h>#i ncl ude <r pc/ r pc. h>#i ncl ude <r pcsvc/ r user s. h>
#i ncl ude <sys/ t ypes. h>#i ncl ude <sys/ i pc. h>#i ncl ude <sys/ msg. h>
#def i ne AM_TAMMSG 50 / * t amanho das st r i ngs de msgs * /#def i ne AM_MSGMAX 10 / * num max de msgs no buf f er par a cada pr oc * /#def i ne AM_MAXPROC 20 / * Numer o maxi mo de pr ocessos nest e host * /
s t r uct AM_LI STHOST{char nome[ 20] ;i nt numer o;} am_l i s t maq[ AM_MAXPROC] ;/ * Li s t a das host s par t i c i pant es do s i s t ema nome= nome da host ( ex. ver di ) , −1 r egi st r o di sponi vel numer o= numer o pel o qual ser a r econheci da no s i s t ema * /
s t r uct AM_LI STPROC {l ong i nt npr oc;char st at us;char msg[ AM_MSGMAX] [ AM_TAMMSG] ;i nt or i gem[ AM_MSGMAX] ;i nt esper a;} am_l i s t pr oc[ AM_MAXPROC] ;/ * Li s t a de pr ocessos. Di f er e−se um pouco da l i s t a ex i st ent e na bi bl i ot eca, pel o f at o de aqui nao exi st i r o nome do pr ocesso,
npr oc e o i d del e do SO e t er campos par a buf er i zar as msg.
npr oc=numer o do pr ocesso msg= buf f er s de mensagem pendent es, cada pr ocesso pode t er at e
AM_MSGMAX mensagens esper ando, cada uma de at e AM_TAMMSG car act er es. s t at us= 0= sem msg par a el e, >0=numer o de msg r ecebi das esper a= −3 campo di sponi vel , −2 ocupado−pr ocesso nao esper a
msg, −1 ocupado, pr ocesso esper a msg de qual quer pr o− cesso, >=0 = numer o do pr ocesso de quem est a esper ando
uma mensagem. or i gem=pr ocessos que envi ar am mensagem, −1=di sponi vel .* /
char am_mi nhahost =0;/ * se =0, est e e o ser v i dor , >0 desi gna o numer o dest a host * /
char am_ser ver name[ 30] ;/ * nome da host ser v i dor a * /
/ * PROTOTYPES DAS FUNCOES * /
i nt am_msgr ec( i nt , i nt , char * ) ;i nt am_msgsend( i nt , i nt , char * ) ;l ong i nt am_st r i nt ( char * ) ;char * * am_ser ver ( char * * ) ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_msgr ec( i nt am_pi dr eq, i nt am_pi dmsg, char * am_msg){ / * Ser v i co de r ecebi ment o de mensagens, se exi st i r mensagem de am_pi dmsg par a am_pi dr eq, est a ser a ar mazenada em am_msg e a f uncao r et or na 1, senao a f uncao r et or na −1 ( o ser v i co de send e r ecei ve e s i ncr ono, mas a de− c i sao de por o pr ocesso par a dor mi r e do am_r ecei ve e nao do Daemon est e ul t i mo apenas i nf or ma ao am_r ecei ve pel o r et or no do RPC que nao ex i s t e a am_msg r equi s i t ada) . Se am_pi dmsg f or −1, i ndi ca r eceber msg de qual quer pr ocesso. * /
i nt cont a, cont a2;
/ * pr ocur a a posi cao do buf f er per t encent e ao pr ocesso que r equi s i t ou o pedi do de r ecei ve * / f or ( cont a=0; cont a<AM_MAXPROC; cont a++)
60
i f ( am_l i s t pr oc[ cont a] . npr oc==am_pi dr eq){
i f ( am_l i s t pr oc[ cont a] . s t at us==0)/ * se st at us e zer o, nao ha msg par a est e pr ocesso * /r et ur n( −1) ;
i f ( am_pi dmsg==−1) / * −1 i ndi ca r eceber de qual quer pr ocesso * / f or ( cont a2=0; cont a2<AM_MSGMAX; cont a2++)
i f ( am_l i s t pr oc[ cont a] . or i gem[ cont a2] ! =−1)
{ spr i nt f ( am_msg, " 1#%d#%s" , am_l i s t pr oc[ cont a] . or i gem[ cont a2] , am_l i s t pr oc[ cont a] . msg[ cont a2] ) ;
/ * mont a a st r i ng de r et or no, 1 i ndi ca sucesso, segue onumer o do pr ocesso qeu envi ou a msg ( ut i l caso am_pi dmsgf osse −1) e em segui da a mensagem * /
am_l i s t pr oc[ cont a] . or i gem[ cont a2] =−1;/ * di sponi bi l i za a posi cao do buf f er * /
am_l i s t pr oc[ cont a] . s t at us−−; r et ur n( 1) ; }
f or ( cont a2=0; cont a2<AM_MSGMAX; cont a2++) i f ( am_l i s t pr oc[ cont a] . or i gem[ cont a2] ==am_pi dmsg)
{ spr i nt f ( am_msg, " 1#%d#%s" , am_pi dmsg, am_l i s t pr oc[ cont a] . msg[ cont a2] ) ; am_l i s t pr oc[ cont a] . or i gem[ cont a2] =−1; am_l i s t pr oc[ cont a] . s t at us−−; r et ur n( 1) ;}
} r et ur n( −1) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /i nt am_msgsend( i nt or i gem, i nt dest i no, char * am_msg){ / * Col oca mensagem no buf f er r et or na 1 se sucesso, ou −1 se er r o ( buf f er chei o,por exempl o * /
i nt cont a, cont a2;
f or ( cont a=0; cont a<AM_MAXPROC; cont a++) / * pr ocur a posi cao de buf f er do pr ocesso dest i no * / i f ( am_l i s t pr oc[ cont a] . npr oc==dest i no)
/ * pr ocur a no buf f er espaco di sponi vel par a ar mazenar a msg * /f or ( cont a2=0; cont a2<AM_MSGMAX; cont a2++) { i f ( am_l i s t pr oc[ cont a] . or i gem[ cont a2] ==−1) { / * buf er i za a mensagem * /
am_l i s t pr oc[ cont a] . or i gem[ cont a2] =or i gem;am_l i s t pr oc[ cont a] . s t at us=am_l i s t pr oc[ cont a] . s t at us++;st r cpy( am_l i s t pr oc[ cont a] . msg[ cont a2] , am_msg) ;r et ur n( 1) ;}
} r et ur n( −1) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /l ong i nt am_st r i nt ( char * dat a)/ * Ret i r a o pr i mei r o numer o i nt ei r o encont r ado na st r i ng dat a, r et or na−o conver t i do par a i nt ei r o e r et i r a−o da st r i ng* /{ char * aux; l ong i nt t ot al =0; i nt s i nal =1;
f or ( aux=dat a; ( * aux<’ 0’ ) | | ( * aux>’ 9’ ) ; aux++){ i f ( aux==NULL) r et ur n( −1) ; i f ( * aux==’ −’ ) s i nal =−1;}
f or ( ; ( * aux>=’ 0’ ) &&( * aux<=’ 9’ ) ; aux++)t ot al =( t ot al * 10) + ( * aux−’ 0’ ) ;
spr i nt f ( dat a, " %s" , aux) ; r et ur n( t ot al * s i nal ) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /char * * am_ser ver ( char * * i ndat a){ / * Pr ogr ama r esponsavel pel o at endi ment o das chamadas de RPC, at r aves das st r i ngs envi adas pel as chamadas, det er mi na o t i po de ser v i co r equi z i t ado e exet ua−o * / s t at i c char dat a[ AM_TAMMSG] ; s t at i c char * pd, * r d; i nt s t at , pi d, am_pi dr eq, am_pi dmsg; r d=* i ndat a;
swi t ch ( * * i ndat a) { case ’ 1’ : / * Test e, usado pel o addhost * /
am_st r i nt ( r d) ; am_mi nhahost =( char ) am_st r i nt ( r d) ; spr i nt f ( am_ser ver name, " %s" , r d+1) ;
dat a[ 0] =’ 1’ ; dat a[ 1] =’ \ 0’ ; br eak; case ’ 2’ : / * Send * / dat a[ 0] =’ 1’ ; dat a[ 1] =’ \ 0’ ;
am_st r i nt ( r d) ; am_pi dr eq=am_st r i nt ( r d) ; am_pi dmsg=am_st r i nt ( r d) ; am_msgsend( am_pi dr eq, am_pi dmsg, r d+1) ;
br eak; case ’ 3’ : / * Recei ve * / am_st r i nt ( r d) ;
am_pi dr eq=am_st r i nt ( r d) ; am_pi dmsg=am_st r i nt ( r d) ; s t at =am_msgr ec( am_pi dr eq, am_pi dmsg, dat a) ; i f ( s t at ==−1)
{ dat a[ 0] =’ 0’ ; dat a[ 1] =’ \ 0’ ;}
br eak; case ’ 4’ : / * St ar t pr oc * /
pi d=f or k( ) ; i f ( ! pi d) {
execv( &r d[ 2] , NULL) ; exi t ( 0) ; }
spr i nt f ( dat a, " %d" , pi d) ; f or ( s t at =0; st at <AM_MAXPROC; st at ++)
i f ( am_l i s t pr oc[ st at ] . esper a==−3){ am_l i s t pr oc[ st at ] . esper a=−2; am_l i s t pr oc[ st at ] . npr oc=pi d; f or ( pi d=0; pi d<AM_MSGMAX; pi d++)
am_l i s t pr oc[ st at ] . or i gem[ pi d] =−1; s t at =AM_MAXPROC+1;}
i f ( s t at ==AM_MAXPROC){ spr i nt f ( dat a, " %d" , −1) ; br eak;}
br eak;case ’ 5’ : / * Myhost * /
spr i nt f ( dat a, " 1#%d" , am_mi nhahost ) ;br eak;
case ’ 6’ : / * am_host name * /am_st r i nt ( r d) ;pi d=am_st r i nt ( r d) ;spr i nt f ( dat a, " 0" ) ;i f ( am_mi nhahost ==0) { f or ( s t at =0; st at <AM_MAXPROC; st at ++)
i f ( am_l i s t maq[ st at ] . numer o==pi d) spr i nt f ( dat a, " 1#%s" , am_l i s t maq[ st at ] . nome) ; }el se spr i nt f ( dat a, " 2#%s" , am_ser ver name) ;br eak;
case ’ 7’ : / * cadast r a nova host * /am_st r i nt ( r d) ;
pi d=am_st r i nt ( r d) ;f or ( s t at =0; st at <AM_MAXPROC; st at ++) i f ( am_l i s t maq[ st at ] . numer o==−1)
{ am_l i s t maq[ st at ] . numer o=pi d; spr i nt f ( am_l i s t maq[ st at ] . nome, " %s" , r d+1) ; s t at =AM_MAXPROC; spr i nt f ( dat a, " %s" , " 1" ) ;}
br eak; case ’ 8’ : / * r egi st r a o pr ocesso ser v i dor * /
am_st r i nt ( r d) ; pi d=am_st r i nt ( r d) ;
am_l i s t pr oc[ 0] . esper a=−2;am_l i s t pr oc[ 0] . npr oc=pi d;f or ( pi d=0; pi d<AM_MSGMAX; pi d++)
am_l i s t pr oc[ 0] . or i gem[ pi d] =−1; br eak;
def aul t : dat a[ 0] =’ 2’ ; dat a[ 1] =’ \ 0’ ; } pd=dat a; r et ur n( &pd) ;}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /mai n( ){ i nt aux=0; f or ( aux=0; aux<AM_MAXPROC; aux++)
/ * i ni c i al i za campos da l i s t a de am_l i s t pr oc * /{ am_l i s t pr oc[ aux] . esper a=−3; am_l i s t pr oc[ aux] . s t at us=0; am_l i s t maq[ aux] . numer o=−1;}
r egi st er r pc( RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM, am_ser ver , xdr _wr apst r i ng, xdr _wr apst r i ng) ; svc_r un( ) ; f pr i nt f ( s t der r , " Er r o: svc_r un r et or nou! \ n" ) ; ex i t ( 1) ;}
BIBLIOGRAFIA
[ SCH 96] SCHL EM ER, El gi o. A mbi ente de M ul t i processamento parauma Rede de M áqui nas UNI X : Trabal ho submet i do comorequi si to i ni ci al para a obtenção do grau de Bacharel emI nf ormát i ca. Canoas: Departamento de I nf ormát i ca daUL BRA . 1996.
[ SHA 87] SHA W, M yr i l Cl ement. UNI X I nternal s . USA : TA B books,1987.
[ SUN 90] SUN. Network Programmi ng Gui de . 1990.