Escolar Documentos
Profissional Documentos
Cultura Documentos
N I V E R S I D A D E
U S A D A
D E
I S B O A
N I V E R S I D A D E
U S A D A
D E
I S B O A
SUMRIO
1. Introduo .................................................................................................... 14 2. Breve abordagem sobre o Linux .................................................................. 15 2.1. Utilizadores, tarefas e processos ........................................................... 15 2.2. Sistema de ficheiros............................................................................... 15 3. Comunicao entre processos (IPC) ........................................................... 16 3.1. Tipos de IPC .......................................................................................... 16 3.1.1. Pipes ............................................................................................... 16 3.1.2. Filas de Mensagens ........................................................................ 16 3.1.3. Memria partilhada .......................................................................... 16 3.2. Sincronizao entre processos .............................................................. 17 3.2.1. Sinais............................................................................................... 17 3.2.2. Semforos ....................................................................................... 17 3.3. A Correo dos programas .................................................................... 17 3.3.1. O programa sobre pipes .................................................................. 17 3.3.1.1. Variveis declaradas ................................................................. 17 3.3.2. O Programa sobre Filas de mensagens .......................................... 18 3.3.2.1. Variveis declaradas ................................................................. 19 3.3.3. Sinais............................................................................................... 20 3.3.4. Socketpair ....................................................................................... 21
13
1. INTRODUO
Este trabalho surge com o objectivo prtico de fazer o estudo sobre a comunicao entre processos. De formas a se perceber os conceitos, foram propostos a anlise de erros em programas criados, fazer correes e a seguir fazer uma comparao com outros programas de maneiras a interiorizar a aplicao e diferena entre alguns tipos de IPC. De forma a entrar bem no tema, farei uma breve abordagem conceptua do termo Linux, baseando em definies de alguns autores e logo a seguir que entrarei nos IPC.
14
The most exciting developments for Linux will happen in user space, not kernel space. The changes in the kernel will seem small compared to whats happening further out in the system. Linus Trovalds
15
Directrio
/bin /boot /dev /etc /home /lib /mnt /opt /proc /root /sbin /tmp /usr /usr/local /usr/src /var
Descrio
Arquivos binrios de comandos essenciais do sistema. Arquivos do arranque do sistema Contm ficheiros que representam todos os dispositivos de hardware e perifricos de sistema. Contm a maioria dos ficheiros de configurao do sistema operativo. Diretrias de trabalho do utilizador. Contm bibliotecas necessrias para que o sistema e os programas possam funcionar. Diretrio de montagem de dispositivos, sistemas de arquivos e partio Para instalao de programas no oficiais da distribuio. Diretrio virtual (RAM) onde rodam os processos ativos. Diretrio local do superusurio (root). Arquivos de sistema essenciais (binrios do superusurio). Arquivos temporrios gerados por alguns utilitrios. Arquivos de usurios nativos da distribuio. Para instalao de programas no oficiais da distribuio. Arquivos fontes do sistema necessrios para compilar o kernel. Arquivos de log e outros arquivos variveis.
16
int fd[2]; /* Declarao da varivel "file descriptor", ir armazenar os servios de escrita e leitura */ char b_entr[BUFSIZ]; /* Declarao da variavel para Alocao esttica do buffer de memria*/ pid_t childpid; /* Declarao da varivel que armazena o ID do Processo Filho*/ pipe(fd); /* Funo Pipe com paramentro que retorna fd (0) e fd(1), que so 2 inteiros */
Na condio a seguir, comea-se por aplicar uma regra muito importante dos Pipes, quando que deve-se fechar o lado receptor, e quando que deve-se fechar o lado emisso, de maneiras a haver a comunicao sem erro algum. Para este caso, quando
17
o processo for filho, este ir fechar o lado receptor do Pipe e simplesmente poder escrever.
/* Na condio a seguir testado a condio de criao do processo filho, caso concretizar-se inicializada a funo fd com parametro 0 */ if((childpid = fork()) == 0) { close (fd[0]); /* O ndice 0 fecha o lado receptor do Pipe */ printf("Eu sou o processo Filho!\n"); dup(fd[0]); /*Duplica o file descriptor de entrada da pipe (fd(0)) na sua entrada padro */ execlp ( "ps","-al",0); /*Sobrepor o cdigo do processo filho com o do comando "ps" */ close (fd[1]); exit(0); }
Contrariamente, caso o processo for pai, este ir fechar o lado emissor do Pipe e simplesmente permitir a sua leitura, tambm de maneiras a permitir a continuidade da comunicao.
/* Execuo do processo pai */ else { /* Esta funo serve para forar uma paragem na execuo do processo pai at que o processo filho termine a sua execuo*/ wait (0); close (fd[1]); /* O ndice 1 Fecha o lado emissor do Pipe */ printf("Eu sou o processo pai! \n"); /* Condio de fazer a leitura do file descriptor fd(0) e saber o tamanho do buffer atravs do ponteiro &b_entr */ while (read(fd[0],&b_entr,BUFSIZ)) printf("%s",b_entr); /* Imprimir o tamanho do buffer no ecr */ close(fd[0]); exit(0); }
18
3.3.2.1. VARIVEIS DECLARADAS Quanto as variveis, importante perceber que temos uma varivel do tipo struct que ir armazenar o tipo de mensagem e a prpria mensagem. Logo a seguir temos o identificador da nossa mensagem que um valor inteiro e temos a string a ser enviada.
key_t chv_f_msg; /* Declarao da varivel do tipo key_t usada para obter o ID do objecto IPC (Clente ou Servidor)*/ /* Criao da varivel (message buffer) do tipo struct que armazena as variveis "tipo de mensagem e a mensagem propriamente dita" */ struct mi_m { long tipo; char texto[251]; } mensagem; /* ID da fila de mensagem */ int num_f_msg; /* Cadeia de caracteres com a mensagem para ser enviada */ char string[] = "\n Mantenha a informao livre!\n";
Nesta seco seguinte, importante ter a funo ftok(), como o processo para a criao da chave da mensagem.
A funo msgget permite criar ou obter o acesso a uma fila de mensagem, o retorno do valor -1 no havendo a criao do identificador da mensagem o programa retorna em erro Obrigatoriamente a mensagem deve ter um identificado de maneira a permitir a sua comunicao com outros processos. A funo msgsnd(), permite enviar uma mensagem a estrutura de fila de mensagem j criada. Caso haver algum erro de envio, o valor a ser retornado ser -1. E por ltimo iremos simplesmente exibir a mensagem enviada, atravs de uma estrutura denominada de Fila de mensagem.
19
/* Copiar a string para o referido destino */ mensagem.tipo=1; strcpy(mensagem.texto,string); /* Funo usada para gerar valores das chaves (ID) tanto do cliente como do servidor que correm no directorio actual (em execuo) */ chv_f_msg = ftok(".", 'a'); /* A Funo msgget() serve para criar ou obter o ID da fila de mensagem.*/ if ((num_f_msg = msgget(chv_f_msg,IPC_CREAT | 0660 ))==-1) /* Retorna -1 em caso de erro, caso no, retorna o identificador da fila de mensagens*/ { perror( "Erro na abertura da fila de mensagens" ); exit(-1); } /* A Funo msgsnd() serve para enviar uma mensagem fila de mensagens j criada. */ if (msgsnd(num_f_msg,&mensagem,255,IPC_NOWAIT)==-1) /* Retorna -1 em caso de 3.3.3. SINAIS erro, caso no, envia a mensagem na fila de mensagem */ { perror( "Erro no envio da mensagem" ); exit(-1); } printf(" %s \n", mensagem.texto); /*Imprime a mensagem no ecr*/
}
/* Cpia da definio da estrutura 'sigaction', presente na header file 'signal.h', que examina e muda a aco de um sinal*/ struct sigaction act; /* Funo de manipulao de possveis sinais recebidos*/ void sighandler(int signum, siginfo_t *info, void *ptr)
/* Instruo que escreve o nmero e a origem de sinais recebidos*/ printf("Received signal %d\n", signum); printf("Signal originates from process %lu\n", (unsigned long)info->si_pid); } /* Funo principal, onde o programa inicia a execuo. */ int main() { /* Instruo que escreve o pid do processo corrente na tela */ printf("I am %lu\n", (unsigned long)getpid()); /* Definio dos princpios de utilizao dos sinais */ memset(&act, 0, sizeof(act)); act.sa_sigaction = sighandler; act.sa_flags = SA_SIGINFO; sigaction(SIGTERM, &act, NULL); /* Funo que inicia a espera por CTRL+C... */ sleep(100); /* Retorno da funo main() */ return 0;
20
3.3.4. SOCKETPAIR
3.3.4.1. VARIVEIS DECLARADAS Neste programa foram declarados, um array de dois inteiros que ir armazenzar o par de sockets, dois ponteiros que iro permitir que sejam apontados no acto de visualizao de suas mensagens. E as Strings a serem armazenadas em determinadas localizaes.
int s[2]; void *ptrc_0,*ptrc_1; /* Declarao de dois ponteiros */ char cadeia_0[] = "Mantenha a informao livre!\n"; /* Declarao de uma String */ char cadeia_1[] = "ervil informao a ahnetnaM!\n"; /* Declarao de uma String */ ptrc_0=malloc(128); /* Alocao dinmica de memria */ Logo a seguir, tal como est o comentrio, achei prefervel ordenar o trabalho de modos a que o processo filho ir fazer a escrita da string na memria e o processo pai ira efectuar a leitura atravs de ponteiros. Com mais detalhe, visto que no acto de criao atravs do fork, o processo filho preparado para escrever uma cadeia de 27 caracteres, enquanto que o processo pai preparado para fazer a leitura dessa cadeia.
21
/* Nas condies seguintes: O processo filho ir escrever a cadeia as cadeias de 27 caracteres e o processo pai ir ler o que o processo filho escreveu atravs do endereo de memria */ if (fork()== 0) { write (s[0],cadeia_0,27); write (s[1],cadeia_1,27); printf("\n\n O Processo filho escreve nos endereo:\n %p e %p",ptrc_0, ptrc_1); } else { read (s[0],ptrc_0,27); read (s[1],ptrc_1,27);
22
Top:= $(Shell Pdw) semaforo: memm.c g++ -ansi -pedantic -Wall -o memoria memm.c $(Top) semlib.o : semlib.c g++ -ansi -pedantic -Wall -c semlib.c shmlib.o : shmlib.c g++ -ansi -pedantic -Wall -c shmlib.c install:
mv semaforo..
Este ficheiro descreve a funcionalidade e o objectivo principal do trabalho. O processo pai escreve os nmeros inteiros de 1 a 20, enquanto que o filho faz a leitura e imprime no ecr. Neste programa, foi implementado uma memria partilhada com o auxlio de semforo. A funo a seguir (ShmDef), reserva uma zona de memria partilhada, com o tamanho suficiente para armazenar um array de 20 inteiros.
23
As condies neste trabalho esto devidamente descritas e em anexo. Por uma questo de uma boa apresentao, foi prefervel descrever de forma sntetica a forma geral do processo. semlib.c: Biblioteca do semforo
Este ficheiro contm um conjunto de de funes que possibilitam operar com os mecanismos de semforos existentes em Linux.
int SemDef( int inicial_value); int SemSignal(int descr_sem); int SemWait( int descr_sem); int SemDel( int descr_sem);
A Funo SemDef(), permite definir um semforo no kernel, privado a um determinado processo e os seus filhos. A funo SemSignal() o descritor que permite incrementar o valor do semforo. A funo SemWait() semforo. A Funo SemDel(), Permite disponibilizar os recursos que so ocupados pelo semforo no sistema operativo. shmlib.c: Biblioteca da memria partilhada. Esta constituida por duas funes: ShmDef () e ShmDel(). A primeira funo serve para a obteno de uma zona de partilhada enquanto que a segunda permite tornar disponivel uma zona de memria partilhada privada. implementa o Wait que permite decrementar o valor do
O size define o comprimento da zona memoria partilhada. O descr identifica perante o Kernel a zona de memoria partilhada que foi criada.
24
4. CONCLUSO
Este trabalho permitiu ter a noo geral sobre processos em Linux. Permitiu receber uma grande incentivao de maneira a continuar com as pesquisas e estar bem preparado para prximos testes a surgirem. Verifiquei que para um ambiente acadmico o Linux torna-se como um grande suporte no ensino sobre sistemas operativos, por permitir efectuar testes reais sobre suas funes. Permitiu tambm ter a noo real sobre o Linux como um sistema operativo bastante seguro, e ter contacto prtico sobre o seu desenvolvimento como um programador pertencente a sua comunidade.
25
REFERNCIAS
PEREIRA, Pereira (2005) Linux Curso completo. 5 ed. Lisboa: FCA Editora. MITCHELL, Mark; et. al. (2001) Advanced Linux Programming 1 ed. Indiana: New Riders.
CRESPO, Rui (2001) Processadores de linguagens Da Concepo implementao. 2 ed. Lisboa: IST Press.
KOWALTOWSKI, Tomasz (2010) Estrutura de dados e tcnicas de programao [Em linha]. [Consult. 06 Mai. 2012]. Disponvel em WWW:<http://colibri.ic.unicamp.br/~tomasz/cursos/mc202/transp_ho_acum.pdf>. LOPES, Arthur (1999) Estrutura de dados Para a construo de softwares. 1 Ed. Canoas: Editora da Ulbra. NETO, Antnio (1998) Explorando recurso e fractals [Em linha]. [Consult. 06 Mai. 2012].Disponvel:WWW:<http://lsm.dei.uc.pt/ribie/docfiles/txt200342415342159M.PDF >.
GUARI, Eiton (1989) Introduction to theory of the computation. [Em linha]. [Consult.06.Mai.2012].Disponvel:WWW:<http://www.cse.ohiostate.edu/~gurari/theory-bk/theory-bk.html>.
26
ANEXOS
LISTA DE ANEXOS
Anexo A - Cdigo fonte do programa principal de memria partilhada Anexo B - Cdigo fonte da biblioteca de memria partilhada Anexo C - Cdigo fonte da biblioteca de semforos Anexo D - Cdigo do Makefile
28
ANEXO A
Cdigo fonte do programa principal de memria partilhada
29
main(void) { int *apt; int f; int pid; int s; /* Descritor do semforo */ int shmd; /* Descritor da memria partilhada */ int erro; apt = (int *) ShmDef(sizeof(int)*20, &shmd); if (apt == NULL) { perror("Erro na obteno de memoria partilhada\n"); exit(-1); } /* Define um semforo com valor incial igual a 1 */ s = SemDef(1); if (s == -1) { perror("Erro na criao do semforo"); exit(-1); } pid = fork(); if (pid > 0) { /* Cdigo do processo pai */ SemWait(s); printf("Pai: a escrever na memria partilhada!!\n"); /* Inicio da seco crtica */ for(f=0; f < 20; f++) { apt[f] = f; } sleep(3); printf("Pai: a sair da seco crtica\n"); /* Fim da seco crtica */ SemSignal(s); /* Coloca o pai a espera do filho */ wait(); /* Remove a zona de memria partilhada */ erro = ShmDel(shmd); if (erro == -1) {
30
printf("Pai: Erro em ShmDel!!!"); exit(-1); } /* Remove o semforo */ erro = SemDel(s); if (erro == -1) { printf("Pai: Erro em SemDel!!!"); exit(-1); } printf("Pai:Processo pai a terminar!!!\n"); } else { /* Cdigo do filho */ sleep(3); printf("Filho: 'a espera para entrar na seco crtica!!\n"); /* Inicio da seco crtica */ SemWait(s); printf("Filho: a executar a seco crtica\n"); for(f=0; f < 20; f++) { printf("Filho: f=%d val=%d\n", f, apt[f]); sleep(1); } printf("Filho: a sair da seco crtica\n"); SemSignal(s); /* Fim da seco crtica */ exit(0); return (0); } }
31
ANEXO B
Cdigo fonte da biblioteca da memria partilhada
32
/* obteno de um descriptor para a zona de memria partilhada */ descritor = shmget(IPC_PRIVATE, size, IPC_CREAT|0600); if (descritor == -1) { perror("Erro em shmget, ao alocar memria partilhada!"); return(NULL); } else { /* Obtenao do apontador para a area de memoria partilhada */ tst = (void *) shmat(descritor, NULL, 0); if ((int)tst == -1) { perror("Erro em shmat, ao alocar memria partilhada!"); return(NULL); } } /* fim do if */ *descr = descritor; return(tst); }
int ShmDel(int descr) { int res; res = shmctl(descr, IPC_RMID, NULL); if (res == -1) { perror("Erro em ShmDel!"); } return(res); }
33
ANEXO C
Cdigo fonte da biblioteca de semforo
34
union semun { int val; /* value struct semid_ds *buf; /* */ unsigned short int *array; /* struct seminfo *__buf; /* };
for SETVAL */ buffer for IPC_STAT & IPC_SET array for GETALL & SETALL */ buffer for IPC_INFO */
int SemDef(int valor_inicial) { int descr_sem; int erro; /* Criao do Semforo */ descr_sem = semget(IPC_PRIVATE, 1, IPC_CREAT|0777); if (descr_sem == -1) { perror("Erro ao criar o semforo!"); return(-1); } /* Inicializa o valor do semforo */ erro = semctl(descr_sem, 0, SETVAL, valor_inicial); if (erro == -1) { perror("Erro ao atribuir valor inicial ao semforo!"); return(-1); } return(descr_sem); }
int SemSignal(int descr_sem) { struct sembuf aux; int erro; /* Preenche a estrutura que permite operar sobre o semforo */ aux.sem_num = 0; aux.sem_op = 1; aux.sem_flg = 0; /* Excuta a operao */ erro = semop(descr_sem, &aux, 1);
35
int SemWait(int descr_sem) { struct sembuf aux; int erro; /* Preenche a estrutura que permite operar sobre o semforo */ aux.sem_num = 0; aux.sem_op = -1; aux.sem_flg = 0; /* Excuta a operao */ erro = semop(descr_sem, &aux, 1); if (erro == -1) { perror("Erro em Wait!"); return(-1); } /* Em caso de sucesso da funo */ return(0); } int SemDel(int descr_sem) { union semun aux; return(semctl(descr_sem, 0, IPC_RMID, aux)); }
36
ANEXO D
Cdigo do Makefile
37
Top:= $(Shell Pdw) semaforo: memm.c g++ -ansi -pedantic -Wall -o memoria memm.c $(Top) semlib.o : semlib.c g++ -ansi -pedantic -Wall -c semlib.c shmlib.o : shmlib.c g++ -ansi -pedantic -Wall -c shmlib.c install: mv semaforo.. clean: rm*
38