我希望能够将内存映射到文件描述符,这样我就可以使用一些需要文件描述符的现有函数。这基本上是我正在寻找的东西:
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 ... */
我可以使用什么系统调用或调用来完成此操作?
我希望能够将内存映射到文件描述符,这样我就可以使用一些需要文件描述符的现有函数。这基本上是我正在寻找的东西:
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 ... */
我可以使用什么系统调用或调用来完成此操作?
一些实现具有fmemopen()
. (那么当然你必须打电话fileno()
)。
如果您没有,您可以使用fork()
and自己构建它pipe()
。
你应该检查出来shm_open()
。
当然,只需open(argv[0], ...)
扫描文件以查找二进制数据的开始位置、lseek()
完成位置。该文件当然不会有您的二进制数据的长度。
您不能将“一些现有的内存缓冲区”映射到文件描述符。正如上面评论中所说,该fmemopen()
函数将内存缓冲区与“FILE *”流指针相关联,该指针可以使用 libc 提供的流函数进行操作。未分配文件描述符:“FILE *”流是高级抽象,与作为低级句柄的文件描述符不兼容。
相反,您可能希望分配一个新的共享内存缓冲区并将其映射到文件描述符。这被广泛使用,在 Linux 术语中被称为“内存映射文件”。
您可以使用通过open()
引用文件获得的文件描述符或通过shm_open()
引用共享内存对象获得的文件描述符。任何文件描述符句柄都可以完成这项工作。然后,您可以调用mmap()
以将文件描述符映射到共享内存缓冲区。
注意:
mmap()
如果文件描述符引用非常规文件,例如管道、套接字或字符设备文件(例如,/dev/ttys001
),则会失败。因此,您通常无法为 STDIN、STDOUT 或 STDERR 文件描述符创建内存映射文件。
您可以以类似数组的方式操作内存缓冲区,并将对内存映射文件的修改提交到磁盘。反之亦然,对文件所做的任何修改(例如,使用write()
系统调用)也会提交到内存。
以下代码段打开您选择的文件并将其映射到内存中。它将打印前 256 个字符并将它们替换为原始文件中的“*”。cc mmap_test.c -o mmap_test
在符合 POSIX 的系统上编译它。
#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;
}