I am trying to create an array of structs that is shared between a parent and child processes. I am getting a segmentation fault when trying to access the array data.
I feel certain that the problem has something to do with the way I'm using pointers, as this is an area I'm not very comfortable with.
Please note that I edited out most of the code that didn't seem relevant.
/* structure of Registration Table */
struct registrationTable{
int port;
char name[MAXNAME];
int req_no;
};
main() {
/* the registrationTable is to be a shared memory space with each child
process able to access and update. No concurrency controls are
implemented. The parent process is responsible for cleaning up after
the kiddies.
*/
struct registrationTable base_table[REG_TABLE_SIZE];
for (int i = 0; i < REG_TABLE_SIZE; i++) {
base_table[i].req_no = 0;
memset(base_table[i].name, '\0', MAXNAME);
base_table[i].port = 0;
}
printf("\nMapping Shared Memory\n");
//set up shared memory space
//void *mmap(void *addr, size_t length, int prot, int flags,
// int fd, off_t offset);
// addr = NONE, prot = PROT_NONE, flags = MAP_SHARED
struct registrationTable *table = mmap(base_table, sizeof(base_table),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
-1, 0);
while(1){
pid_t child = fork();
if (child == 0) {//is child
for(int i = 0; i < REG_TABLE_SIZE; i++) {
printf("\nExamining table looking for client at %s port: %d\n",
packet_reg.data, clientAddr.sin_port);
printf("\ntable[1].req_no: %d", ta[i].req_no);
//segmentation fault on next line
if (strcmp(table[i].name, packet_reg.data) == 0
&& table[i].port == clientAddr.sin_port) {
table[i].req_no++;
}
You haven't initialized content of the table after it was allocated by mmap. So it contains garbage. And so strcmp(table[i].name, packet_reg.data) has a great chance to go over allocated buffers and access e.g. non-allocated memory.
initialize table properly;
use strncmp for the comparison there.
Related
I am trying to solve the producer consumer problem using mutexes and a shared buffer, but am having trouble accessing values in my shared buffer struct, specifically the char array. When I invoke the producer.c file in one terminal and print the values (the input is a txt file of the alphabet) using
printf("%c", newBuff->bytes[newBuff->rear]);
the chars do appear as normal, however when I do the same thing in consumer.c, but with
printf("%c", newBuff->bytes[newBuff->front]);
the values appear blank. The newBuff->front value is zero, so it should print the letter a. When I access other values in my struct in consumer.c like front, count, or rear they are correct. Share memory creation as well as attachment also works properly so I believe the issue is either I am not storing the char values properly in the array or I am trying to access them incorrectly. In the code below I placed the printf in the loop for producer.c and then outside the loop for consumer.c so I know for a fact a value is present before the consumer starts extracting data.
Consumer.c
typedef struct buffer{
pthread_mutex_t lock;
pthread_cond_t shout;
int front;
int rear;
int count;
int endOfFile;
char bytes[1024];
} buffer;
int main(int argc, char const *argv[]) {
int i=0;
FILE *file = fopen(argv[1], "w");
if (argc != 2){
printf("You must enter in a file name\n");
}
int shmid, swapCount=0;
char swapBytes[] = "";
char path[] = "~";
key_t key = ftok(path, 7);
buffer* newBuff;
if ((shmid = shmget(key, SIZE, 0666 | IPC_CREAT | IPC_EXCL)) != -1) {
newBuff = (buffer*) shmat(shmid, 0, 0);
printf("successful creation\n");
newBuff->front = 0;
newBuff->count = 0;
newBuff->endOfFile = 0;
pthread_mutexattr_t attr;
pthread_condattr_t condAttr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&newBuff->lock, &attr);
pthread_condattr_init(&condAttr);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&newBuff->shout, &condAttr);
} //shared memory creation
else if ((shmid = shmget(key, 0, 0)) != -1){
printf("%d\n", shmid);
printf("successful attachment\n" );
newBuff = (buffer*) shmat(shmid, 0, 0);
printf("%c\n", newBuff->count);
}
else{
printf("oops\n");
exit(0);
}
pthread_mutex_lock(&newBuff->lock);
printf("%c\n", newBuff->bytes[newBuff->front]);
while (newBuff->endOfFile != 1)
{
while (newBuff->count == 0){
pthread_cond_signal(&newBuff->shout);
pthread_cond_wait(&newBuff->shout, &newBuff->lock);
}
newBuff->front = ((newBuff->front + 1)%SIZE);
newBuff->count--;
}
pthread_mutex_unlock(&newBuff->lock);
shmdt(&newBuff);
//pthread_mutexattr_destroy(&attr);
//pthread_condattr_destroy(&condAttr);*/
return 0;
}
Producer.c
typedef struct buffer{
pthread_mutex_t lock;
pthread_cond_t shout;
int front;
int rear;
int count;
int endOfFile;
char bytes[1024];
} buffer;
int main(int argc, char const *argv[]) {
FILE *file = fopen(argv[1], "r");
if (argc != 2){
printf("You must enter in a file dumbass\n");
}
int shmid;
char path[] = "~";
key_t key = ftok(path, 7);
buffer* newBuff;
printf("dfasdfasdf\n");
if ((shmid = shmget(key, SIZE, 0666 | IPC_CREAT | IPC_EXCL)) != -1) {
newBuff = (buffer*) shmat(shmid, 0, 0);
printf("successful creation\n");
newBuff->front = 0;
newBuff->count = 0;
newBuff->endOfFile=0;
pthread_mutexattr_t attr;
pthread_condattr_t condAttr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&newBuff->lock, &attr);
pthread_condattr_init(&condAttr);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&newBuff->shout, &condAttr);
} //shared memory creation
else if ((shmid = shmget(key, 0, 0)) != -1){
printf("successful attachment\n" );
newBuff = (buffer*) shmat(shmid, 0, 0);
}
else{
printf("oops\n");
exit(0);
}
printf("%d\n", shmid);
pthread_mutex_lock(&newBuff->lock);
while (fscanf(file, "%c", &newBuff->bytes[newBuff->rear]) != EOF) //read in file
{
printf("%c\n", newBuff->bytes[newBuff->rear]);
while (newBuff->count >= SIZE){ //buffer is full
//("%c\n", newBuff->bytes[newBuff->rear]);
pthread_cond_signal(&newBuff->shout);
pthread_cond_wait(&newBuff->shout, &newBuff->lock);
}
//printf("%c\n", newBuff->bytes[newBuff->rear]);
newBuff->rear = ((newBuff->front + 1)%SIZE);
newBuff->count++;
}
newBuff->endOfFile = 1;
pthread_cond_signal(&newBuff->shout);
pthread_mutex_unlock(&newBuff->lock);
shmdt(&newBuff);
//pthread_mutexattr_destroy(&attr);
//pthread_condattr_destroy(&condAttr);
return 0;
}
There are several difficulties with your code, some already addressed in comments:
ftok() requires the path passed to it to designate an existing file, but the path you are passing does not.
You request less shared memory than you actually need: only the size of the buffer content, not of a whole struct buffer. Because the amount of shared memory actually allocated will be rounded up to a multiple of the page size, this may end up being ok, but you should ensure that it will be ok by requesting the amount you actually need.
System V shared memory segments have kernel persistence, so once created, they will continue to exist until they are explicitly removed or the system is rebooted. You never remove yours. You also initialize its contents only when you first create it. Unless you manually delete it between runs, therefore, you'll use old data -- with the end-of-file indicator set, for instance -- on the second and subsequent runs. I suggest having the consumer schedule it for removal.
The consumer prints only one byte of data from the buffer, and it does so before verifying that there is anything to read.
After adding a byte to the buffer, the producer does not update the available byte count until after signaling the consumer. At best, this is wasteful, because the consumer will not see the change in count until the next time (if any) it wakes.
The producer updates the rear index of the buffer incorrectly, based on the current front value instead of on the current rear value. The data will therefore not be written into the correct places in the buffer array.
Once the producer sets the endOfFile flag, the consumer ignores all but one of any remaining unread bytes.
If the producer leaves the count zero when it finishes, the consumer will deadlock.
I find that modified versions of your programs addressing all of these issues successfully and accurately communicate data through shared memory.
Update:
Also,
The way in which consumer and / or producer initializes the mutex and condition variable is not itself safe. It is possible for whichever process attempts the shmget() second (or third, or ...) to access those objects before the first finishes initializing them. More generally, once a shared memory segment is attached, there is no inherent memory barrier involved in writing to it. To address these issues, the natural companion to SysV shared memory is SysV semaphores.
I'm currently programming my Bachelor Project what consists an RFB-Client and a Shared Memory. The initialisation of the RFB-Client is done, the Shared Memory is created. My teacher told me to decouple the code and I wrote several functions and used a global variable for the shared memory.
But now a segmentation fault occurs while trying to read the content of the global variable. I debugged the code and found out: The content of the global variabel "my_shm" is always "0x00" :-/
Could you please help me?
These are the portions of code where the problem occurs:
(I know, this is a long code, but sending just parts of it would be useless...)
char *my_shm; --> //global variable
int SHM_init (int shmid, char* shm, key_t key, long int size) {
/* Create a new (System V) shared memory segment of the specified size */
shmid = shmget(key, SHM_SIZE, IPC_CREAT|0777);
/* Check if SHM creation was successful */
if (shmid < 0) {
/* DBG: Debug message to show which point of the program has been passed */
DBG_PRINT("C\n");
/* Check if creation failed because of already existing SHM */
if (EEXIST == errno) {
/* DBG: Debug message to show which point of the program has been passed */
DBG_PRINT("CC\n");
/* Delete already existing SHM with shmctl */
shmctl(shmid, IPC_RMID, NULL);
} else {
/* DBG: Debug message to show which point of the program has been passed */
DBG_PRINT("CCC\n");
}
/* Creation and initialization of SHM failed */
return -1;
}
/* Attach the SHM data pointer to the previously created SHM segment */
shm = shmat(shmid, NULL, 0);
if(shm == (char *) -1) {
/* Attaching failed */
return -1;
}
DBG_PRINT("Shared Memory Initialization successful\n");
/* Creation and initialization of shared memory was successful */
return 0;
}
void RFB_update(rfbClient* client) {
DBG_PRINT("RFB_update called\n");
int i,j;
rfbPixelFormat* pformat=&client->format;
DBG_PRINT("A\n");
/*bytesPerPix: variable which stores Bytes per Pixel*/
int bytesPerPix = pformat->bitsPerPixel/8;
DBG_PRINT("B\n");
/*row= width of frame*bytes per Pixel*/
int row=client->width*bytesPerPix;
DBG_PRINT("C\n");
char byte_to_write;
//as long as j is smaller than 128*(width*bytesPerPix)
for(j=0;j<client->height*row;j+=row) {
//as long as i is smaller than 128 * bytesPerPix
for(i=0;i<client->width*bytesPerPix;i+=bytesPerPix) {
/*frameBuff: Pointer on FrameBuffer*/
unsigned char* frameBuff = client->frameBuffer+j+i;
unsigned int v;
if(bytesPerPix==4)
v=(unsigned int*)frameBuff;
byte_to_write = ((v>>pformat->redShift)*256/(pformat->redMax+1));
SHM_write_byte(my_shm,byte_to_write);
byte_to_write = ((v>>pformat->greenShift)*256/(pformat->greenMax+1));
SHM_write_byte(my_shm,byte_to_write);
byte_to_write = ((v>>pformat->blueShift)*256/(pformat->blueMax+1));
SHM_write_byte(my_shm,byte_to_write);
}
}
DBG_PRINT("RFB_update successful, Shared Memory is filled\n");
}
int SHM_write_byte (char** shm, char byte) {
/*Check if pointer to SHM is valid */
if (shm == (char **) -1) {
/* Pointer is invalid */
return -1;
}
shm = byte;
shm++;
return 0;
}
int main (int argc, char *argv[]) {
if (SHM_init(shmid, my_shm, SHM_KEY, SHM_SIZE) != 0) {
DBG_PRINT("Shared Memory initialized\n");
/* Couldn't initialize SHM,initializing failed */
return -1;
}
/* Initialize RFB Client */
if (RFB_client_init(rfb_client, (FinishedFrameBufferUpdateProc)RFB_update) != 0) {
DBG_PRINT("Couldn't initialize client\n");
/* Couldn't initialize Client,initializing failed */
return -1;
}
--> everywhere the variable "my_shm" is used: the content is: 0x00...
This seems to be a very common problem here on stackoverflow.com today, and the problem is that you pass arguments to function by value and not by reference.
What that means is that when you pass an argument to a function, its value is copied, and the function only work on the copy locally inside the function. As you should know, modifying a copy will of course not modify the original.
C does not have pass by reference, but it can be emulated by using pointers. In your case, since you have a pointer you need to pass a pointer to the pointer using the address-of operator, like
SHM_init(shmid, &my_shm, SHM_KEY, SHM_SIZE)
// ^
// |
// Note ampersand (address-of operator) here
You of course need to modify the function to actually accept a pointer to the pointer:
int SHM_init (int shmid, char** shm, key_t key, long int size)
And of course use the dereference operator * when using the variable:
*shm = shmat(shmid, NULL, 0);
I 'm working on a sample program on mmap and shared memory. Here is the piece of code I was trying,
Process B
#include<stdio.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<unistd.h>
#include<malloc.h>
typedef struct sh_mem_t{
int offset;
char *buffer;
}sh_mem;
int main(){
int fd;
sh_mem *shm_obj;
fd = shm_open("/myshm",O_RDWR,0777);
if(fd == -1){
perror("fd:ERROR");
return -1;
}
shm_obj = mmap(0,sizeof(sh_mem),PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
if(shm_obj == MAP_FAILED){
perror("shm_obj:ERROR");
return -1;
}
printf("\n offset : %d \n",shm_obj->offset);
// printf("\n Good work! : %s \n",shm_obj->buffer);
return 0;
}
Process A
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<sys/sem.h>
typedef struct sh_mem_t{
int offset;
char *buffer;
}sh_mem;
int main(int argc,char *argv[]){
int file_size = 0;
int fd_sh = 0;
sh_mem *shmptr = NULL;
int fd = 0;
char offset[2];
int no_bytes_read = 0;
int read_size = 10;
int count = 0;
int ret_val = 0;
/* Variables for semaphore */
int ret = 0;
int semid = 0;
key_t sem_key = 0;
struct sembuf op[1];
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
union semun arg;
/* Validate the i/p parameters */
if(argc < 3){
perror("argc:Did u forget the I/P file and the count 0?");
return -1;
}
printf("File : %s",argv[1]);
count = atoi(argv[2]);
/* Create a semaphore */
semid = semget(sem_key,1,IPC_CREAT | 0777);
if(semid == -1){
perror("semid:");
return -1;
}
arg.val = 1;
ret = semctl(semid,0,SETVAL,arg);
/* Open the file to read the contents */
fd = open(argv[1],O_RDONLY);
/* Calculate the total size of the file */
file_size = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
printf("\n File Size is : %d \n",file_size);
/* Create a new memory object */
fd_sh = shm_open("/myshm",O_RDWR | O_CREAT,0777);
/* Set the memory object's size */
if((ftruncate(fd_sh,sizeof(sh_mem))) == -1){
perror("ftruncate:ERROR");
return -1;
}
/* Map the Memory object */
shmptr = mmap(0,sizeof(sh_mem),PROT_READ | PROT_WRITE,MAP_SHARED,fd_sh,0);
/* Allocate the memory for the buffer */
shmptr->buffer = malloc((sizeof(char)*file_size));
printf("\nThe Map address is : 0x%08x\n",shmptr);
/* Copy the contents to the shared memory */
read(fd,&offset,1);
if(count == 0){
shmptr->offset = 0;
}
while(shmptr->offset < file_size){
/* Semaphore section Start */
op[0].sem_num=0;
op[0].sem_op=-1;
op[0].sem_flg=0;
semop(semid,op,1);
printf("\n ProcessA Entering! \n");
printf("\n initial offset value : %d \n",shmptr->offset);
if(shmptr->offset > 0){
shmptr->buffer = shmptr->buffer + shmptr->offset;
ret_val = lseek(fd,shmptr->offset,SEEK_SET);
}
no_bytes_read = read(fd,shmptr->buffer,read_size);
shmptr->offset = (read_size + shmptr->offset);
printf("\n offset : %d \n",shmptr->offset);
printf("\n contents : %s \n",shmptr->buffer);
sleep(10);
op[0].sem_op = 1;
semop(semid,op,1);
printf("\n ProcessA Leaving ! \n");
/* Semapore section End*/
}
/* Detach from the shared memory */
shmdt(shmptr);
close(fd);
close(fd_sh);
return 0;
}
I have process A, which has put the data into the shared memory containing the structure values offset and buffer. Process B wants to access the contents stored in the shared memory(offset,buffer), but I could able to access only offset. When tried to access the buffer i'm getting a segmentation fault. Why am i getting a seg fault. As the shared object is mapped to the shared memory.
Process A will put 10 bytes into the shared memory and will go to sleep, then again it continues to put the next 10 bytes and so on.
When tried to access the buffer i'm getting a segmentation fault.
buffer is declared as pointer as part of your mapped memory:
typedef struct sh_mem_t{
int offset;
char *buffer;
}sh_mem;
Transferring pointers between processes does not make sense, since the pointer does not have any meaning in the slave process - the data it points to still resides in the master process.
You need to include the actual data you want to transfer from master to slave process:
typedef struct sh_mem_t{
int offset;
char buffer[BUFSIZE];
}sh_mem;
With the updated code in the question, the following changes are necessary to make it work:
In both A and B, change the declaration of the shared memory struct to something like
typedef struct sh_mem_t{
int offset;
char buffer[1024];
}sh_mem;
In A, remove the malloc() for shmptr->buffer. Also remove the line where you adjust the buffer by adding the offset (shmptr->buffer = shmptr->buffer + shmptr->offset;) - that needs to be handled differently, if you still need it
In B, uncomment the line which prints the Good work! output.
With these changes, I was able to start the A process like ./A data.txt 0. When I then start the B process, it prints both offset and buffer content, as it was last printed by the A process.
Some additional remarks
You should use a header file to declare the sh_mem struct, and include this file in both your .c files, to make sure the declaration is consistent between A and B.
With the solution I posted above, the application will crash with file sizes > 1024. You need to handle this accordingly, to make sure to not exceed the buffer size.
Why isnt it working with pointers
You can not access (non-shared) memory from the master process in the slave process, especially not by simply passing a pointer through the shared memory (this would make the shared memory concept obsolete). The memory which you allocated with malloc() in your master process is not part of the shared memory segment, so it is not accessible from the slave process.
In addition, mmap(), by default, is not guaranteed to return the same virtual address in both processes. So, even when you pass a pointer which points to a location inside the shared memory segment in the master, it does not point anywhere useful inside the slave process, unless you pass specific parameters to mmap(). See mmap(2) for more details.
I am trying to write a code that shares a structure type, but im getting segmentation error when tryign to write in a structure member in the shared memory, the shared memory is between a parent and child process. as im showing in the code, im just tryin to access the struct member for now, so i can use semaphore later for synch.
Thanx in advance.
typedef struct file
{
char *shmPtr;
} file_entry;
int main (void)
{
int shmid;
int n;
file_entry *entries;
if (fork() == 0) {
/*wait for a while*/
if ((shmid = shmget(20441, sizeof(file_entry), 0666)) == -1) {
printf("shmget");
exit(2);
}
entries = (file_entry*) shmat(shmid, 0, 0);
if (entries->shmPtr == (char *) -1) {
printf("problem2");
exit(2);
}
printf("\nChild Reading ....\n\n");
printf("%s\n", entries->shmPtr[0]);
printf("%s\n", entries->shmPtr[1]);
putchar('\n');
printf("\nDone\n\n");
} else {
if ((shmid = shmget(20441, sizeof(file_entry), IPC_CREAT | 0666)) == -1) {
printf("problem3");
exit(2);
}
entries = (file_entry *) shmat(shmid, 0, 0);
if (entries->shmPtr == (char *) -1) {
printf("problem4");
exit(2);
}
printf("done attachment"); /*the parent prints this statment, then segmentation fault*/
entries->shmPtr[0]='a';
entries->shmPtr[1]='b';
putchar('\n');
wait();
shmdt(&shmid);
}
exit(0);
}
shmat returns a pointer to the shared memory area. In your code, after the call to shmat, entries points to the shared region. You are then treating the first few bytes of that shared area as a pointer to char (shmPtr). The value of shmPtr is uninitialized, and it points to some random location. Then you try to write to it and get a segfault.
Edit:
As Richard suggested, you could get rid of the struct and just use a char *. However, I'm guessing the reason you are using a struct and not just a char * is that you are planning to add some extra fields to the struct in the future. If that's the case, you can use a flexible array member:
typedef struct file
{
int flag;
int blah;
char shmPtr[];
} file_entry;
and the allocation becomes
shmget(20441, sizeof(file_entry) + bufsize, IPC_CREAT | 0666)
Of course, if the buffer size is fixed, you could just hardcode it:
typedef struct file
{
int flag;
int blah;
char shmPtr[BUFSIZE];
} file_entry;
/* ... */
shmget(20441, sizeof(file_entry), IPC_CREAT | 0666)
I am new to linux environment. I just know the basics of C. I am trying to learn linux programming. For this I am trying an example on shared memory. Please someone help me with this example.
I am trying to send person details (like name, phone number & address) to another process using Shared memory. After receiving the data by the second process, I am trying to save received data into a file. This is the task I am doing.
I am able to send just the name and receive it in the second process. Can someone please help how to send the data(like name, phone number & address) to second process and in the second process it must print the data and it should save the data to a file.
Here is my code:
address.c
char *shared_memory;
int main()
{
int select;
int segment_id;
char* shared_memory;
int segment_size;
key_t shm_key;
const int shared_segment_size = 0x6500;
shm_key = ftok("/home/madan/programs/shm_tok",'C');
if(shm_key < 0) {
printf("failed to create the key %s\n",strerror(errno));
}
/* Allocate a shared memory segment. */
segment_id = shmget (shm_key, shared_segment_size,
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
if(segment_id < 0) {
printf("error geting the segment id %s\n",strerror(errno));
}
printf("segment ID:%d\n", segment_id);
/* Attach the shared memory segment. */
shared_memory = (char*) shmat (segment_id, 0, 0);
printf ("shared memory attached at address %p\n", shared_memory);
/* I want to send these details to the shared memory. Can someone suggest me the correct way to send these details to shared memory so that second process can retrieve them*/
sprintf(shared_memory, "maddy\n");
sprintf(shared_memory, "767556686");
sprintf(shared_memory, "Ontario");
system("./address-insert");
/* Detach the shared memory segment. */
shmdt (shared_memory);
/
* Deallocate the shared memory segment.*/
shmctl (segment_id, IPC_RMID, 0);
}
addres-insert.c
int main ()
{
int segment_id;
char* shared_memory;
FILE *fp;
char *name;
int segment_size;
key_t shm_key;
shm_key = ftok("/home/madan/programs/shm_tok",'C');
const int shared_segment_size = 0x6500;
/* Allocate a shared memory segment. */
segment_id = shmget (shm_key, shared_segment_size,
S_IRUSR | S_IWUSR);
if(segment_id < 0) {
printf("error:[%s]",strerror(errno));
}
printf("segment id %d\n",segment_id);
/* Attach the shared memory segment. */
shared_memory = (char*) shmat (segment_id, 0, 0);
if(shared_memory == NULL) {
printf("failed to attach the shared memory %s",strerror(errno));
}
printf ("shared memory2 attached at address %p\n", shared_memory);
/* printing the data from shared memory send by first process*/
printf ("name=%s\n", shared_memory);
/*copying the data in shared memory so i can save them to a file*/
strcpy(name, shared_memory);
printf("%s", name);
/*here i have to save the data to a file. But i don't know how to do it, can someone help me with this please*/
/* Detach the shared memory segment. */
shmdt (shared_memory);
return 0;
}
For saving the data in a file, you can use file stream. For that you have to know about file streams.
Hope these link will help.
http://linux.die.net/man/3/fopen
http://en.wikipedia.org/wiki/C_file_input/output
Here comes the example program which I particularly typed, compiled and attached it for your reference.
#include<sys/types.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
struct mystruct // you can make your own structure if you want to pass many data
{
int i;
float f;
char c;
int arr[3];
}myObj = {1,1.1,'C',{100,1000,10000}};
main()
{
int shmid;
char* addr1;
key_t key;
//file to key. Generates a unique key
key = ftok("/home/muthu/Desktop/anyfile.txt",'T');
shmid = shmget(key,sizeof(struct mystruct),IPC_CREAT|SHM_R|SHM_W);
printf("shmid = %d",shmid);
addr1 = shmat(shmid,0,0);
printf("\nIPC SHARED MEMORY");
//copying your structure at the shared location.
memcpy(addr1,&myObj,sizeof(myObj));
printf("\nMESSAGE STORED");
}
And for shared memory 2.....
//<All necessary header files>
//<same my struct declaration here>
main()
{
int shmid;
char* addr1;
FILE* fp;
key_t key;
struct mystruct* myObj2;
//Generate the same unique key. Must provide the same file here too.
key = ftok("/home/muthu/Desktop/anyfile.txt",'T');
shmid = shmget(key,sizeof(struct mystruct),SHM_R|SHM_W);
addr1 = shmat(shmid,0,0);
myObj2 = (struct mystruct*)malloc(sizeof(struct mystruct)*1);
if(shmid == -1)
printf("\nShared memory error");
//Retrieve the stored information, form the shared location.
memcpy(myObj2,addr1,sizeof(struct mystruct));
fp = fopen("/home/muthu/Desktop/MyFile.txt","w"); //open a file stream
if(fp == NULL)
printf("\nError on opening file stream.\n");
fprintf(fp,"\nIPC SHARED MEMORY");
fprintf(fp,"\nMESSAGE RECIEVED FORM THE SHARED MEMORY IS..\n");
fprintf(fp,"\ninteger: %d",myObj2->i);
fprintf(fp,"\nfloat: %f",myObj2->f);
fprintf(fp,"\nchar: %c",myObj2->c); //write to the file
fprintf(fp,"\narr: %d %d %d",myObj2->arr[0],myObj2->arr[1],myObj2->arr[2]);
fprintf(fp,"\nDATA RECIEVED.");
fclose(fp); //close the file stream
printf("\nMessage successfully stored!");
}
Here is a snippet that you can use
fp = fopen("filename","a+");
fwrite(name, 1, strlen(name),fp);
fclose(fp);
You can store all your three fields onto a structure and load the structure onto the Shared Memory. In this way you are assured to have all the fields under one structure.
In the process that reads the SHM you can use the File Stream utils as mentioned above by others.