Чтение.img файла в C с использованием open()

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

Вот мой код, и когда я запускаю код, я продолжаю получать ошибку, что p равно MAP_FAILED

int diskinfo(int argc, char* argv[]){

void *p;
char *size

    if (argc < 2) {
            printf("Please put ./diskinfo <file> \n");
            exit(1);
    }

    int fp = open(argv[1],"rb+");
    if(fp == NULL) {
            printf("Error opening file");
            exit(1);
    }

    struct stat buf;
    fstat(fp, &buf);

    p = mmap(NULL,buf.st_size, PROT_READ, MAP_PRIVATE, fp, 0);

    if(p == MAP_FAILED){
            printf("Error mapping memory\n");
            exit(1);
    }}

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

Изменение на perror() не работает. Также изменение этой функции не меняет того факта, что p все еще равно MAP_FAILED

if(p == MAP_FAILED){
        return;
}

Я изменил ниже, что является решением:

int fp = open(argv[1],O_RDWR);
if(fp < 0){ 
    . . .

Но я все еще возвращаюсь

2 ответа

Решение

Из состояния вашего вопроса неясно, смогли ли вы когда-либо получить mmap работать. Ваше последнее изменение добавлено:

int fp = open(argv[1],O_RDWR);

Что хорошо, если вы пишете обратно в файл, который вы открыли, но если нет, вы должны открыть, используя O_RDONLY чтобы предотвратить непреднамеренное изменение вашего исходного файла.

Пока не ошибка, fp обычно используется как указатель файла, связанный с операциями файлового потока, когда файл открывается с fopen, Здесь вы используете низкоуровневый ввод-вывод с read/write который использует файловый дескриптор вместо указателя потока. При обращении к дескриптору общее общеупотребительное использование fd как сокращение для файлового дескриптора. (лично мне было неловко видеть, как они используются взаимозаменяемо - я подозреваю, что это относится и к другим)

Ваше оставшееся использование fstat, результирующий buf.st_size и ваш звонок mmap не проблема. Ваша проблема лежит в другом месте - это одна из основных причин, по которой вы должны опубликовать Минимальный, Полный и Проверяемый пример (MCVE).

Тем не менее, чтобы убедиться, что вы правильно включили свои изменения, я оставлю вам простой пример, который mmapSA файл и просто сбрасывает файл в stdout (поэтому ограничьте ваши имена входных файлов достаточно коротким текстовым файлом для работы с примером - в противном случае вы увидите все виды странных символов). Проработайте следующее:

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

int diskinfo (int argc, char *argv[]) {

    char *p = NULL;         /* pointer to mmapped file */
    int fd = 0;             /* file descriptor */
    struct stat buf = {0};  /* struct stat */
    ssize_t size = 0;       /* file size (typed for write return) */

    if (argc < 2) { /* validate at least 2 arguments */
        printf ("Please put %s <file> \n", argv[0]);
        exit (EXIT_FAILURE);
    }

    if ((fd = open (argv[1], O_RDONLY)) == -1) { /* open/validate file */
        perror ("Error opening file");
        exit (EXIT_FAILURE);
    }

    if (fstat (fd, &buf) == -1) {       /* stat file for size */
        perror ("error: fstat buf");
        exit (EXIT_FAILURE);
    }
    size = buf.st_size;                 /* get file size */

    /* mmap file and validate return */
    if ((p = mmap (NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) 
                    == (void *) -1) {
        perror ("mmap failed");
        exit (EXIT_FAILURE);
    }

    /* simple example, output mmapped file to stdout */
    if (write (STDOUT_FILENO, p, size) != size) {
        perror ("error on write");
        exit (EXIT_FAILURE);
    }

    munmap (p, size);   /* unmap file */

    return 1;   /* return success (fn could be void due to exit) */
}

int main (int argc, char **argv) {

    diskinfo (argc, argv);  /* call diskinfo function */

    return 0;
}

(примечание: ваш чек if (argc < 2) действительно должно быть сделано в вызывающей функции, main() Вот. Нет причин звонить diskinfo пока вы не подтвердите, у вас есть имя файла, чтобы открыть. Вы могли бы на самом деле рефакторинг вашего кода, чтобы проверить аргументы и open файл в main() и просто передать открытый файл-дескриптор diskinfo как параметр)

Пример использования / Вывод

$ ./bin/mmapdiskinfo dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

Посмотрите вещи и дайте мне знать, если у вас есть какие-либо вопросы. Если вы все еще не можете заставить свою функцию работать, то опубликуйте MCVE, чтобы мы могли помочь вам в дальнейшем.

Ваш код не работает в начале, проверьте ваш open вызов.

Если вы компилируете с правильными флагами, такими как -Wall -Werror Вы должны получить предупреждения, подобные этому:

error: passing argument 2 of ‘open’ makes integer from pointer without a cast [-Werror]
note: expected ‘int’ but argument is of type ‘char *’

Вы должны назначить open а также fopen функции, это разные вещи.

int open(const char *pathname, int flags);
Другие вопросы по тегам