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