使用 open() 在 C 中读取 .img 文件
Reading .img file in C using 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){
. . .
但我还是回来了
您的代码一开始没有工作,请检查您的 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);
从你的问题状态来看,你是否曾经能够 mmap
工作还不清楚。您上次添加的编辑:
int fp = open(argv[1],O_RDWR);
如果您正在写回您打开的文件,这很好,但如果不是,您应该使用 O_RDONLY
打开以防止无意中修改您的原始文件。
虽然不是错误,但当使用 fopen
打开文件时,fp
通常用作与文件流操作关联的 文件指针 。在这里,您使用 low-level I/O 和 read/write
,它使用 文件描述符 而不是 流指针 .引用描述符时,一般白话使用 fd
作为 short-hand 用于 文件描述符 。 (就个人而言,看到两者以互换方式使用是很尴尬的——我怀疑其他人也是如此)
您对 fstat
的剩余使用、生成的 buf.st_size
和您对 mmap
的调用都不是问题。您的问题出在其他地方 - 这是您应该 post A Minimal, Complete, and Verifiable Example (MCVE).
的主要原因之一
就是说,为了确保您以正确的方式合并了您的更改,我将给您一个简单的示例,即 mmap
s 一个文件并将该文件简单地转储到 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()
中的文件,然后简单地将一个打开的 file-descriptor 传递给 diskinfo
作为参数)
示例Use/Output
$ ./bin/mmapdiskinfo dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.
检查一下,如果您有任何问题,请告诉我。如果您仍然无法让您的功能正常工作,那么 post 一个 MCVE 以便我们可以提供进一步的帮助。
我正在尝试映射 .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){
. . .
但我还是回来了
您的代码一开始没有工作,请检查您的 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);
从你的问题状态来看,你是否曾经能够 mmap
工作还不清楚。您上次添加的编辑:
int fp = open(argv[1],O_RDWR);
如果您正在写回您打开的文件,这很好,但如果不是,您应该使用 O_RDONLY
打开以防止无意中修改您的原始文件。
虽然不是错误,但当使用 fopen
打开文件时,fp
通常用作与文件流操作关联的 文件指针 。在这里,您使用 low-level I/O 和 read/write
,它使用 文件描述符 而不是 流指针 .引用描述符时,一般白话使用 fd
作为 short-hand 用于 文件描述符 。 (就个人而言,看到两者以互换方式使用是很尴尬的——我怀疑其他人也是如此)
您对 fstat
的剩余使用、生成的 buf.st_size
和您对 mmap
的调用都不是问题。您的问题出在其他地方 - 这是您应该 post A Minimal, Complete, and Verifiable Example (MCVE).
就是说,为了确保您以正确的方式合并了您的更改,我将给您一个简单的示例,即 mmap
s 一个文件并将该文件简单地转储到 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()
中的文件,然后简单地将一个打开的 file-descriptor 传递给 diskinfo
作为参数)
示例Use/Output
$ ./bin/mmapdiskinfo dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.
检查一下,如果您有任何问题,请告诉我。如果您仍然无法让您的功能正常工作,那么 post 一个 MCVE 以便我们可以提供进一步的帮助。