0

What I want to do is to create a globally shared variable to be accessed by different processes. I want the child process to be replaced by an existing executable.

UPDATE: I think this is the solution. The code is borrowed from here. But since every process needs at least one I/O operation to mmap the file, is there any faster approach?

mycode.h

static void* addr; //static

app1.cc

include

#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h> 

int main(void)
{
    size_t length = 1024 * 1024;
    off_t offset = 0;
    int prot = (PROT_READ| PROT_WRITE);
    int flags = MAP_SHARED;
    int fd = -1;

    fd = open("./jim.mymemory", O_RDWR| O_CREAT, S_IRUSR| S_IWUSR );
    if (fd == 0) {
        int myerr = errno;
        printf("ERROR: open failed (errno %d %s)\n", myerr, strerror(myerr));
        return EXIT_FAILURE;
    }

    addr = mmap(NULL, length, prot, flags, fd, offset);
    if (addr == 0) {
        int myerr = errno;
        printf("ERROR (child): mmap failed (errno %d %s)\n", myerr,
                strerror(myerr));
    }
    *((int *) addr)=5;
if (munmap(addr, length) == -1) {
        int myerr = errno;
        printf("ERROR (child): munmap failed (errno %d %s)\n", myerr,
                strerror(myerr));
    }    
return 0;
}

mycode.cc

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "mycode.h"

int main(void) {
    size_t length = 1024 * 1024;
    off_t offset = 0;
    int prot = (PROT_READ| PROT_WRITE);
    int flags = MAP_SHARED;
    int fd = -1;
    pid_t pid;

    fd = open("./jim.mymemory", O_RDWR| O_CREAT, S_IRUSR| S_IWUSR );
    if (fd == 0) {
        int myerr = errno;
        printf("ERROR: open failed (errno %d %s)\n", myerr, strerror(myerr));
        return EXIT_FAILURE;
    }
    if (lseek(fd, length - 1, SEEK_SET) == -1) {
        int myerr = errno;
        printf("ERROR: lseek failed (errno %d %s)\n", myerr, strerror(myerr));
        return EXIT_FAILURE;
    }
    write(fd, "", 1);

    if ((pid = fork()) == 0) { // child
        /*Child process*/

        printf("INFO (child): start \n");
        execv("./app1", NULL); // **app1**
        printf("INFO (child): done \n");

        msync(addr,sizeof(int),MS_SYNC|MS_INVALIDATE); // can  be commented out, since we wait in the parent process

    } else {
        /*Parent process*/
        unsigned int readval = 0;
        addr = mmap(NULL, length, prot, flags, fd, offset);
        if (addr == 0) {
            int myerr = errno;
            printf("ERROR (parent): mmap failed (errno %d %s)\n", myerr,
                    strerror(myerr));
        }

        printf("INFO (parent): start read\n");
        wait(NULL);
        readval = *((int *) addr);
        printf("val: %d \n", readval);
        printf("INFO (parent): done read\n");

        if (munmap(addr, length) == -1) {
            int myerr = errno;
            printf("ERROR (parent): munmap failed (errno %d %s)\n", myerr,
                    strerror(myerr));
        }
    }

    if (close(fd) == -1) {
        int myerr = errno;
        printf("ERROR: close failed (errno %d %s)\n", myerr, strerror(myerr));
    }
    unlink ("./jim.mymemory");
    return EXIT_SUCCESS;
}

Any help is appreciated.

towi_parallelism
  • 1,421
  • 1
  • 16
  • 38
  • 1
    Instead of creating an anonymous mmap, you could use a real file. – Vaughn Cato Jun 03 '13 at 03:50
  • @VaughnCato: thanks. but would it be possible to do something like this?`struct Costume_Struct* my_struct;` and then in the processes `addr = mmap(NULL, length, prot, flags, fd, offset); Costume_Struct* proc_struct = (Costume_Struct*) addr` – towi_parallelism Jun 03 '13 at 09:23

1 Answers1

3

The execve will drop all mappings in the kernel, so this technique will not work. What you can do instead is open a file (as in Vaughn's suggestion) and pass the descriptor to the child process. Open file descriptors are unchanged across an exec. Then you can map it in the child. Alternatively, investigate APIs like shm_open()/shm_unlink() which will manage a global file mapping such that other processes can use it, not just a child.

But basically: you have to mmap() in the child, you can't pass anything in your address space to the child in Unix.

Andy Ross
  • 11,699
  • 1
  • 34
  • 31
  • Thanks. But what if I want to share a structure? Should I implement it as text in the shared file? or is this possible:`struct Costume_Struct* my_struct;` and then in the processes `addr = mmap(NULL, length, prot, flags, fd, offset); Costume_Struct* proc_struct = (Costume_Struct*) addr` ? – towi_parallelism Jun 03 '13 at 09:21
  • 2
    Yes, you can put structs (but not C++ objects, at least without great care to make sure they are "POD") in the shared memory. It will work exactly as you think it will; it's just m emory. – Andy Ross Jun 03 '13 at 15:30
  • Many Thanks! What about my last question? -> Since every process needs at least one I/O operation to mmap the file, is there any faster approach? – towi_parallelism Jun 03 '13 at 15:54
  • 1
    Doing an exec inherently involves many mmap operations (at the very least ld-linux.so and the executable .text segment, dynamic binaries have many more). Adding one more is not a meaningful overhead IMHO. – Andy Ross Jun 03 '13 at 18:14
  • Maybe I didn't clearly convey my meaning. I mean, this approach comes with an "open file" operation which is an I/O operation. Is there any other way to start from the memory itself rather than memory mapping a file? – towi_parallelism Jun 03 '13 at 18:26
  • 2
    Again, "open file" is a fast operation that is already done multiple times underneath every exec. Adding one really isn't a problem that I can see. Rather, if it is, your problem is likely that you're trying to exec **at all** and not with the shared memory mechanism. Have you investigated things like `clone()` with non-standard arguments to allow you to spawn vm-isolated children that start from the parent's memory state? – Andy Ross Jun 03 '13 at 19:30
  • Alright. I got your point. Thanks ver much. I will take a look at it as well. – towi_parallelism Jun 03 '13 at 20:06