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
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?
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;
}
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];
};
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.
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;