1

I'm learning about process management and shared memory, and I was wondering if someone could help me out. I'm trying to read in a large-ish text file (2MB) with a forked parent process and feed it to the corresponding child process to be ... well ... processed. However, my proof of concept mini program cannot READ the data I write into the shared memory. Calling 'capacity()' and 'length()' work fine, but actually attempting to retrieve the data stored there returns an empty string. I even tried copying the contents from the pointer into an array of characters, but still nothing. Any thoughts?

Program code:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

using namespace std;

#define SHM_SIZE 2000000    // 2 MB of shared memory

int main(int argc, char* argv[])
{
    string* data = (string*) mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, 
    MAP_SHARED | MAP_ANONYMOUS, -1, 0);

printf("Shared memory capacity before reserve: %ld\n", data->capacity());
data->reserve(SHM_SIZE); // make sure string can use all available space
printf("Shared memory capacity after reserve: %ld\n", data->capacity());

switch(fork())
{
    case -1:
        printf("Something went wrong ... exiting program\n");
        break;
    case 0:
        usleep(1000 * 1000 * 2); // force child to wait for sanity purposes
        printf("\nChild capacity:  %ld\n", data->capacity());
        printf("Child contents:  %s\n", data->c_str());
        break;
    default:
        // Sample input ... file reading logic omitted for brevity
        *data = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean leo elit, aliquam "
            "vitae aliquam sed, rhoncus et mi. Aliquam erat volutpat. Phasellus non urna sit amet "
            "enim tincidunt aliquam quis sit amet orci. Maecenas velit turpis, venenatis eu diam "
            "vel, varius volutpat nulla. Nam mi massa, tristique eget imperdiet id, dictum ut urna. "
            "Nulla id massa placerat, finibus purus quis, ornare neque. Vivamus eget varius ante. "
            "Aenean varius ac neque quis ultricies. Donec vitae bibendum dolor, vitae tempor augue.";
        printf("\nParent capacity:  %ld\n", data->capacity());
        printf("Parent contents:  %s\n", data->c_str());

        wait(NULL);
        munmap(data, sizeof *data);
        printf("\nHello world\n");
        break;
}

return 0;
}

Output:

MacBook-Pro:sharedmem-test slehr$ ./sharedmem-mapred 
Shared memory capacity before reserve: 22
Shared memory capacity after reserve: 2000015

Parent capacity:  2000015
Parent contents:  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean leo elit, aliquam vitae aliquam sed, rhoncus et mi. Aliquam erat volutpat. Phasellus non urna sit amet enim tincidunt aliquam quis sit amet orci. Maecenas velit turpis, venenatis eu diam vel, varius volutpat nulla. Nam mi massa, tristique eget imperdiet id, dictum ut urna. Nulla id massa placerat, finibus purus quis, ornare neque. Vivamus eget varius ante. Aenean varius ac neque quis ultricies. Donec vitae bibendum dolor, vitae tempor augue.

Child capacity:  2000015
Child contents:  

Hello world
MacBook-Pro:sharedmem-test slehr$ 
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • 3
    No, seriously? `string* data = (string*) mmap(...)`? No way this will work. Try something like `memcpy` to the mapped address. Note that a `string` is not just something like a pointer, it's an object (which, among other things, contains a pointer). – Damon Sep 29 '17 at 14:17
  • 1
    C and C++ are different languages. In particular here you seem to have a C++ problem, how to have a C++ `string` point to a shared memory. I removed the C tag. – Jens Gustedt Sep 29 '17 at 14:20

1 Answers1

1

A std::string is likely to be some data structure with a size, a length, a pointer (or something similar). You can't expect its internal pointer to point to shared memory

with mmap-ed memory you should use raw pointers, e.g.

auto data = (char*) mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, 
                         MAP_SHARED | MAP_ANONYMOUS, -1, 0);

Of course you should test against failure:

if (data==(char*)MAP_FAILED) { perror("mmap"); exit(EXIT_FAILURE); };

Read again mmap(2)

You might consider shm_overview(7) (and look at sem_oveview(7) for synchronization)

Read Advanced Linux Programming

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • You are absolutely correct about the std::string data structure ... I changed it to char* and was able to get it working with the help of memcpy(). Thanks so much! – Sarah Lehman Sep 29 '17 at 15:54