Why is my string not showing after transfer via SHM? - c

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?

Related

How to use struct in POSIX shared memory?

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).

Inter process communication via shared memory

I am trying do an inter process communication using shared memory. Here is the structure definition.
#define SHM_SIZE (519430400)
test_ht *CommandLine_Buffer;
typedef struct
{
int a;
int testnum;
st_cl cli[3];
}test_ht;
typedef struct
{
tHT CliInfo;
} st_cl;
typedef struct
{
int x;
} tHT;
Shared memory is created as below
int fd;
int ret_v;
void* addr;
int i;
fd = shm_open("SharedBuf.shm", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
ret_v = ftruncate(fd, SHM_SIZE);
SharedBuffer = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, SEEK_SET);
I access the structure members as below
CommandLine_Buffer->cli[i].CliInfo.x
Here I can read and write a and testnum across procesess. Shared memory is created successfully.
At the same time I can access
CommandLine_Buffer->cli[0].CliInfo.x and CommandLine_Buffer->cli[1].CliInfo.x
Am unable to get CommandLine_Buffer->cli[2].CliInfo.x.
Any tips to debug this or any idea why am unable to read the last location.

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