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