Newsgroup: it.comp.os.linux.development
Titolo: Implementazione memoria condivisa

 
 Salve,
sono alle prime armi con la programmazione di sistema. Usando le api posix
per la memoria condivisa so che è possibile creare array di interi
condivisi.
Ma è possibile creare array di strutture condivise?? o array di stringhe
stringhe ?? o array di array di stringhe condivisi????
ho molte difficolta già a creare un array di stringhe condivise in quanto mi
risulta ostico accedere alla iesima posizione dell'array, non oso pensare
all'array di array di stringhe.
qualcuno consce qualche soluzione migliore??
la mia è
    /* creazione mem condivisa */
    if( (nick_des = shm_open(sh_nick_name, O_CREAT |O_RDWR|O_TRUNC, mode)) == -1
)
        perror("shm_open"),exit(1);
    if( ftruncate(nick_des,(MAXCONN*MAXNICK)*sizeof(char)) == -1 )
        perror("ftruncate"),exit(1);
    /* collegamento del segmento allo spazio di indirizzamento del processo */
    if( (nick =
mmap(0,(MAXCONN*MAXNICK)*sizeof(char),PROT_WRITE|PROT_READ,MAP_SHARED,nick_des,0))
== ((caddr_t)-1) )
        perror("mmap"),exit(1);
/* riempi array */
    inizionick = nick;
    for(i=0;i<MAXCONN;i++) {
        idclient[i] = i;
        memcpy(nick,"nick",MAXNICK);
        nick += MAXNICK;
    }
/* stampa array*/
    nick = inizionick;
    for(i=0;i<MAXCONN;i++) {
       printf("%d ",idclient[i]);
       printf("%s\n",nick);
       nick += MAXNICK;
    }
se questa è la soluzione migliore come posso creare e indirizzare
correttamente un array di array di stringhe??
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 all'array di array di stringhe.
Immagina una scacchiera 8x8, dove in ogni casella puoi mettere una
lettera. Le caselle son numerate da 0 a 63 partendo dalla casella in alto
a sinistra.
Su questa scacchiera puoi facilmente mettere 8 parole da al massimo 7
caratteri + un carattere terminatore.
Per individuare il numero della casella dove inizia una parola ti basta
sapere in che riga sta (partendo da zero) e moltiplicare per 8: la prima
parola inizia alla casella 0, la seconda alla casella 8, la terza alla
casella 16, etc.
Ora immagina di avere una pila di 10 scacchiere 8x8 una sopra l'altra. Il
numero totale di caselle è 64x10, e puoi enumerarle partendo dalla prima
casella della prima scacchiera (0) fino all'ultima casella dell'ultima
scacchiera (640). Per individuare la casella dove inizia una parola ti
basta sapere in quale scacchiera sta e in quale riga di quella scacchiera.
Ad esempio, se mi interessa sapere qual è la casella dove inizia la
quarta parola della terza scacchiera, basta moltiplicare 64 (il numero di
caselle di una scacchiera) per 2 (la terza scacchiera, partendo da zero) e
poi sommarci 8 (il numero di caselle per ogni riga) per 3 (la quarta
riga, partendo da zero). Il risultato è che la parola in questione
inizia alla casella 152.
Ora immagina di avere tante pile da dieci scacchiere ciascuna: il
procedimento è analogo, solo che ora devi anche sapere in che pila andare
a guardare. Ed anche qui puoi sempre enumerare tutte le caselle partendo
dalla prima casella della prima riga della prima scacchiera della prima
pila fino all'ultima casella dell'ultima riga dell'ultima scacchiera
dell'ultima pila.
In pratica: per ogni matrice multidimensionale (con dimensioni note) c'è
una matrice monodimensionale equivalente, la cui dimensione è il prodotto
delle dimensioni di cui sopra.
Problema: e se invece di memorizzare singole parole da al massimo sette
lettere più il carattere terminatore io dovessi memorizzare delle intere
frasi, che possono andare dal monosillabo ("si", "no", "boh?") al testo
dell'intera Divina Commedia? Dovrei prevedere delle scacchiere con righe
da centomila caselle, la maggior parte delle quali andrebbe inutilizzata.
Allora l'idea è quella di memorizzare le frasi in maniera contigua, l'una
dietro l'altra, e di avere una matrice che memorizza gli indirizzi in
memoria a tali frasi (un indirizzo occupa poco: 4 byte su architetture a
32 bit, 8 per le architetture a 64 bit), ed è anche quello che
normalmente si fa in C: ci si riserva (via malloc() o calloc()) un po' di
memoria da qualche parte, ci si copia dentro la stringa, e poi ci si tiene
da parte nella matrice il puntatore alla stringa: più che array di
stringhe hai array di puntatori a stringhe.
Anche nelle struct vale lo stesso discorso: il C non prevede struct a
dimensioni variabili, per cui o ti riservi un po' di spazio all'interno
della struct per metterci dentro i dati del caso, o metti nella struct
un puntatore a dati memorizzati da un'altra parte. In entrambi i casi hai
una struct di dimensioni costanti (puoi saperne le dimensioni in byte
usando sizeof(struct mia_struct)), con cui puoi fare tutti i ragionamenti
di cui sopra (invece di avere scacchiere con righe da 8 caselle avrai
righe da sizeof(struct mia_struct) caselle).
Con la memoria condivisa il discorso cambia poco: nel caso di struct con
dentro direttamente i dati ti basta fare il conto partendo dall'indirizzo
del segmento di memoria condivisa, mentre nel caso di struct con i dati
memorizzati da un'altra parte ti devi implementare un allocatore (stile
malloc()/calloc()) che ti allochi del posto all'interno del segmento di
memoria condivisa (invece che allocarla nello heap).
Purtroppo implementare un allocatore efficiente non è banale, ma se
cerchi in giro dovresti trovarne di già fatti.
-- 
  |   \    \  | ___|_  |_  |  ianezz a casa sua... :-)
  |  _ \  | \ | _|    /   /   Verba volant, scripta
 _|_/  _\_|  _|____|___|___|  manent, data corrupted

