28
U NIVERSIDADE L USÍADA DE L ISBOA Faculdade de Ciências da Economía e da Empresa Mestrado em Ciências da Computação Primeiro relatório de Comunicação entre processos (IPC) Hercílio Rui Dinis Duarte Lisboa Maio 2012

Comunicação entre processos(IPC) em C/Linux

Embed Size (px)

DESCRIPTION

Este trabalho surge com o objectivo prático de fazer o estudo sobre a comunicação entre processos.De formas a se perceber os conceitos, foram propostos a análise de erros em programas criados, fazer correcções e a seguir fazer uma comparação com outros programas de maneiras a interiorizar a aplicação e diferença entre alguns tipos de IPC.De forma a entrar bem no tema, farei uma breve abordagem conceptual do termo “Linux”, baseando em definições de alguns autores e logo a seguir é que entrarei nos IPC.

Citation preview

U N I V E R S I D A D E L U S Í A D A D E L I S B O A

F a c u ld ad e de C i ê nc i as d a Ec o n o mí a e d a Em p re s a

Mestrado em Ciências da Computação

Primeiro relatório de Comunicação entre processos (IPC)

Hercílio Rui Dinis Duarte

Lisboa

Maio 2012

U N I V E R S I D A D E L U S Í A D A D E L I S B O A

F a c u ld ad e de C i ê nc i as e d a Ec o no mí a d a Em p re s a

Mestrado em Ciências da Computação

Primeiro relatório de comunicação entre processos (IPC)

Hercílio Rui Dinis Duarte

Lisboa

Maio 2012

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 13

SUMÁRIO

1. Introdução .................................................................................................... 14

2. Breve abordagem sobre o Linux .................................................................. 15

2.1. Utilizadores, tarefas e processos ........................................................... 15

2.2. Sistema de ficheiros............................................................................... 15

3. Comunicação 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. Memória partilhada .......................................................................... 16

3.2. Sincronização entre processos .............................................................. 17

3.2.1. Sinais ............................................................................................... 17

3.2.2. Semáforos ....................................................................................... 17

3.3. A Correção dos programas .................................................................... 17

3.3.1. O programa sobre pipes .................................................................. 17

Variáveis declaradas ................................................................. 17 3.3.1.1.

3.3.2. O Programa sobre Filas de mensagens .......................................... 18

Variáveis declaradas ................................................................. 19 3.3.2.1.

3.3.3. Sinais ............................................................................................... 20

3.3.4. Socketpair ....................................................................................... 21

Variáveis declaradas ................................................................. 21 3.3.4.1.

3.4. O Programa da memória partilhada ....................................................... 22

4. Conclusão .................................................................................................... 25

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 14

1. INTRODUÇÃO

Este trabalho surge com o objectivo prático de fazer o estudo sobre a comunicação

entre processos.

De formas a se perceber os conceitos, foram propostos a análise de erros em

programas criados, fazer correções e a seguir fazer uma comparação com outros

programas de maneiras a interiorizar a aplicação e diferença entre alguns tipos de

IPC.

De forma a entrar bem no tema, farei uma breve abordagem conceptua do termo

“Linux”, baseando em definições de alguns autores e logo a seguir é que entrarei nos

IPC.

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 15

2. BREVE ABORDAGEM SOBRE O LINUX

2.1. UTILIZADORES, TAREFAS E PROCESSOS

O sistema operativo linux é um sistema multitarefa e multiutilizador. Isso implica que o

sistema tem de impedir que os utilizadores possam interferir no trabalho uns dos

outros. Este conceito respeita exactamente o principio da confidencialidade.

(PEREIRA Paulo, 2005)

O Linux é tido como um dos sistemas operativos mais seguros, devido a aplicação do

coneceito de Superutilizador. Para alterarmos ficheiro do sistema precisamos estar

logados como root, isto significa que o aconselhável para um utilizador é de jamais

acessar com os privilégios de Superutilizador.

Segundo FERREIRA (2005), os poderes de Superutilizador são quase infinitos e por

isso esse modo deve ser sempre usando cuidados, porque qualquer erro pelo

utilizador root pode causar consequências desastrosas.

Suponhamos que existe a tentativa de envio de virus para um sistema Linux, este não

poderá propagar-se devido a realidade de muitos utilizadores estarem logados com

privilégios normais.

A tentativa do Linux como um sistema operativo Open Source tornou-o bastante forte

