Home > Mobile >  Can I create a shared data section in among a Linux process and forked sub-processes?
Can I create a shared data section in among a Linux process and forked sub-processes?

Time:04-24

I know this might be a strange requirement, but here it is: I have to create a read-write section/segment in my x86-64 Linux ELF executable, so that this section can be shared among process and its sub-processes. I will handle any data synchronization requirement in the buffer, so pls do not worry about this trouble.

I know mmap can map 'shared' pages into my process, but for some reason, I cannot use mmap or similar functions. What I can do is to use a big char array. So far, I don't know if this is a mission impossible.

Here is my test code

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

// reserve 20M bytes as JIT buffer
#define BUF_SIZE 20*1024*1024
char jit_buffer[BUF_SIZE] __attribute__((section(".buffer"), aligned(4096)));

int main()
{
    printf("pid=%d\n\n", getpid());
    printf(".main Start Address: %p\n", &main);
    printf(".buffer Start Address: %p\n", jit_buffer);

    getchar();
    return 0;
}
gcc -o bssmap bssmap.c

after execution, I can check the .buffer section but only found that it is private, and I don't know whether and how to make it shared?

$ ./bssmap 
pid=557836

.text Start Address: 0x564e9637f189
.buffer Start Address: 0x564e96383000

in another terminal

$ cat /proc/557836/maps
564e9637e000-564e9637f000 r--p 00000000 08:02 7213494  bssmap
564e9637f000-564e96380000 r-xp 00001000 08:02 7213494  bssmap
564e96380000-564e96381000 r--p 00002000 08:02 7213494  bssmap
564e96381000-564e96382000 r--p 00002000 08:02 7213494  bssmap
564e96382000-564e97783000 rw-p 00003000 08:02 7213494  bssmap <-- 'private' but want 'shared'

btw, I know there is a 'shared' attribute in GCC manual, but it is for Windows and will be ignored with a warning while compiling in Linux.

CodePudding user response:

I know mmap can map 'shared' pages into my process

Yes, do use mmap. Other possible answers: POSIX shared memory (shm_open and friends) and SysV IPC (shmat and friends).

but for some reason, I cannot use mmap or similar functions.

You better figure out what "some reason" is, because you've just disallowed solutions which can work.

What I can do is to use a big char array. So far, I don't know if this is a mission impossible.

That will not work. You can only share the "big char array" at the moment you fork(). Once you have two separate processes, not further communication through this array will be possible.

CodePudding user response:

You can try to read via /proc/<pid>/mem, e.g:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>

// reserve 20M bytes as JIT buffer
#define BUF_SIZE 20*1024*1024
char jit_buffer[BUF_SIZE] __attribute__((section(".buffer"), aligned(4096)));

void read_mem(char *desc, int pid, off_t address)
{
    int fd;
    char memfile[32];
    int val = 0;

    snprintf(memfile, sizeof(memfile), "/proc/%d/mem", pid);
    fd = open(memfile, O_RDONLY);
    if (fd >= 0) {
        if (pread(fd, &val, sizeof(val), address) == sizeof(val)) {
            printf("%s value=%d\n", desc, val);
        }
        close(fd);
    }
}

int main()
{
    pid_t fid = getpid();
    pid_t pid = fork();
    if (pid < 0) {
        printf("fork() failed!\n");
        return 1;
    } else if (pid > 0) {
        *(int *)jit_buffer = 1;
        usleep(100000);
        read_mem("read child buffer:", pid, (long)jit_buffer);
        wait(NULL);
    } else {
        *(int *)jit_buffer = 2;
        usleep(200000);
        read_mem("read parent buffer:", fid, (long)jit_buffer);
    }
    return 0;
}
  • Related