Linux中不同可执行文件之间的共享变量

时间:2013-06-03 03:37:13

标签: linux process fork mmap execv

我想要做的是创建一个由不同进程访问的全局共享变量。我希望子进程被现有的可执行文件替换。

更新:我认为这是解决方案。代码来自here。但由于每个进程至少需要一个I / O操作来映射文件,有没有更快的方法?

mycode.h

static void* addr; //static

app1.cc

包括

#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;
}

感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

execve将删除内核中的所有映射,因此这种技术不起作用。你可以做的是打开一个文件(如Vaughn的建议)并将描述符传递给子进程。一个exec中的打开文件描述符没有变化。然后你可以在孩子中映射它。或者,调查像shm_open()/ shm_unlink()这样的API,它将管理全局文件映射,以便其他进程可以使用它,而不仅仅是孩子。

但基本上:你必须在孩子中使用mmap(),你不能将地址空间中的任何东西传递给Unix中的孩子。