e robusto. Pois o código fonte de suas versões estão disponíveis para que possam ser

utilizados por qualquer pesssoa, de maneiras a permitir uma continuidade para a

comunidade que utiliza.

2.2. SISTEMA DE FICHEIROS

A origem da árvore de directorias do sistema Linux é marcada pela directoria root que

é representada pelo caracter “ / ”. A seguir ao root existem as subdirectorias descri na

tabela a seguir:

“The most exciting developments for Linux will happen in user space, not kernel space. The changes in the kernel will seem small compared to what’s happening further out in the system.” Linus Trovalds

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 16

Directório Descrição /bin Arquivos binários de comandos essenciais do

sistema.

/boot Arquivos do arranque do sistema

/dev

Contém ficheiros que representam todos os dispositivos de hardware e periféricos de sistema.

/etc Contém a maioria dos ficheiros de configuração do sistema operativo.

/home Diretórias de trabalho do utilizador.

/lib Contém bibliotecas necessárias para que o sistema e os programas possam funcionar.

/mnt Diretório de montagem de dispositivos, sistemas de arquivos e partição

/opt Para instalação de programas não oficiais da distribuição.

/proc Diretório virtual (RAM) onde rodam os processos ativos.

/root Diretório local do superusuário (root).

/sbin Arquivos de sistema essenciais (binários do superusuário).

/tmp Arquivos temporários gerados por alguns utilitários.

/usr Arquivos de usuários nativos da distribuição.

/usr/local Para instalação de programas não oficiais da distribuição.

/usr/src Arquivos fontes do sistema necessários para compilar o kernel.

/var Arquivos de log e outros arquivos variáveis.

3. COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Que em inglês significa Inter-Process Communication, trata-se de um conjunto de

mecanismos de manipulação que permitem efectuar a transferência de informação

entre processos.

(MITCHELL Mark; et. al. (2001), definem simplesmente como sendo a transferência de

dados entre processos.

3.1. TIPOS DE IPC

3.1.1. PIPES

3.1.2. FILAS DE MENSAGENS

3.1.3. MEMÓRIA PARTILHADA

Tabela 1 – A árvore de directorias do Linux (PEREIRA Paulo, 2005)

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 17

3.2. SINCRONIZAÇÃO ENTRE PROCESSOS

3.2.1. SINAIS

3.2.2. SEMÁFOROS

3.3. A CORREÇÃO DOS PROGRAMAS

Este subcapítulo faz parte do primeiro trabalho prático da disciplina de Tecnologías e

Sistemas da computação, de maneira a praticar-se e de forma mais direrecta e

perceber os conceitos sobre os IPC. Além de fazer-se a correção dos programas, o

grande objectivo será o estudo e as suas interpretações.

3.3.1. O PROGRAMA SOBRE PIPES

VARIÁVEIS DECLARADAS 3.3.1.1.

Essencial descrever exactamente este trecho, para se ter noção das intenções do

programa.

No acto de criação de um Pipe, é essencial pensar na declaração de seus estremos.

Como podemos ver, para um Pipe, este será sempre um array inteiro de dimensão 2

denominado como array dos file descriptor (descritores de ficheiro) devido a sua

utilidade. Quando se cria um Pipe, O sistema retorna os dois descritores que

representam o lado de escrita e o lado de leitura.

Na condição a seguir, começa-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 comunicação sem erro algum. Para este caso, quando

int fd[2]; /* Declaração da variável "file descriptor", irá armazenar os serviços de escrita e leitura */ char b_entr[BUFSIZ]; /* Declaração da variavel para Alocação estática do buffer de memória*/ pid_t childpid; /* Declaração da variável que armazena o ID do Processo Filho*/ pipe(fd); /* Função Pipe com paramentro que retorna fd (0) e fd(1), que são 2 inteiros */

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 18

o processo for filho, este irá fechar o lado receptor do Pipe e simplesmente poder

escrever.

Contrariamente, caso o processo for pai, este irá fechar o lado emissor do Pipe e

simplesmente permitir a sua leitura, também de maneiras a permitir a continuidade da

comunicação.

3.3.2. O PROGRAMA SOBRE FILAS DE MENSAGENS

/* Na condição a seguir é testado a condição de criação do processo filho, caso concretizar-se é inicializada a função 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 padrão */ execlp ( "ps","-al",0); /*Sobrepor o código do processo filho com o do comando "ps" */ close (fd[1]); exit(0); }

