2012-05-27 25 views
5

He estado probando esto durante horas, y googleé todas las cosas en las que pienso, pero me estoy volviendo loco.Punteros dentro del segmento de memoria compartida

que tienen una estructura:

typedef struct { 
    int rows; 
    int collumns; 
    int* mat; 
    char* IDs_row; 
} mem; 

no sé el tamaño de la int * (una matriz) y char * hasta el posterior.

Cuando lo haga, puedo crear la memoria compartida como esto:

mem *ctrl; 
int size = (2 + ((i-1)*num_cons))*sizeof(int) + i*26*sizeof(char); //I have the real size now 
shmemid = shmget(KEY, size, IPC_CREAT | 0666); 
if (shmemid < 0) { 
    perror("Ha fallado la creacion de la memoria compartida."); 
    exit(1); 
} 
ctrl = (mem *)shmat(shmemid, 0, 0); 
if (ctrl <= (mem *)(0)) { 
    perror("Ha fallado el acceso a memoria compartida"); 
    exit(2); 
} 

No hay problema aquí. Luego doy un valor a ctrl-> rows y collumns, y asigno 0 a toda la matriz.

Pero después de eso, escribo algo en el char * y bam, fallo de segmentación.

Depuración del programa Vi que tanto los punteros, mat e IDs_row estaban nulos. ¿Cómo les doy los valores correctos dentro del segmento de memoria compartida?

Intenté eliminar el puntero char *, solo para intentarlo, y luego el error de segmentación estaba en el otro programa conectado a dicha memoria compartida y simplemente comprobé los valores dentro de la matriz (marcando -> filas y -> collumns fue exitosa)

Respuesta

5
ctrl = (mem *)shmat(shmemid, 0, 0); 

Esto sólo asigna memoria válida al puntero ctrl, no ctrl->mat o ctrl->IDs_row.

es probable que desee:

mem *ctrl; 
shmemid = shmget(KEY, sizeof(ctrl), IPC_CREAT | 0666); 
//allocate memory for the structure 
ctrl = (mem *)shmat(shmemid, 0, 0); 

//allocate memory for the int* 
shmemid = shmget(KEY,((i-1)*num_cons))*sizeof(int), IPC_CREAT | 0666); 
ctrl->mat = (int*)shmat(shmemid, 0, 0); 

//allocate memory for the char* 
shmemid = shmget(KEY,i*26*sizeof(char), IPC_CREAT | 0666); 
ctrl->IDs_row = (char*)shmat(shmemid,0,0); 
+0

¡Gracias! Nunca pensé en hacer el shmget para cada puntero. (Ni siquiera entiendo cómo funciona, haciendo la misma llamada pero "fundiéndolo") Ahora hay un problema con el segundo entero en la estructura, las "columnas". Pongo un "1" allí en un proceso, y el otro proceso lo lee como 62045 o algo así. Intenté cambiar sizeof (ctrl) a sizeof (men) y 2 * sizeof (int) + sizeof (int *) + sizeof (char *), pero no tuve suerte. – Knudow

+0

Disculpa, envié el mensaje y luego lo edité. ¿Me puedes ayudar un poco más? Tengo un problema ahora con el segundo entero en la estructura. – Knudow

+0

@ user1420534 por favor publique una nueva pregunta con este nuevo problema, no parecen estar relacionados. –

7

En primer lugar, poner absolutos punteros en segmentos de memoria compartida es idea terrible lejísimos - los punteros sólo serían válidos en el proceso que llenó en sus valores. Los segmentos de memoria compartida son no garantizados para adjuntar a la misma dirección virtual en cada proceso. Por el contrario, se conectan donde el sistema lo considera posible cuando se especifica shmaddr == NULL en la llamada al shmat(). Puede especificar la misma dirección virtual al llamar al shmat(), pero depende de usted asegurarse de que no se haya mapeado nada más en esa región de memoria en todos los procesos participantes. Esto es difícil de hacer de manera portátil. Lo que más le gustaría hacer es:

1) Asignar un gran segmento de memoria compartida que acomoda tanto la estructura mem como las dos matrices de datos. Entonces no debe poner punteros absolutos sino punteros relativos al comienzo del bloque de memoria y luego ajustar el uso.

2) Asignar los tres segmentos de memoria compartida diferentes, pero en vez de poner punteros, poner los ID de memoria compartida devuelto por shmget():

typedef struct { 
    int rows; 
    int collumns; 
    int mat_id; 
    int IDs_row_id; 
} mem; 

Cuando necesite acceder a la matriz o la matriz de identificadores solo conéctelo a la ID de memoria compartida almacenada en el campo correspondiente.

Tenga en cuenta que el uso de la misma KEY en las siguientes invocaciones de shmget() no producirá el resultado esperado a menos que KEY == IPC_PRIVATE. Lo mejor es usar un valor de clave fijo para el bloque de memoria compartida con el descriptor (del tipo mem) y IPC_PRIVATE para los otros dos bloques de memoria; de lo contrario, las tres llamadas devolverán el mismo mismo bloque de memoria compartida - el primero lo hará créelo y los próximos dos simplemente devolverán su ID ya que un bloque con esa clave ya existe.

Cuestiones relacionadas