You cannot map "some existing memory buffer" to a file descriptor. As said in a comment above, the fmemopen()
function associates a memory buffer with a "FILE *" stream pointer which can be manipulated with the libc-provided streams functions. No file descriptor is allocated: the "FILE *" stream is a high-level abstraction and is NOT compatible with a file descriptor which is a low-level handle.
Instead, you may want to allocate a new shared memory buffer and map it to a file descriptor. This is widely used and known as a "memory-mapped file" in the Linux jargon.
You can use a file descriptor obtained with open()
that refers to a file or a file descriptor obtained with shm_open()
that refers to a shared memory object. Any file descriptor handle will do the job. You can then invoke mmap()
to map the file descriptor to a shared memory buffer.
Note: mmap()
will fail if the file descriptor refers to a non-regular file such as a pipe, a socket or a character device file (e.g., /dev/ttys001
). Due to this, you cannot usually create a memory-mapped file for the STDIN, STDOUT or STDERR file descriptors.
You can manipulate the memory buffer in an array-like fashion and modifications to the memory-mapped file are committed to disk. The opposite is also true, with any modifications made to the file (e.g., with a write()
syscall) committed to memory as well.
The following snippet opens a file of your choice and maps it into memory. It will print the first 256 characters and replace them with "*" in the original file. Compile it with cc mmap_test.c -o mmap_test
on a POSIX-compliant system.
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
int main(int ac, char *av[])
{
int pagesize, fd;
unsigned char *data;
if ( ac < 2 ) {
printf("Usage: %s <filepath>\n", av[0]);
return 1;
}
pagesize = getpagesize();
if ( (fd = open(av[1], O_RDWR)) == -1 ) {
perror("Error: cannot open file for reading");
return 1;
}
if ( (data = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED ) {
perror("Error: cannot create memory-mapped file");
return 1;
}
write(1, data, 256);
memset(data, '*', 256);
return 0;
}
fileno()
fails on both Linux/FreeBSD (and I presume others) when theFILE*
comes fromfmemopen
or something equivalent. Without a way to get the file descriptor, I'm not sure we have a solution. – Succentor