/* Execução do processo pai */ else { /* Esta função serve para forçar uma paragem na execução do processo pai até que o processo filho termine a sua execução*/ wait (0); close (fd[1]); /* O índice 1 Fecha o lado emissor do Pipe */ printf("Eu sou o processo pai! \n"); /* Condição de fazer a leitura do file descriptor fd(0) e saber o tamanho do buffer através 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);

}

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 19

VARIÁVEIS DECLARADAS 3.3.2.1.

Quanto as variáveis, é importante perceber que temos uma variável do tipo struct que

irá armazenar o tipo de mensagem e a própria mensagem. Logo a seguir temos o

identificador da nossa mensagem que é um valor inteiro e temos a string a ser

enviada.

Nesta secção seguinte, é importante ter a função ftok(), como o processo para a

criação da chave da mensagem.

A função msgget permite criar ou obter o acesso a uma fila de mensagem, o retorno

do valor -1 não havendo a criação do identificador da mensagem o programa retorna

em erro Obrigatoriamente a mensagem deve ter um identificado de maneira a permitir

a sua comunicação com outros processos.

A função 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, atravês de uma

estrutura denominada de Fila de mensagem.

key_t chv_f_msg; /* Declaração da variável do tipo key_t usada para obter o ID do objecto IPC (Clente ou Servidor)*/ /* Criação da variável (message buffer) do tipo struct que armazena as variáveis "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 informação livre!\n";

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 20

3.3.3. SINAIS

/* Copiar a string para o referido destino */ mensagem.tipo=1; strcpy(mensagem.texto,string); /* Função usada para gerar valores das chaves (ID) tanto do cliente como do servidor que correm no directorio actual (em execução) */ chv_f_msg = ftok(".", 'a'); /* A Função 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 não, retorna o identificador da fila de mensagens*/ { perror( "Erro na abertura da fila de mensagens" ); exit(-1); } /* A Função 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 erro, caso não, 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ã*/

}

/* Cópia da definição da estrutura 'sigaction', presente na header file 'signal.h', que examina e muda a acção de um sinal*/ struct sigaction act; /* Função de manipulação de possíveis sinais recebidos*/

void sighandler(int signum, siginfo_t *info, void *ptr)

