My process is accessing a shared memory that is already created. The pointer attached to the shared memory is a structure containing a pointer and 2 or 3 variables.
eg:
typedef struct _info_t{
int id;
char c;
}info_t;
typedef struct _details_t{
int buff_id;
info_t* info;
}details_t;
details_t* details = shmat(shmid,(void*)0,0);
printf("\n %d \n",details->info->id); // gives me a segmentation fault
If a memory segment is shared between more than one process, there's no guarantee it will be mapped at the same address, so you cannot store pointers in shared memory segment. Try to avoid using pointers, use offsets or arrays (if possible).
shmat(2) is a syscall (on Linux). It may fail. So at least code
details_t* details = shmat(shmid,(void*)0,0);
if (!details) { perror("shmat"); exit(EXIT_FAILURE); };
and you cannot put (easily) pointers in shared memory, since the address is specific to each process.
Related
I am declaring a structure and one of the structure member is a pointer which store the address of IPC buffer .
The ipc_buffer is the local to one method and when I am passing the address of same buffer to another function and sending over IPCWrite() observing data corruption in IPC_recevie side ?
Could anyone have pointer here why the data got corrupted ?
typedef struct ev_entry_s
{
event_t ev_id;
uint8_t *ipc_local_async_buff;
uint32_t ev_data_size;
uint8_t ev_data[0];
}ev_entry_t;
fun_1()
{
uint8_t ipc_buffer[IPC_MAX_SEND_LEN];
fun_2(&ipc_buffer); /*sending as a parameter */
}
fun_2(uin8_t *catch_pointer)
{
ev_entry_t event_p;
//Storing ipc_buffer addres in ipc_local_async_buff
event_p.ipc_local_async_buff = catch_pointer;
fun_3(&event_p);
}
fun_3(ev_entry *event_p)
{
/*sending the address of ipc_buffer over IPCWrite*/
}
On Linux processes do not share memory by default. Memory allocated for one process is not allocated for other processes.
Pointers are simply not sharable between processes.
You need to use shared memory. And not send pointers, but instead give a name to the shared memory segment so the other process can find it. Then use some other IPC mechanism to signal the other process that the memory can be read.
This question already has answers here:
how to use shared memory to communicate between two processes
(3 answers)
Closed 5 years ago.
I have a variable with a value and I want to share it with the proccesses.
Ex:
typedef struct {
unsigned int a;
unsigned int b;
another_struct * c;
} struct1;
...
struct1 A ={...};
...
Now, I want to create a shared memory region and put the A variable in this region. How can i do this?
Shared memory is an operating system feature (which does not exist in C11). It is not "provided" by the C standard.
I guess that you are coding for Linux. BTW, read Advanced Linux Programming.
Read first shm_overview(7). You'll need to synchronize, so read also sem_overview(7).
You'll get some shared memory segment into a pointer and you'll use that pointer.
First, open the shared memory segment with shm_open(3):
int shfd = shm_open("/somesharedmemname", O_RDWR|O_CREAT, 0750);
if (shfd<0) { perror("shm_open"); exit(EXIT_FAILURE); };
Then use mmap(2) on that shfd:
void* ad = mmap(NULL, sizeof(struct1), PROT_READ|PROT_WRITE, MAP_SHARED,
shfd, (off_t)0);
if (ad==MAP_FAILED) { perror("mmap"); exit(EXIT_FAILURE); };
Then you can cast that address into a pointer:
struct1* ptr = (struct1*)ad;
and use it. (Don't forget to close).
BTW, you don't and you cannot put a variable into a shared memory. You get a pointer to that shared memory and you use it, e.g. ptr->a = 23;
Of course, don't expect the same shared segment to be mapped at the same address (so you can't easily deal with pointer fields like c) in different processes. You probably should avoid pointer fields in shared struct-s.
Notice that C variables exist only at compile time. At runtime, you only have locations and pointers.
PS. Shared memory is a quite difficult inter-process communication mechanism. You should perhaps prefer pipe(7)-s or fifo(7)-s and you'll need to multiplex using poll(2).
Take a look at Beej's Guide to IPC.
I would basically treat the whole shard memory segment as a void* that you can place items at. You could use memcpy, of string.h, to copy A into your shared memory space. However your pointer in A would become invalid and cause a segfault if you attempted to use it in another process connected to shared memory segment.
I have 2 programs which need to share memory. Let's call one program A, the other one B.
There is a struct in this format for this purpose:
struct town_t {
int population;
char * name;
}
In program A, data gets written to shared memory using mmap. This works for program A. (It uses strcpy for the name)
Program B's purpose is to simply read the data. This too works with mmap. Accessing the shared memory's population field works without any problems. However, accessing the population field gives a segmentation fault.
Since I used strcpy, the entire string should be in the shared memory right?
I use the following flags to get the pointer to shared memory, which returns no error.
tptr = (struct town_t *) mmap(0, 1024, PROT_READ, MAP_SHARED, shm_fd, 0)
How could I make it so I can actually read the string (char*) from program B?
There's no point in putting a pointer in shared memory. A pointer gives a location inside the address space of a particular process. It would have no meaning to another process with another address space. (With some complicated exceptions such as a pointer to memory allocated before a call to fork accessed by related processes running the same executable.)
You can store the string data itself in shared memory if you wish. For example, this will work:
#define MAX_NAME_SIZE 100
struct town_t
{
int population;
char name[MAX_NAME_SIZE];
};
I have a "Server" and a "Client" process, they "communicate" through a struct shared memory.
typedef struct
{
char* buffer;
int cards;
int maxCards;
} myStruct
Both "Server" and "Client" processes can get/set the values of the two int types, but the thing is different with the buffer (we use this as a pointer to chars): the "Server" allocates memory, like:
(*sharedMem).buffer = (char*) malloc(sizeof(char)*maxCards);
has the ability to set or get values:
(*sharedMem).buffer[0] = 'a';
printf("%c\n",(*sharedMem).buffer[0]);
but when the "Client" process tries to access a char:
printf("%c\n",(*sharedMem).buffer[0])
It collapses with Segmentation Fault Core Dumped error.
Is there a way to solve this problem without using an Array or List? Any Ideas?
Both processes have different address spaces, so pointers in one are generally meaningless in the other (except for possibly NULL).
If you need to exchange more data between processes, you could use
pipes (see the pipe() system call)
shared memory (see POSIX shm* calls)
memory mapped files (see mmap())
use an array-of-char in your struct
If I have some struct
struct processData{
int *a;
int *b;
}
And I set up my shared memory ID as
int shmid = shmget(1234, sizeof(processData), IPC_CREAT | 0666);
Where 1234 is my key
Would I set up my actual shared struct like this..
processData* pData =(processData *) shmat(shmid, NULL, 0);
And then shouldn't I be able to change things around in seperate processes like:
pData -> a = SOME_NUMBER;
When I do this, all of my processes aren't interacting with the same piece of memory and I'm clueless why.
The members *a and *b in your structure processData are integer pointer type. Attaching a shared memory to your process does not make them point to a memory location inside the shared memory. Secondly the shared memory that you are creating using the shmget() function in the first place has only enough space to hold a processData data type. You will need some additional memory space to hold two int data types which *a and *b will point to and off course these memory spaces should also be shared so that other processes can access it.
So the solution to your problem will be something like this.
//Create the shared memory to hold the structure.
shmid=shmget(KEY1,sizeof(struct processData),IPC_CREAT|0666);
//Attach it to the process.
pData=shmat(shmid,0,0);
//Create a shared memory to hold an integer which will be pointed by *a.
shmid=shmget(KEY2,sizeof(int),IPC_CREAT|0666);
//Attach the shared memory to the location pointed by *a.
pData->a=shmat(shmid,0,0);
//Create a shared memory to hold an integer which will be pointed by *b.
shmid=shmget(KEY3,sizeof(int),IPC_CREAT|0666);
//Attach the shared memory to the location pointed by *b.
pData->b=shmat(shmid,0,0);
This is the way you should create and attach the shared memories to all the processes that are going to access the shared memory.
(Note: You do not need to create 3 separate shared memories using 3 separate key values. It can also be done by creating a single chunk of shared memory of sufficient size using 1 key and then seeking the pointers to the their respective positions inside the shared memory. It is a little complicated that is why I have given a simple example for better understanding.)
Now coming to the next problem. Since you are using pointers in your structure you cannot assign values to them like this, pData -> a = SOME_NUMBER;. Because, pData -> a is a pointer, to assign some value to it you need to deference it. So it will be done like this.
*(pData -> a) = SOME_NUMBER;
Similarly to read the value in other processes will also need to derefence it there.
SOME_NUMBER = *(pData -> a);
When in your local process you copy the pointer of a int into your struct with:
pData -> a = some-pointer;
you are actually copying the logical memory address (which is valid in your current process) into the shared memory.
When from another process you read such value, it will be a logical memory address occupied by something else (possibly also out of current addressable space).