How to use struct in POSIX shared memory? - c

I want my POSIX shared memory segment to conform to a particular structure. I think this code creates the shared memory segment in the shape of the struct.
(File creating the shared memory segment)
typedef struct {
int cnt;
char buf[segsize];
} shmseg_t;
int shm_fd = shm_open(shm_name, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, sizeof(shmseg_t);
void* addr = mmap(NULL, sizeof(shmseg_t), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
How do I write data from a file to the different fields of the struct in the shared memory?
(File writing to the shared memory segment)
int shm_fd = shm_open(shm_name, O_WRONLY, 0);
ftruncate(shm_fd, segsize);
void* addr = mmap(NULL, segsize, PROT_WRITE, MAP_SHARED, shm_fd, 0);
// How do I get shmp, which should be a shmseg_t struct?
shmp->cnt = read(fd, shmp->buf, segsize);
And how do I get out the data that was written to the struct in the shared memory?
(File reading from the shared memory segment)
int shm_fd = shm_open(shm_name, O_RDONLY, 0);
ftruncate(shm_fd, segsize);
void* addr = mmap(NULL, segsize, PROT_READ, MAP_SHARED, shm_fd, 0);
// How to get out shmp->cnt and shmp->buf?

It is unclear whether you want to share the entire structure or just buf.
Option 1: Make buf a pointer, and share what it points to.
typedef struct {
int cnt;
char *buf;
} shmseg_t;
ftruncate(shm_fd, segsize);
void* addr = mmap(NULL, segsize,
PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
assert(addr != MAP_FAILED);
shm_seg_t shmp = {
.cnt = ???, // Whatever value of cnt you want.
.buf = addr,
};
Option 2: Share the entire struct.
typedef struct {
int cnt;
char buf[segsize];
} shmseg_t;
ftruncate(shm_fd, sizeof(shmseg_t));
void* addr = mmap(NULL, sizeof(shmseg_t),
PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
assert(addr != MAP_FAILED);
shm_seg_t *shmp = addr;
If you share it this way, reading and writing are not really different (but you do need to use memory barriers or synchronization).

Related

Why is my string not showing after transfer via SHM?

I've created the following types to transfer a list of nodes from one process to the other one:
typedef struct {
char *from;
char *to;
} Edge;
typedef struct {
size_t numEdges;
Edge *fst;
} EdgeList;
typedef struct {
EdgeList buffer[BUFFER_SIZE];
...
} CircularBuffer; /**< used as shared memory. */
This is what the process that sends the EdgeList looks like:
// open shared memory -> shm_open()
int shm_fd = shm_open(SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR);
...
// map shared memory into memory -> mmap()
CircularBuffer *shm = mmap(NULL, sizeof(CircularBuffer),
PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
...
while (true) {
shm->buffer[...] = getSolution(...);
...
}
...
This is what the process that receives the EdgeList looks like:
// create shared memory -> shm_open()
int shm_fd = shm_open(SHM_PATH, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
...
// set shared memory size -> ftruncate()
ftruncate(shm_fd, sizeof(CircularBuffer);
...
// map shared memory into memory -> mmap()
CircularBuffer *shm = mmap(NULL, sizeof(CircularBuffer),
PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
...
EdgeList bestSolution = {.numEdges = SIZE_MAX, .fst = NULL};
while (true) {
EdgeList solution = shm->buffer[...];
if (solution.numEdges < bestSolution.numEdges) {
bestSolution = solution;
// I can read 'bestSolution.numEdges' here just fine.
// But i can't read 'bestSolution.fst[i].from' and 'bestSolution.fst[i].to' for some reason.
}
...
}
...
Now here is where things behave unexpectedly: The receiving process is not showing me any strings from the shared memory but everything else works just as expected.
I have access to bestSolution.numEdges after it being read from the shared memory, but not to bestSolution.fst[i].from and bestSolution.fst[i].to (with i being a legal index from that array).
When I try to read these strings, I only see (null) instead of the strings. Can I fix this issue?

copying with memcpy some data to mmap return pointer address location of a file

If I have a file which I mapped with mmap like this
sfd = open("test.txt", O_RDONLY);
filesize = lseek(sfd, 0, 10);
src = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, sfd, 0);
so right now the sizeof mapping is 0 bytes because size of test.txt is 0. So what if I want to write word hello to mapped area. How to do it?
I tried like this
memcpy(src,"hello", sizeof("hello"));
But this throws Bus error. I could use mremap but that is not available on my system. So I like to know how to write to mapped area something with memcpy
Update
This is my code and now it giving me segFault at memcpy line
int main(int argc, char **argv){
int sfd, dfd;
char *src, *dest;
size_t filesize=10;
/* SOURCE */
sfd = open("test.txt", O_RDWR);
src = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, sfd, 0);
ftruncate(sfd,10);
if(src== MAP_FAILED)
{printf("error\n");exit(0);}
/* DESTINATION */
memcpy(src,"hello", sizeof("hello"));
munmap(src, filesize);
close(sfd);
close(dfd);
return 0;
}

ftruncate() invalid arguement error

I just started learned about shared memory and we are suppose to create an object of shared memory for my assignment, but I keep getting an error when I run my program.
The error comes from the ftruncate() function and it keeps telling me its an invalid argument, here's my code segment for the shared memory:
struct container* rPtr;
int fd;
/* Creates shared memory object and sets it size */
fd = shm_open("/collatzRegion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd == -1)
{ perror("shm_open");
return 1;
}
if ((ftruncate(fd, sizeof(struct container))) == -1)
{ perror("ftruncate");
return 1;
}
/* Maps shared memory object */
rPtr = mmap(NULL, sizeof(struct container), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if ( rPtr == MAP_FAILED)
{ perror("mmap");
return 1;
}
and my structure, that is defined before my main(), is:
/* Defines "structure" of shared memory */
#define MAX_LEN 10000
struct container
{ int length;
int buf[MAX_LEN];
};

c - writing to shared memory segment causes segmentation fault

I'm having problems with writing to shared memory segment. Here's the code:
EDIT: after I removed that == (mistake), now I'm getting Bus Error (Core Dumped), here's the edited code:
// Struct for data from shared memory
typedef struct {
pthread_mutex_t shared_mutex;
int last_used_job_id;
} shared1;
static void *job_generator(void *param)
{
int J = *((int *) param);
shared1 *shd;
int shm;
int job_id;
// Open shared memory, don't create it if doesn't exist
shm = shm_open("/lab5", O_RDWR, 00600);
// Check
if (shm == -1) {
// Open shared memory, create it if doesn't exist (O_CREAT)
shm = shm_open(q_name, O_RDWR | O_CREAT, 00600);
// Map space for struct
shd = mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if (shd == (void *) -1) {
perror ( "mmap" );
exit(1);
}
// Initialize mutex
if (pthread_mutex_init(&(shd->shared_mutex), NULL) != 0)
{
printf("Mutex initialization failed!\n");
exit(1);
}
}
else
{
// Map space for struct
shd = mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if (shd == (void *) -1) {
perror ( "mmap" );
exit(1);
}
}
// Lock mutex
pthread_mutex_lock(&(shd->shared_mutex));
job_id = shd->last_used_job_id + 1;
shd->last_used_job_id = job_id + J;
printf("a: %d\n", shd->last_used_job_id);
return NULL;
}
it's caused by any of the instructions which are using shd, so any of these:
// Lock mutex
pthread_mutex_lock(&(shd->shared_mutex));
job_id = shd->last_used_job_id + 1;
shd->last_used_job_id = job_id + J;
printf("a: %d\n", shd->last_used_job_id);
I think this is where your problem lies:
shd == mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
You're comparing shd to the return value of mmap with '=='. I think you meant to use a single '=' which would assign the return value to shd.

C - Reading an integer through shared memory with mmap

Currently I have got my shared memory working between 2 processes
my parent looks like this
/* strings written to shared memory */
const char *message_0 = "Hello";
const char *message_1 = "World!";
/* shared memory file descriptor */
int shm_fd;
/* pointer to shared memory obect */
void *ptr;
/* create the shared memory object */
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory object */
ftruncate(shm_fd, SIZE);
/* memory map the shared memory object */
ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
/* write to the shared memory object */
sprintf(ptr,"%s",message 0);
ptr += strlen(message_0);
sprintf(ptr,"%s",message 1);
ptr += strlen(message_1);
and my child process receives the code like so
const char *name = "OS";
/* shared memory file descriptor */
int shm_fd;
/* pointer to shared memory obect */
void *ptr;
/* open the shared memory object */
shm_fd = shm_open(name,O_CREAT | O_RDWR, 0666);
/* memory map the shared memory object */
ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
/* read from the shared memory object */
//char message = ptr;
//int newmsg;
//newmsg = atoi(message);
printf("%s",(char *)ptr);
printf("\n");
Now instead of passing hello world I would like to pass arrays instead, so I tried changing the end of my parent to try passing a single integer.
sprintf(ptr, "%d", 5);
ptr += 20; //just used 20 since it should be big enough for now
and in my child process I changed
printf("%d",(char *)ptr);
to
printf("%s", (int *)ptr);
However my message always messes up somewhere, and I print an invalid number instead. Can anyone tell me what i am missing?
You shouldn't try to represent your numeric values as strings when passing them via memory. Your receiver should just take a pointer to the address where you put your int, and interpret it as int:
child:
ptr = (int*) mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
....
int value = *ptr;

Resources