Question

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top