Sziasztok!
Nem nagyon szoktam ilyet kérni, de úgy látszik most rákényszerülök. Akinek van egy kis ideje, és készített már shared memory-s programot, légyszíves nézze, meg hogy mit szúrok el! Előre is nagyon köszönöm!Először létrehozom a megosztott memória területet.
size = ( (a+1) + a*(a+1) + a*a*(b+1) ) * sizeof(float*) + (a*a*b*(b+1)) * sizeof(float);
if ((id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0666)) < 0)
{
printf("Hiba a megosztott memória lefoglalása közben (méret: %d Byte)\n", size);
return -1;
}
Erre a területre egy nagy a*a-s mátrix (2d tömb) kerül, melynek minden eleme egy b*b-s kisebb mátrix (2d tömb ez is). Minden tömb NULL-al lesz lezárva, kivéve az utolsót amiben a számok vannak, az FLT_MAX_EXP-el (ez egy konstans a legnagyobb float-ra).
Ekkor fork()-olok, és exec-el elindítom többször ugyanazt a programot (ezek fogják a mátrixokat szorozgatni). A program megkapja argumentumként az shmget() által visszaadott azonosítót.
A fork() után, még mindig a főprogramban felcsatolom a memóriát, és létrehozom a megfelelő pointer struktúrát a 4 dimenziós tömb tárolásához.
if ((matrix = shmat(id, 0, 0)) == (pMATRICES)-1)
{
printf("Hiba a megosztott memória felcsatolása közben.\n");
return NULL;
}
for (i=0; i<a; i++)
{
step = ( (a+1) + i*(a+1) ) * sizeof(float*);
matrix[i] = (float***)(matrix + step);
for (j=0; j<a; j++)
{
step = ( (a+1) + a*(a+1) + i*a*(b+1) + j*(b+1) ) * sizeof(float*);
matrix[i][j] = (float**)(matrix + step);
for (k=0; k<b; k++)
{
step = ( (a+1) + a*(a+1) + a*a*(b+1) ) * sizeof(float*) + ( i*a*b*(b+1) + j*b*(k+1) + k*(b+1) ) * sizeof(float);
matrix[i][j][k] = (float*)(matrix + step);
for (l=0; l<b; l++)
{
if (matrix[i][j][k][l] == FLT_MIN_EXP)
{
printf("Hiba, már inicializált terület (matrix[%d][%d][%d][%d]: %p)\n", i, j, k, l, &matrix[i][j][k][l]);
return NULL;
}
else
{
matrix[i][j][k][l] = FLT_MIN_EXP;
}
}
matrix[i][j][k][b] = FLT_MAX_EXP;
}
matrix[i][j][b] = NULL;
}
matrix[i][a] = NULL;
}
matrix[a] = NULL;
Ha ez sikerült, akkor szemaforral jelzek, az eddig a jelzésig várakozó, az előbb indított processzeknek. Erre ők felcsatolják a megosztott memóriát (az id-t argumentumként kapták meg)
if ((R = shmat(Rid, 0, 0)) == (pMATRICES)-1)
{
printf("[#%d] Hiba az R mátrixhoz tartozó megosztott memória felcsatolása közben. Kilépés.\n", num);
return 1;
}
És végül csak próba képen megpróbálok olvasni a mátrixból:
printf("[#%d] Hello Világ! Én vagyok a(z) %d számú virtuális processzor.\n", num, num);
printf("%g\n", R[0][0][0][0]);
Erre a főprogram (aki wait()-el vár) azt tapasztalja, hogy a gyerekfolyamatok befejeződtek, és 139-es hibakódot adnak vissza. Guglizás után arra jutottam, hogy ez Segmention Violation, vagyis valami olyasmi, hogy olyan memóriaterületet akartam elérni ami nem az én címtartományomhoz tartozik. A shm-nek nem pont ez lenne a célja?
Remélem valaki meglátja, hogy mit szúrtam el, mert én már nagyon kifogytam az ötletekből. Előre is nagyon köszönök minden ötletet!
Taki
- 1724 megtekintés
Hozzászólások
Hi,
Probald meg probakepp ezt a matrixos cuccot kihanytani belole, es megnezni hogy egy sima tombbel mukodik e. Ha nem, akkor biztos az shm/sem kezelesben van a hiba, de reszletesebb forrast ossz meg.
- A hozzászóláshoz be kell jelentkezni
Szia!
Köszönöm szépen a tippet. Kipróbáltam, és úgy tényleg működik. Tehát máris közelebb kerültem a megoldáshoz, a hiba valahol a mátrix létrehozásánál (createSharedMatrices függvény) van.
Nincs nagy gyakorlatom ilyesfajta segítségkérésben, így nem tudom mit jelent a RÉSZLETESEBB forrás. Kiexportáltam az egész programot HTML-be és felraktam a http://www.hszk.bme.hu/~ta490/matrix/ címre.
Nagyon köszönöm mindenkinek, aki veszi a fáradságot és megpróbál segíteni!
Taki
- A hozzászóláshoz be kell jelentkezni
Van nekem egy mintám, ha elfogadod...
Az első (szerver) program létrehozza a megosztott memóriát, a
másik (kliens) csak megnyitja magának. Mindkét program
tud ezután írni ugyanarra a területre. A kliens programnak
később kell kezdenie és előbb kell befejeznie a futást, mint a
szervernek, mert különben segfault. (A MEAfieldStruct helyett
bármilyen pointer lehet) Sok szerencsét: meditor
Szerver:
--------
#define SHM_SIZE sizeof(struct MEAfieldStruct)
void *shm_cmt;
int shm_id;
struct MEAfieldStruct *ShMF;
///////////////////
int SMinit (unsigned int flag)
{int ret;
ret=-1;shm_cmt=NULL;shm_id=shmget(0x2000,SHM_SIZE,0666 | flag);
if(shm_id==-1){MakeLogline(" - Common Field not created.");}
else{shm_cmt=shmat(shm_id,(void*)0,0);
if(shm_cmt==(void*)-1){MakeLogline(" - Common Field not attached.");}
else{ShMF=(struct MEAfieldStruct*)shm_cmt;
MakeLogline(" - Common Field memory O.K.");ret=1;}}
return(ret);
}
///////////////////
void SharedMemBye(void)
{shmdt(shm_cmt);shmctl(shm_id,IPC_RMID,0);
MakeLogline(" - All of the shared memory removed.");
}
///////////////////
int main(int argc, char *argv[])
{
if(SMinit(IPC_CREAT)>0){/* ide rakd a server_főprogramot*/SharedMemBye();}
}
//----------------------------------------------------------------------------------------------
kliens:
--------
#define SHM_SIZE sizeof(struct MEAfieldStruct)
void *shm_cmt;
int shm_id;
struct MEAfieldStruct *ShMF;
///////////////////
int SMinit (unsigned int flag)
{int ret;
ret=-1;shm_cmt=NULL;shm_id=shmget(0x2000,SHM_SIZE,0666 | flag);
if(shm_id==-1){;}
else{shm_cmt=shmat(shm_id,(void*)0,0);
if(shm_cmt==(void*)-1){;}
else{ShMF=(struct MEAfieldStruct*)shm_cmt;ret=1;}}
return(ret);
}
///////////////////
void SharedMemBye(void){shmdt(shm_cmt);}
///////////////////
int main(int argc, char *argv[])
{
if(SMinit(0)>0){/*ide rakd a cliens főprogramot */
SharedMemBye();}
}
//----------------------------------------------------------------------------------------------
> Sol omnibus lucet.
- A hozzászóláshoz be kell jelentkezni
Köszönöm szépen, azonban sajnos nem sokat segít. Ahogy LeslieT javasolta, megpróbáltam kiszedni a programból a 4d mátrixot, és csak a shared memory-val kísérletezni. Működött. Ha csak egyetlen tömb van (nem kell semmiféle pointer hókusz - pókusz) akkor működik szépen. A főprogram ír, a gyerekek pedig mind olvasnak.
Egyre erősebb az az érzésem, hogy a mátrix struktúra létrehozásánál (= pointer hókusz - pókusz) van a probléma.
Azt nem értem viszont, ha az shmat() ugyanarra a területre mutató pointert ad vissza mind a főprogramban, mind a gyerekekben, akkor a főprogram miért tudja gond nélkül írni és olvasni a 4dimenziós mátrixot, és a gyerekek miért halnak meg rá???
- A hozzászóláshoz be kell jelentkezni
Jol ertem hogy ugyanaz a program szuloje hozzafer de annak gyermek folyamata mar nem? Ha igy van, akkor a memszegmens becsatolast (shmat) egyszer vegezd el a fork() elott, es childek ugyis orokolni fogjak. Ha kulso programbol (exec mar az) is hozza akarsz ferni a megosztott eroforrashoz, akkor pedig IPC_PRIVATE helyett ftok()-al generalj kulcsot.
Egyebkent probald meg kidebuggolni, hogy pontosan hol hal meg a child process. Ha megvan melyik utasitasnal akkor megnezni milyen memoriacimekre hivatkozik, es ezek benne vannak e megosztott memoriateruletben.
- A hozzászóláshoz be kell jelentkezni
Köszönöm szépen, de úgy látszik megvan a megoldás:
Tamasi Ferenc írt egy e-mailt:
shmat mas es mas virtualismemoria cimet ad(hat) minden processznek, tehat ha az
inicializalo processzben pl.:
R = shmat() = 0x1 es R[0] = R+4 = 0x5 ezek ervenyes memoriacimek, de egy gyerekben mar:
R = shmat() = 0x2 DE R[0] = 0x5!!!!! meg mindig, ami lehet egy teljesen
ervenytelen cim a gyerekben!
Megoldas (quick'n'dirty): kezzel szamolgatni az offseteket, igy meg a
mutatok memoriafoglalasat is meguszod :).
Magyarul: egy shm-ben ne taroljunk memoricimeket.
Tehát szerintem írok egy függvényt ami kap 4 indexet (mintha a 4 tömbindex lenne), és az majd kiszámolgatja a megfelelő értéket.
- A hozzászóláshoz be kell jelentkezni