Operating System - Linux
1753434 Members
4633 Online
108793 Solutions
New Discussion юеВ

Re: IPC shared memory with a struct?

 
SOLVED
Go to solution
Pedro Dinis
Advisor

IPC shared memory with a struct?


i am trying to set a memory segment with this struct:

SERVER

typedef struct dataestrutura {
char * usr;
char * passwd;
char * osid;
} dataestrutura;


int main( int argc, char *argv[] )
{
key_t key;
int shmid;
int mode;
///struct em vez do char *///

dataestrutura *data_ptr;

/* Initialize the logging interface */
openlog( DAEMON_NAME, LOG_PID, LOG_LOCAL5 );
syslog( LOG_INFO, "starting" );

/* One may wish to process command line arguments here */
cout << "\n daemon started \n" << endl;

/* Daemonize */
daemonize( DAEMON_NAME );



cout <<"/* make the key: */"< if ((key = ftok("/home/pedro/SHARED_MEMORY/teste.txt", 'LP')) == -1)
{
perror("ftok");
exit(1);
}



cout << "/* connect to (and possibly create) the segment: */" << endl;
if ((shmid = shmget(key,SHM_SIZE, 0644 | IPC_CREAT)) == -1)
{
perror("shmget");
exit(1);
}

cout << "/* attach to the segment to get a pointer to it: */" << endl;
data_ptr = (dataestrutura *)shmat(shmid,0, 0);
if (data_ptr == (dataestrutura *)(-1))
{
perror("shmat");
exit(1);
}

cout << "/* read or modify the segment, based on the command line: */" << endl;


/*strcpy(data_ptr->usr, "bdsn");
strcpy(data_ptr->passwd, "bdsn");
strcpy(data_ptr->osid, "oesis");*/

data_ptr->usr="bdsn";
data_ptr->passwd="bdsn";
data_ptr->osid="osid";




cout <<"/* detach from the segment: */" << endl;
if (shmdt(data_ptr) == -1)
{
perror("shmdt");
exit(1);
}







cout << "/* Finish up */" << endl;
syslog( LOG_NOTICE, "terminated" );
closelog();
return 0;
}



CLIENT

its not getting the data :


int main( int argc, char *argv[] )
{

int shmid ; /* identificateur de la memoire commune */
int size = 1000 ;
char *path="/home/pedro/SHARED_MEMORY/teste.txt" ;

int flag = 0 ;
dataestrutura *mem;

/*
* 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 = (dataestrutura*)shmat (shmid, 0, flag)) == (dataestrutura*)-1){
perror("acoplamento impossivel") ;
exit (1) ;
}
/*
* tratamento do conteudo do segmento
*/

printf("leitura do segmento de memoria compartilhada:\n");
printf("\t==>endere├зo:%d\n",&mem) ;
printf("\t==>mem:%d\n",sizeof(mem)) ;
printf("\t==>mem:%s\n",mem) ;
printf("\t==>mem:%s\n",mem->usr) ;

cout <<"/* detach from the segment: */" << endl;
if (shmdt(mem) == -1)
{
perror("shmdt");
exit(1);
}


}
SLB SLB SLB Glorioso
4 REPLIES 4
A. Clay Stephenson
Acclaimed Contributor
Solution

Re: IPC shared memory with a struct?

typedef struct dataestrutura {
char * usr;
char * passwd;
char * osid;
} dataestrutura

The fundamental problem is that you have allocated space for the pointers but not for the data pointed to.

If you change your struct to something like this:

#define BIG_ENOUGH 256

typedef struct dataestrutura {
char usr[BIG_ENOUGH];
char passwd[BIG_ENOUGH];
char osid[BIG_ENOUGH];
} dataestrutura

then you will actually allocate storage space.

If it ain't broke, I can fix that.
Pedro Dinis
Advisor

Re: IPC shared memory with a struct?

now its working


thanks

Muchas Gracias
SLB SLB SLB Glorioso
Dennis Handly
Acclaimed Contributor

Re: IPC shared memory with a struct?

Basically what you are doing is taking addresses from one process and expect them to be valid in another.

Instead of Clay's suggestion of arrays, you can take addresses of other parts of shared memory and then initialize your struct.

shmid = shmget(key,SHM_SIZE+slop, 0644 | IPC_CREAT)

data_ptr = (dataestrutura*)shmat(shmid,0, 0);

// Copy strings into slop area.

char *string_area = (char*)&dataestrutura[1];
char *string_ptr = string_area;
strcpy(string_ptr, "bdsn");
data_ptr->usr = string_ptr;
string_ptr += strlen("bdsn")+1;
...

And of course you need to make sure that you don't run off the end of the "slop" area.

Since you are using C++, you can just use an STL allocator to allocate space in your shared memory. In fact, you can create a basic_string with that allocator, so when you construct a string, it just goes there.

(Of course if you want to free space, you would have to know how to reclaim the space.)

Dennis Handly
Acclaimed Contributor

Re: IPC shared memory with a struct?

Oops, that should have been:
char *string_area = (char*)&dataestrutura[1];

(When you have gotten the answers in a thread, you should close them so people know you don't need more help. You have several that aren't closed.)