считывание памяти из файла I / OC / C ++ - PullRequest
0 голосов
/ 06 декабря 2018

Я новичок в области отображения памяти, и мне было интересно, есть ли способ прочитать текстовый файл, используя память, сопоставленную со строкой.Я действительно не знаю, как начать писать код.

1 Ответ

0 голосов
/ 06 декабря 2018

Общая идея ввода-вывода с отображением в память заключается в том, что вы сообщаете операционной системе (ОС) , какой файл вам нужен, и он (после выполнения некоторой работы по настройке) сообщает вам где этот файл сейчас находится в памяти.

Как только этот контракт будет выполнен, вы сможете копировать вещи в эту память и из нее любым удобным для вас способом (например, с memcpy),и он будет волшебным образом обрабатывать ввод-вывод для вас.

Подробно зависит от того, какую ОС вы используете, поскольку стандарт ISO C не определяет это поведение - поэтому он зависит от ОС.

Например, Windows использует парадигму сопоставления файлов, показанную здесь , в то время как Linux использует mmap, чтобы позволить подвергнуть файл, который вы уже открыли, отображению памяти (через его файлдескриптор).

В качестве примера, эта программа для Linux, несколько объемная из-за проверки ошибок и отчетов о ходе выполнения, отображает в памяти файл file.txt и выводит его содержимое:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

// Helper function to minimise error code in main.

static int clean(
    int retVal,     // value to return.
    char *err,      // error/NULL, allows optional %s for strerror(errno).
    int fd,         // fd/-1 to close.
    void *filMem,   // memory/NULL to unmap.
    off_t sz,       // size if unmapping.
    void *locMem    // memory/NULL to free.
) {
    if (err)     printf (err, strerror(errno));
    if (locMem)  free(locMem);
    if (filMem)  munmap(filMem, sz);
    if (fd >= 0) close(fd);
    return retVal;
}

int main(void) {
    int fd = open("file.txt", O_RDONLY);
    if (fd < 0) return clean(-1, "Can't open: %s\n", -1, NULL, 0, NULL);
    printf("File opened okay, fd = %d.\n", fd);

    off_t sz = lseek(fd, 0, SEEK_END);
    if (sz == (off_t) -1) return clean(-1, "Can't seek: %s\n", fd, NULL, 0, NULL);
    printf("File size is %ld.\n", sz);

    void *fileArea = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
    if (! fileArea) return clean(-1, "Can't map: %s\n", fd, NULL, 0, NULL);
    printf("File mapped to address %p.\n", fileArea);

    char *localArea = calloc(1, sz + 1);
    if (! localArea) return clean(-1, "Can't allocate\n", fd, fileArea, sz, NULL);
    memcpy(localArea, fileArea, sz);
    printf("Data copied to %p, result is [\n%s]\n", localArea, localArea);

    return clean(0, NULL, fd, fileArea, sz, localArea);
}

Запуск этого на моей локальной системествол, результаты можно увидеть из следующего стенограммы:

pax$ cat file.txt
...This is the input file content.

pax$ ./testprog
File opened okay, fd = 3.
File size is 35.
File mapped to address 0x7f868a93b000.
Data copied to 0x1756420, result is [
...This is the input file content.
]
...