I want to be able to map memory to a file descriptor so I can use some existing functions that need a file descriptor. Here's essentially what I'm looking for:
void do_operation1(int fd);
char data[DATA_MAX] = { /* embedded binary data */ };
int fd = addr_to_fd(data, DATA_MAX);
do_operation1(fd);
/* ... operate on fd ... */
What system call, or calls, can I use to accomplish this?
Some implementations have fmemopen()
. (Then of course you have to call fileno()
).
If yours doesn't, you can build it yourself with fork()
and pipe()
.
You should Check out shm_open()
.
Sure, just open(argv[0], ...)
, scan through the file to find where your binary data starts, lseek()
there and done. That file won't have the length of your binary data of course.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With