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