next up previous
Next: Função shmdt() Up: Memória Compartilhada Previous: A Função shmctl()

Função shmat()

       # include <sys/types.h>
       # include <sys/shm.h>

       void *shmat ( int shmid, const void *shmaddr, int shmflg )

Valor de retorno: endereço do segmento de memória compartilhada, ou -1 em caso de erro.

Antes que o processo possa utilizar um segmento de memória criado por outro processo, ele deve inicialmente se acoplar a esse segmento. É exatamente a função shmat() que faz esse papel. Ela ''acopla'' (attaches) o segmento de memória compartilhada identificado por shmid ao segmento de dados do processo que a chamou. A função exige três argumentos: o identificador do segmento shmid, um ponteiro shmaddr especificando o endereço de acoplamento e um conjunto de flags, shmflg.

O endereço de acoplamento é especificado através dos dois últimos parâmetros shmaddr e shmflg:

Observações:

Quando a função shmat é chamada, o sistema verifica se existe espaço suficiente no espaço de endereçamento da memória virtual do processo ao qual deve ser acoplado o segmento de memória compartilhada. Se esta não for o caso, um código de erro será retornado. Note ainda que não existe efetivamente uma cópia da zona de memória, mais simplesmente um redirecionamento do endereçamento para o segmento de memória que está sendo compartilhado.

Exemplo:

Suponha que um segmento de memória compartilhada tenha sido criado anteriormente através do programa test_shmget. O programa test_shmat vai reacoplar um processo ao segmento e escrever na memória comum, uma cadeia de caracteres. O programa test_shmat2 irá então se acoplar à mesma zona de memória e ler então seu conteúdo. O programa test_shmctl irá então obter informações sobre o segmento de memória antes de destruí-lo.

                /* arquivo test_shmat.c */

/*
 * exemplo de utilizacao de shmat()
 * escrita num segmento de memoria compartilhada
 */

#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

#define KEY 123
#define KEY 123
#define MSG "Mensagem escrita na memoria comum"

int main()
{
  int shmid ;  /* identificador da memoria comum */
  int size = 1024 ;
  char *path="nome_de_arquivo_existente" ;
  char *mem ;
  int flag = 0;

     /*
     * recuperacao do shmid 
     */
     if (( shmid = shmget(ftok(path,(key_t)KEY), size,0)) == -1) {
          perror("Erro no shmget") ;
          exit(1) ;
     }
     printf("Sou o processo com pid: %d \n",getpid()) ;
     printf("Identificador do segmento recuperado: %d \n",shmid) ;
     printf("Este segmento e associado a chave unica: %d\n",
                   ftok(path,(key_t)KEY)) ;
    /*
     * acoplamento do processo a zona de memoria
     * recuperacao do pornteiro sobre a area de memoria comum
     */
     if ((mem = shmat (shmid, 0, flag)) == (char*)-1){
          perror("acoplamento impossivel") ;
          exit (1) ;
     }

    /*
     * escrita na zona de memoria compartilhada
     */
     strcpy(mem,MSG);
     exit(0);
}

                 /* fichier test_shmat2.c */

/*
 * programa para ler o conteudo de um segmento de memoria
 * compartilhada que foi preenchido anteriormente por outro processo
 */

#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

#define KEY 123

int main()
{
  int shmid ;  /* identificateur de la memoire commune */
  int size = 1000 ;
  char *path="nome_de_arquivo_existente" ;
  char *mem ;
  int flag = 0 ;

      /*
     * recuperacao do shmid 
     */
     if (( shmid = shmget(ftok(path,(key_t)KEY), size,0)) == -1) {
          perror("Erro no shmget") ;
          exit(1) ;
     }
     printf("Sou o processo com pid: %d \n",getpid()) ;
     printf("Identificador do segmento recuperado: %d \n",shmid) ;
     printf("Este segmento e associado a chave unica: %d\n",
                   ftok(path,(key_t)KEY)) ;
    /*
     * acoplamento do processo a zona de memoria
     * recuperacao do pornteiro sobre a area de memoria comum
     */
     if ((mem = shmat (shmid, 0, flag)) == (char*)-1){
          perror("acoplamento impossivel") ;
          exit (1) ;
     }
    /*
     * tratamento do conteudo do segmento
     */
     printf("leitura do segmento de memoria compartilhada:\n");
     printf("\t==>%s\n",mem) ;
     exit(0);
}

Resultado da execução:

euler:~/> test_shmget
Identificador do segmento: 41600 
Este segmento e associado a chave unica: 2063804629
euler:~/> test_shmat
Sou o processo com pid: 1250 
Identificador do segmento recuperado: 41600 
Este segmento e associado a chave unica: 2063804629
euler:~/> test_shmat2
Sou o processo com pid: 1251
Identificador do segmento recuperado: 41600 
Este segmento e associado a chave unica: 2063804629
leitura do segmento de memoria compartilhada:
        ==>Mensagem escrita na memoria comum
euler:~/> test_shmctl
ESTADO DO SEGMENTO DE MEMORIA COMPARTILHADA 41600
ID do usuario proprietario: 1145
ID do grupo do proprietario: 1000
ID do usuario criador: 1145
ID do grupo criador: 1000
Modo de acesso: 384
Tamanho da zona de memoria: 1024
pid do criador: 1249
pid  (ultima operacao): 1251

Note que após o lançamento em seqüência dos programas, o processo com pid = 1249, correspondente à execução de test_shmget cria o segmento de memória. Depois, esse segmento será acessado por dois processos, sendo que o último é aquele com pid = 1251, correspondente à execução de test_shmat2.


next up previous
Next: Função shmdt() Up: Memória Compartilhada Previous: A Função shmctl()
Celso Alberto Saibel Santos 2000-11-14