Чтение.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).
Тем не менее, чтобы убедиться, что вы правильно включили свои изменения, я оставлю вам простой пример, который 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, чтобы мы могли помочь вам в дальнейшем.
Ваш код не работает в начале, проверьте ваш 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);