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;
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?
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).
I tried to realize shared memory with C, but I came up with a problem with my output.
I tried to make a thread called TA put the grade into a shared memory space and make "student" thread output the grade.
In the TA thread:
const int SIZE = 4096;
const char *name_ta = "Students_Information_ta";
int studentGrade = (int)((random() % (100 - 80 + 1)) + 80); // TA gives out a grade to a student
char *grade = (char *)&studentGrade;
/* shared memory file descriptor */
int shm_fd_ta;
/* pointer to shared memory object */
void *ptr_ta;
/* create the shared memory segment of ta */
shm_fd_ta = shm_open(name_ta, O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory segment of ta*/
ftruncate(shm_fd_ta, SIZE);
/* map the shared memory segment of ta in the address space of the process */
ptr_ta = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_ta, 0);
if (ptr_ta == MAP_FAILED)
{
printf("Map failed\n");
return -1;
}
/* write to the shared memory region */
sprintf(ptr_ta, "%d", grade);
ptr_ta += strlen(grade);
And here is the output sentences in student thread:
/* name of shared memory object */
const char *name_ta = "Students_Information_ta";
/* size of shared memory object in bytes */
const int SIZE = 4096;
int shm_fd_ta;
void *ptr_ta;
/* open the shared memory segment of ta */
shm_fd_ta = shm_open(name_ta, O_RDWR, 0666);
if (shm_fd_ta == -1)
{
printf("shared memory failed\n");
exit(-1);
}
/* map the shared memory segment of ta in the address space of the process */
ptr_ta = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_ta, 0);
if (ptr_ta == MAP_FAILED)
{
printf("Map failed\n");
exit(-1);
}
printf("The grade assigned by the TA is %d\n", ptr_ta); // student receives a grade
I thought it should gave me the grades which are numbers between 80 and 100, but in fact the output is some very large numbers like 251142144. Perhaps it has output the address. What can I do to fix this mistake?
char *grade = (char *)&studentGrade;
Okay, so grade is of type pointer to character but is pointing to an integer. Not sure why you'd want to do that, but okay.
sprintf(ptr_ta, "%d", grade);
You told sprintf to print an integer but you passed it a pointer to a character that points to an integer. The sprintf function certainly has no idea what to do with such a mismatched pointer, especially when you told it you were going to pass it an integer.
Why not:
sprintf(ptr_ta, "%d", studentGrade);
If you tell it you're going to give it an integer, maybe give it an integer.
--
ptr_ta = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_ta, 0);
if (ptr_ta == MAP_FAILED)
{
printf("Map failed\n");
exit(-1);
}
Now, ptr_ta is a pointer to the string you printed.
printf("The grade assigned by the TA is %d\n", ptr_ta); // student receives a grade
You told printf you were going to pass it an integer, but instead you passed it a pointer to a string. How is that supposed to work?
I'd change a lot of things, but this is a start:
printf("The grade assigned by the TA is %s\n", (char *) ptr_ta); // student receives a grade
int main() {
int mfd; //file descriptor for the shared object
int seg_size = (sizeof(message)); //shared object sized to store message
char *shared_msg;
// create the shared memory object with shm_open()
mfd = shm_open(SHARED_OBJ_PATH, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG);
if (mfd < 0) {
perror("error in shm_open()");
exit(1);
}
printf("I have created a lucky shared memory object: %s\n", SHARED_OBJ_PATH);
ftruncate(mfd, seg_size) ; // define size of shared memory object
// map the shared memory object to this process
shared_msg = mmap(NULL, seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0);
if (shared_msg == NULL) {
perror("error in mmap()");
exit(1);
}
printf("Shared memory is now allocated %d bytes\n", seg_size);
memcpy(shared_msg, "Hello Man", 30); //put something onto the memory
printf("Message content is: %s\n\n Hit any key to finish!\n", shared_msg) ;
getchar() ; // wait for user to hit any key
shm_unlink(SHARED_OBJ_PATH) ; // unlink - better to add error check
return 0 ;
}
I don't know how to use write function, I just delete memcpy() and change it to write (fd, buf, 30), I do not know how to display "Hello Man".
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.