/* Instrução que escreve o número e a origem de sinais recebidos*/ printf("Received signal %d\n", signum); printf("Signal originates from process %lu\n", (unsigned long)info->si_pid); } /* Função principal, onde o programa inicia a execução. */ int main() { /* Instrução que escreve o pid do processo corrente na tela */ printf("I am %lu\n", (unsigned long)getpid()); /* Definição dos princípios de utilização dos sinais */ memset(&act, 0, sizeof(act)); act.sa_sigaction = sighandler; act.sa_flags = SA_SIGINFO; sigaction(SIGTERM, &act, NULL); /* Função que inicia a espera por CTRL+C... */ sleep(100);

/* Retorno da função main() */ return 0;

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 21

3.3.4. SOCKETPAIR

VARIÁVEIS DECLARADAS 3.3.4.1.

Neste programa foram declarados, um array de dois inteiros que irá armazenzar o par

de sockets, dois ponteiros que irão permitir que sejam apontados no acto de

visualização de suas mensagens. E as Strings a serem armazenadas em

determinadas localizações.

Logo a seguir, tal como está o comentário, achei preferível ordenar o trabalho de

modos a que o processo filho irá fazer a escrita da string na memória e o processo pai

ira efectuar a leitura atravês de ponteiros.

Com mais detalhe, é visto que no acto de criação atravês 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.

int s[2];

void *ptrc_0,*ptrc_1; /* Declaração de dois ponteiros */

char cadeia_0[] = "Mantenha a informação livre!\n"; /* Declaração de uma String

* /

char cadeia_1[] = "ervil informação a ahnetnaM!\n"; /* Declaração de uma String

*/

ptrc_0=malloc(128); /* Alocação dinâmica de memória */

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 22

3.4. O PROGRAMA DA MEMÓRIA PARTILHADA

Neste programa trabalhei com 4 ficheiros importantes:

Makefile: Como estudado, o makefile permite automatizar o processo de

criação dos programas objectos. Mas para tal é necessário obedecer a regras

de dependencia entre o objecto a ser criado e os devidos códigos fontes como

vimos no código a seguir trabalhado:

/* Nas condições 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 atravês do

endereço de memória */

if (fork()== 0)

{ write (s[0],cadeia_0,27);

write (s[1],cadeia_1,27);

printf("\n\n O Processo filho escreve nos endereço:\n %p e %p",ptrc_0,

ptrc_1);

}

else

{ read (s[0],ptrc_0,27);

read (s[1],ptrc_1,27);

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 23

memm.c: Este é o programa principal da nossa memória partilhada.

Este ficheiro descreve a funcionalidade e o objectivo principal do trabalho. O processo

pai escreve os números inteiros de 1 a 20, enquanto que o filho faz a leitura e imprime

no ecrâ.

Neste programa, foi implementado uma memória partilhada com o auxílio de

semáforo.

A função a seguir (ShmDef), reserva uma zona de memória partilhada, com o tamanho

suficiente para armazenar um array de 20 inteiros.

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..

apt = (int *) ShmDef(sizeof(int)*20, &shmd);

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 24

As condições neste trabalho estão devidamente descritas e em anexo. Por uma

questão de uma boa apresentação, foi preferível descrever de forma síntetica a forma

geral do processo.

semlib.c: Biblioteca do semáforo

Este ficheiro contém um conjunto de de funções que possibilitam operar com os

mecanismos de semáforos existentes em Linux.

A Função SemDef(), permite definir um semáforo no kernel, privado a um determinado

processo e os seus filhos.

A função SemSignal() é o descritor que permite incrementar o valor do semáforo.

A função SemWait() implementa o Wait que permite decrementar o valor do

semáforo.

A Função SemDel(), Permite disponibilizar os recursos que são ocupados pelo

semáforo no sistema operativo.

shmlib.c: Biblioteca da memória partilhada. Esta é constituida por duas

funções: ShmDef () e ShmDel(). A primeira função serve para a obtenção de

uma zona de partilhada enquanto que a segunda permite tornar disponivel uma

zona de memória partilhada privada.

O size define o comprimento da zona memoria partilhada. O descr identifica perante o Kernel a zona de memoria partilhada que foi criada.

void *ShmDef(int size, int *descr)

int ShmDel(int descr)

int SemDef( int inicial_value); int SemSignal(int descr_sem); int SemWait( int descr_sem);

int SemDel( int descr_sem);

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 25

4. CONCLUSÃO

Este trabalho permitiu ter a noção geral sobre processos em Linux. Permitiu receber

uma grande incentivação de maneira a continuar com as pesquisas e estar bem

preparado para próximos testes a surgirem.

Verifiquei que para um ambiente acadêmico o Linux torna-se como um grande suporte

no ensino sobre sistemas operativos, por permitir efectuar testes reais sobre suas

funções.

Permitiu também ter a noção real sobre o Linux como um sistema operativo bastante

seguro, e ter contacto prático sobre o seu desenvolvimento como um programador

pertencente a sua comunidade.

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 26

REFERÊNCIAS

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 Concepção à

implementação. 2ª ed. Lisboa: IST Press.

KOWALTOWSKI, Tomasz (2010) – Estrutura de dados e técnicas de programação

[Em linha]. [Consult. 06 Mai. 2012]. Disponível em

WWW:<http://colibri.ic.unicamp.br/~tomasz/cursos/mc202/transp_ho_acum.pdf>.

LOPES, Arthur (1999) – Estrutura de dados – Para a construção de softwares. 1ª Ed.

Canoas: Editora da Ulbra.

NETO, António (1998) – Explorando recursão e fractals [Em linha]. [Consult. 06 Mai.

2012].Disponível: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].Disponível:WWW:<http://www.cse.ohio-

state.edu/~gurari/theory-bk/theory-bk.html>.

ANEXOS

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS (IPC)

Hercílio Rui Dinis Duarte 28

LISTA DE ANEXOS

Anexo A - Código fonte do programa principal de memória partilhada

Anexo B - Código fonte da biblioteca de memória partilhada Anexo C - Código fonte da biblioteca de semáforos Anexo D - Código do Makefile

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 29

ANEXO A Código fonte do programa principal de memória partilhada

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 30

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include "semlib.c"

#include "shmlib.c"

main(void)

{

int *apt;

int f;

int pid;

int s; /* Descritor do semáforo */

int shmd; /* Descritor da memória partilhada */

int erro;

apt = (int *) ShmDef(sizeof(int)*20, &shmd);

if (apt == NULL)

{

perror("Erro na obtenção de memoria partilhada\n");

exit(-1);

}

/* Define um semáforo com valor incial igual a 1 */

s = SemDef(1);

if (s == -1)

{

perror("Erro na criação do semáforo");

exit(-1);

}

pid = fork();

if (pid > 0)

{

/* Código do processo pai */

SemWait(s);

printf("Pai: a escrever na memória partilhada!!\n");

/* Inicio da secção crítica */

for(f=0; f < 20; f++)

{

apt[f] = f;

}

sleep(3);

printf("Pai: a sair da secção crítica\n");

/* Fim da secção crítica */

SemSignal(s);

/* Coloca o pai ‘a espera do filho */

wait();

/* Remove a zona de memória partilhada */

erro = ShmDel(shmd);

if (erro == -1)

{

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 31

printf("Pai: Erro em ShmDel!!!");

exit(-1);

}

/* Remove o semáforo */

erro = SemDel(s);

if (erro == -1)

{

printf("Pai: Erro em SemDel!!!");

exit(-1);

}

printf("Pai:Processo pai a terminar!!!\n");

}

else

{

/* Código do filho */

sleep(3);

printf("Filho: 'a espera para entrar na secção crítica!!\n");

/* Inicio da secção crítica */

SemWait(s);

printf("Filho: a executar a secção crítica\n");

for(f=0; f < 20; f++)

{

printf("Filho: f=%d val=%d\n", f, apt[f]);

sleep(1);

}

printf("Filho: a sair da secção crítica\n");

SemSignal(s);

/* Fim da secção crítica */

exit(0);

return (0);

}

}

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 32

ANEXO B Código fonte da biblioteca da memória partilhada

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 33

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <unistd.h>

#include <stdio.h>

void *ShmDef(int size, int *descr)

{

int descritor;

void *tst;

/* obtenção de um descriptor para a zona de memória partilhada */

descritor = shmget(IPC_PRIVATE, size, IPC_CREAT|0600);

if (descritor == -1)

{

perror("Erro em shmget, ao alocar memória partilhada!");

return(NULL);

}

else

{

/* Obtençao do apontador para a area de memoria partilhada */

tst = (void *) shmat(descritor, NULL, 0);

if ((int)tst == -1)

{

perror("Erro em shmat, ao alocar memória 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);

}

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 34

ANEXO C

Código fonte da biblioteca de semáforo

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 35

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <unistd.h>

#include <ctype.h>

union semun

{

int val; /* value for SETVAL */

struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET

*/

unsigned short int *array; /* array for GETALL & SETALL */

struct seminfo *__buf; /* buffer for IPC_INFO */

};

int SemDef(int valor_inicial)

{

int descr_sem;

int erro;

/* Criação do Semáforo */

descr_sem = semget(IPC_PRIVATE, 1, IPC_CREAT|0777);

if (descr_sem == -1)

{

perror("Erro ao criar o semáforo!");

return(-1);

}

/* Inicializa o valor do semáforo */

erro = semctl(descr_sem, 0, SETVAL, valor_inicial);

if (erro == -1)

{

perror("Erro ao atribuir valor inicial ao semáforo!");

return(-1);

}

return(descr_sem);

}

int SemSignal(int descr_sem)

{

struct sembuf aux;

int erro;

/* Preenche a estrutura que permite operar sobre o semáforo */

aux.sem_num = 0;

aux.sem_op = 1;

aux.sem_flg = 0;

/* Excuta a operação */

erro = semop(descr_sem, &aux, 1);

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 36

if (erro == -1)

{

perror("Erro em Signal!");

return(-1);

}

/* Em caso de sucesso da função */

return(0);

}

int SemWait(int descr_sem)

{

struct sembuf aux;

int erro;

/* Preenche a estrutura que permite operar sobre o semáforo */

aux.sem_num = 0;

aux.sem_op = -1;

aux.sem_flg = 0;

/* Excuta a operação */

erro = semop(descr_sem, &aux, 1);

if (erro == -1)

{

perror("Erro em Wait!");

return(-1);

}

/* Em caso de sucesso da função */

return(0);

}

int SemDel(int descr_sem)

{

union semun aux;

return(semctl(descr_sem, 0, IPC_RMID, aux));

}

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 37

ANEXO D

Código do Makefile

PRIMEIRO RELATÓRIO DE COMUNICAÇÃO ENTRE PROCESSOS

Hercílio Rui Dinis Duarte 38

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*