2013-06-03 2 views
0

Что я хочу сделать, так это создать глобальную общую переменную, к которой будут обращаться различные процессы. Я хочу, чтобы дочерний процесс был заменен существующим исполняемым файлом.Общая переменная между различными исполняемыми файлами в Linux

UPDATE: Я думаю, что это решение. Код заимствован от here. Но поскольку для каждого процесса требуется хотя бы одна операция ввода-вывода для mmap-файла, существует ли более быстрый подход?

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

Вместо создания анонимного mmap вы можете использовать реальный файл. –

+0

@VaughnCato: спасибо. но можно ли было бы сделать что-то вроде этого? struct Costume_Struct * my_struct; ', а затем в процессах' addr = mmap (NULL, length, prot, flags, fd, offset); Costume_Struct * proc_struct = (Costume_Struct *) addr' –

ответ

2

execve потеряет все отображения в ядре, поэтому эта техника не будет работать. Вместо этого вы можете открыть файл (как в предложении Vaughn) и передать дескриптор дочернему процессу. Открытые дескрипторы файлов не изменяются в exec. Затем вы можете отобразить его в дочернем элементе. Кроме того, изучите API, такие как shm_open()/shm_unlink(), которые будут управлять глобальным сопоставлением файлов, чтобы другие процессы могли использовать его, а не только дочерний.

Но в основном: у вас есть mmap() в дочернем, вы не можете передать что-либо в своем адресном пространстве ребенку в Unix.

+0

Спасибо. Но что, если я хочу поделиться структурой? Должен ли я реализовать его как текст в общем файле? или это возможно: 'struct Costume_Struct * my_struct;', а затем в процессах 'addr = mmap (NULL, length, prot, flags, fd, offset); Costume_Struct * proc_struct = (Costume_Struct *) addr'? –

+0

См. «ОБНОВЛЕНИЕ» –

+2

Да, вы можете поместить в общую память структуры (но не объекты C++, по крайней мере без особого внимания, чтобы убедиться, что они «POD»). Он будет работать точно так, как вы думаете. это просто m emory. –