Grazie per la spiegazione!!
Ora vedo cosa riesco a fare :)



Ok ho implementato un array di array di stringhe GRAZIE
ora però ho difficolta per un array di struct.... forse sbaglio qualcosa nel
codice, riporto le rige salienti
struct strut {
    int val;
} strut;
	mode = S_IRWXU | S_IRWXG;
	shmdes = shm_open(shm_fn,O_CREAT|O_RDWR|O_TRUNC,mode);
	ftruncate(shmdes,NBUFF*sizeof(struct strut));
        shmptr = mmap(0,NBUFF*sizeof(struct
strut),PROT_WRITE|PROT_READ,MAP_SHARED,shmdes,0);
        for(index = 0; index<NBUFF; index++ )
               shmptr+(index*sizeof(struct strut)).val = index;
in fase di compilazione ottengo il seguente errore: request for member `val'
in something not a structure or union
e se accedo al campo con ->val ottengo il seguente errore: invalid type
argument of `->'
mi sapreste dire como accedere al campo val in lettura e scrittura
correttamente? o se ho sbagliato la dichiarazione come dichiararlo
correttamente...
e nel caso val fosse una stringa? qual'è la ichiarazione corrette e i giusti
modi per acedervi?
                  Il 06 Lug 2005, 07:46, ianezz <n...@thanks.test> ha scritto:



 argument of `->'
Non puoi dereferenziare un puntatore a void. Devi convertirlo prima in un
puntatore a qualche altro tipo (nel tuo caso, uno struct strut *).


grazie ianezz.
Semplicemente geniale, tutto fila e combacia... hai mai pensato di scrivere
un testo in cui chiarire tutti questi dettagli!!
vado a implementare e spero di non avere + problemi del genere
grazie ancora ciao

