使用open()在C中读取.img文件

时间:2018-03-16 21:14:07

标签: c mmap fstat

我正在尝试映射.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 个答案:

答案 0 :(得分:3)

您的代码在开始时无效,请检查您的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 *’

您应该指定openfopen函数,它们是不同的东西。

int open(const char *pathname, int flags);

答案 1 :(得分:1)

从您的问题的状态不清楚您是否能够mmap工作。您添加的上一次修改:

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

如果您要回写已打开的文件,那么没问题,但如果没有,则应使用O_RDONLY打开以防止无意中修改原始文件。

虽然不是错误,但fp通常用作与fopen打开文件时与文件流操作关联的文件指针。在这里,您使用read/write的低级I / O,它使用文件描述符而不是流指针。在引用描述符时,一般白话使用fd作为文件描述符的简写。 (就个人而言,看到两者以互换的方式使用是很尴尬的 - 我怀疑其他人也是如此)

您对fstat的剩余使用,结果buf.st_size和您对mmap的通话不是问题。您的问题出在其他地方 - 这是您应该发布A Minimal, Complete, and Verifiable Example (MCVE)的主要原因之一。

也就是说,为了确保您以适当的方式合并了您的更改,我将为您提供mmap sa文件的简单示例,并将文件转储到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以便我们可以进一步提供帮助。