2011-08-30 26 views
12

Estoy tratando de comunicarme entre dos procesos. Intento guardar datos (como nombre, número de teléfono, dirección) en la memoria compartida en un proceso e intentar imprimir esos datos a través de otro proceso.cómo usar la memoria compartida para comunicar entre dos procesos

process1.c

#include <stdio.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 
int main() 
{ 
    int segment_id; 
    char* shared_memory[3]; 
    int segment_size; 
    key_t shm_key; 
    int i=0; 
    const int shared_segment_size = 0x6400; 
    /* Allocate a shared memory segment. */ 
    segment_id = shmget (shm_key, shared_segment_size, 
      IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 
    /* Attach the shared memory segment. */ 
    shared_memory[3] = (char*) shmat (segment_id, 0, 0); 
    printf ("shared memory attached at address %p\n", shared_memory); 
    /* Write a string to the shared memory segment. */ 
    sprintf(shared_memory[i], "maddy \n"); 
    sprintf(shared_memory[i+1], "73453916\n"); 
    sprintf(shared_memory[i+2], "america\n"); 

    /*calling the other process*/ 
    system("./process2"); 

    /* Detach the shared memory segment. */ 
    shmdt (shared_memory); 
    /* Deallocate the shared memory segment.*/ 
    shmctl (segment_id, IPC_RMID, 0); 

    return 0; 
} 

process2.c

#include <stdio.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 
int main() 
{ 
    int segment_id; 
    char* shared_memory[3]; 
    int segment_size; 
    int i=0; 
    key_t shm_key; 
    const int shared_segment_size = 0x6400; 
    /* Allocate a shared memory segment. */ 
    segment_id = shmget (shm_key, shared_segment_size, 
       S_IRUSR | S_IWUSR); 
    /* Attach the shared memory segment. */ 
    shared_memory[3] = (char*) shmat (segment_id, 0, 0); 
    printf ("shared memory22 attached at address %p\n", shared_memory); 
    printf ("name=%s\n", shared_memory[i]); 
    printf ("%s\n", shared_memory[i+1]); 
    printf ("%s\n", shared_memory[i+2]); 
    /* Detach the shared memory segment. */ 
    shmdt (shared_memory); 
    return 0; 
} 

Pero no estoy recibiendo la salida deseada. la salida que tengo es:

shared memory attached at address 0x7fff0fd2d460 
Segmentation fault 

Cualquiera puede por favor me ayude con esto. ¿Es esta la forma correcta de inicializar shared_memory[3]?

Gracias.

Respuesta

14
char* shared_memory[3]; 
... 
shared_memory[3] = (char*) shmat (segment_id, 0, 0); 

se declara shared_memory como una matriz capaz de contener tres punteros a char, pero lo que en realidad se hace con él es escribir un puntero un puesto por detrás del final de la matriz. Como no se sabe para qué sirve la memoria, lo que sucede a continuación es generalmente impredecible.

Las cosas van definitivamente mal después cuando intenta utilizar los punteros en shared_memory[0] hasta shared_memory[2], porque esos punteros nunca se han inicializado. Están llenos de basura sin sentido de la pila, por lo tanto, la falla de segmentación.

Parece que, en general, no distingue entre la matriz y sus elementos. Debe ir y hacerse mucho más cómodo con matrices y apuntadores en código secuencial antes de probar su mano en el IPC de memoria compartida.

Tenga en cuenta que la memoria compartida es una de las formas más fáciles de obtener errores de IPC. A menos que tenga restricciones de eficiencia rígidas y vaya a cambiar mucho de datos, es mucho más fácil trabajar con tuberías, tubos con nombre o tomas de corriente.

+0

Gracias Henning. – maddy

0

Debe reservar suficiente memoria compartida para intercambiar datos. Se supone que los procesos no tienen acceso a la memoria de los demás, incluso si utilizan punteros compartidos. Tenga en cuenta que solo se comparten los datos brutos que se escriben durante el tiempo de ejecución, no se verifica el tipo ni se pasan otros metadatos. Puede usar una estructura común, si sus datos le permiten usar arreglos de tamaño fijo, para acceder a los datos más fácilmente. De lo contrario, tendrá que ordenar manualmente los datos entre los procesos.

11

Las otras dos respuestas te indicaron lo que sucede, pero quiero darte un código ejecutable. Puedes modificarlo para pasar cualquier cosa, el principio es que necesitas guardar la longitud de cada elemento que pasaste al otro lado.

//write.c

#include <stdio.h> 
#include <string.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 

int main() 
{ 
    key_t shm_key = 6166529; 
    const int shm_size = 1024; 

    int shm_id; 
    char* shmaddr, *ptr; 
    int next[2]; 

    printf ("writer started.\n"); 

    /* Allocate a shared memory segment. */ 
    shm_id = shmget (shm_key, shm_size, IPC_CREAT | S_IRUSR | S_IWUSR); 

    /* Attach the shared memory segment. */ 
    shmaddr = (char*) shmat (shm_id, 0, 0); 

    printf ("shared memory attached at address %p\n", shmaddr); 

    /* Start to write data. */ 
    ptr = shmaddr + sizeof (next); 
    next[0] = sprintf (ptr, "mandy") + 1; 
    ptr += next[0]; 
    next[1] = sprintf (ptr, "73453916") + 1; 
    ptr += next[1]; 
    sprintf (ptr, "amarica"); 
    memcpy(shmaddr, &next, sizeof (next)); 
    printf ("writer ended.\n"); 

    /*calling the other process*/ 
    system("./read"); 

    /* Detach the shared memory segment. */ 
    shmdt (shmaddr); 
    /* Deallocate the shared memory segment.*/ 
    shmctl (shm_id, IPC_RMID, 0); 

    return 0; 
} 

// leer.c

#include <stdio.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 

int main() 
{ 
    key_t shm_key = 6166529; 
    const int shm_size = 1024; 

    int shm_id; 
    char* shmaddr, *ptr; 
    char* shared_memory[3]; 
    int *p; 

    /* Allocate a shared memory segment. */ 
    shm_id = shmget (shm_key, shm_size, IPC_CREAT | S_IRUSR | S_IWUSR); 

    /* Attach the shared memory segment. */ 
    shmaddr = (char*) shmat (shm_id, 0, 0); 

    printf ("shared memory attached at address %p\n", shmaddr); 

    /* Start to read data. */ 
    p = (int *)shmaddr; 
    ptr = shmaddr + sizeof (int) * 2; 
    shared_memory[0] = ptr; 
    ptr += *p++; 
    shared_memory[1] = ptr; 
    ptr += *p; 
    shared_memory[2] = ptr; 
    printf ("0=%s\n", shared_memory[0]); 
    printf ("1=%s\n", shared_memory[1]); 
    printf ("2=%s\n", shared_memory[2]); 

    /* Detach the shared memory segment. */ 
    shmdt (shmaddr); 
    return 0; 
} 

// Resultado de la carrera:

> [lex:shm]$ ./write 
> writer started. 
> shared memory attached at address 0x7fa20103b000 
> writer ended. 
> shared memory attached at address0x7fd85e2eb000 
> 0=mandy 
> 1=73453916 
> 2=amarica 
+0

¿No llamaría a IPC_CREAT durante la lectura.c para crear un conjunto completamente nuevo de memoria compartida en lugar de obtener la existente? – Sherd

Cuestiones relacionadas