我可以在 Linux 进程和分支子进程之间创建共享数据部分吗?

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

我知道这可能是一个奇怪的要求,但它是: 我必须在我的 x86-64 Linux ELF 可执行文件中创建一个读写 section/segment,以便该部分可以在进程及其子进程之间共享。我会处理缓冲区中的任何数据同步需求,所以请不要担心这个问题。

我知道 mmap 可以将 'shared' 页面映射到我的进程中,但由于某些原因,我不能使用 mmap 或类似的功能。我能做的是使用一个大 char 数组。到目前为止,我不知道这是否是不可能完成的任务。

这是我的测试代码

#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

执行后,查看.buffer段,只发现是private,不知道是否以及如何制作共享?

$ ./bssmap 
pid=557836

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

在另一个终端

$ 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'

顺便说一句,我知道 GCC 手册中有一个 'shared' 属性,但它是针对 Windows 的,在 Linux.[=18 中编译时将被忽略并发出警告=]

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

是,使用mmap。其他可能的答案:POSIX 共享内存(shm_open and friends) and SysV IPC (shmat 和朋友)。

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.

不会 工作。你只能在你 fork() 的时候分享“大字符数组”。一旦你有两个独立的进程,就不可能通过这个数组进行进一步的通信。

您可以尝试通过/proc/<pid>/mem阅读,例如:

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