C 读取二进制文件到缓冲区
C Read binary file to a buffer
我正在尝试创建一个简单的 VM,它可以读取二进制文件,遵循二进制文件中的指令(每条指令 4 个字 - 32 位),然后在遵循所有指令后输出结果。
我目前正处于项目的第一阶段,我正在尝试使用 fread/fopen 将我的文件内容读入缓冲区。在大多数情况下,代码类似于 fread for cplusplus.com 上给出的示例,但是我想找到一种方法将我的文件一次分成 4 个单词。我以前从未在如此低的水平上工作过,并且在确定我是否正确执行此操作时遇到问题,并希望这里有人可以帮助我确保我将文件正确分解为 4 个单词。
FILE * pFile;
long lSize;
unsigned char * buffer;
size_t result;
pFile = fopen ( "test.bin" , "rb" );
if (pFile==NULL) {fprint("error, file null")}
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
buffer = (unsigned char*) malloc (sizeof(unsigned char)*lSize);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
// copy the file into the buffer:
result = fread (buffer, 4,lSize,pFile); //The error is here, if I use 1 instead of 4 there is no error output but I am not sure this would properly break the file into 4 words read at a time.
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
printf("%ld\n",lSize);
现在,当我 运行 出现此错误时,除非我将我评论的行中的数字更改回 1。
将二进制文件表示为缓冲区是您的 OS 可以为您做的事情; mmap 的手册页在 C89 中有一个工作示例(所以它是古董):
fd = open(argv[1], O_RDONLY);
...
if (fstat(fd, &sb) == -1) /* To obtain file size */
handle_error("fstat");
offset = atoi(argv[2]);
pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
/* offset for mmap() must be page aligned */
...
if (argc == 4) {
length = atoi(argv[3]);
if (offset + length > sb.st_size)
length = sb.st_size - offset;
/* Can't display bytes past end of file */
} else { /* No length arg ==> display to end of file */
length = sb.st_size - offset;
}
addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
MAP_PRIVATE, fd, pa_offset);
if (addr == MAP_FAILED)
handle_error("mmap");
现在,addr
指向包含进程地址 space 中输入文件的内存区域。
这将节省您在开始处理之前阅读整个文件的时间,因为您的 OS 可以自动只读取您实际访问的文件部分,而无需进一步的麻烦。
此外,由于您正在编写 VM(无论这对您意味着什么!),您应该了解典型的进程内存结构,因此学习 mmap
的作用是一个很好的练习。
我正在尝试创建一个简单的 VM,它可以读取二进制文件,遵循二进制文件中的指令(每条指令 4 个字 - 32 位),然后在遵循所有指令后输出结果。
我目前正处于项目的第一阶段,我正在尝试使用 fread/fopen 将我的文件内容读入缓冲区。在大多数情况下,代码类似于 fread for cplusplus.com 上给出的示例,但是我想找到一种方法将我的文件一次分成 4 个单词。我以前从未在如此低的水平上工作过,并且在确定我是否正确执行此操作时遇到问题,并希望这里有人可以帮助我确保我将文件正确分解为 4 个单词。
FILE * pFile;
long lSize;
unsigned char * buffer;
size_t result;
pFile = fopen ( "test.bin" , "rb" );
if (pFile==NULL) {fprint("error, file null")}
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
buffer = (unsigned char*) malloc (sizeof(unsigned char)*lSize);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
// copy the file into the buffer:
result = fread (buffer, 4,lSize,pFile); //The error is here, if I use 1 instead of 4 there is no error output but I am not sure this would properly break the file into 4 words read at a time.
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
printf("%ld\n",lSize);
现在,当我 运行 出现此错误时,除非我将我评论的行中的数字更改回 1。
将二进制文件表示为缓冲区是您的 OS 可以为您做的事情; mmap 的手册页在 C89 中有一个工作示例(所以它是古董):
fd = open(argv[1], O_RDONLY);
...
if (fstat(fd, &sb) == -1) /* To obtain file size */
handle_error("fstat");
offset = atoi(argv[2]);
pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
/* offset for mmap() must be page aligned */
...
if (argc == 4) {
length = atoi(argv[3]);
if (offset + length > sb.st_size)
length = sb.st_size - offset;
/* Can't display bytes past end of file */
} else { /* No length arg ==> display to end of file */
length = sb.st_size - offset;
}
addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
MAP_PRIVATE, fd, pa_offset);
if (addr == MAP_FAILED)
handle_error("mmap");
现在,addr
指向包含进程地址 space 中输入文件的内存区域。
这将节省您在开始处理之前阅读整个文件的时间,因为您的 OS 可以自动只读取您实际访问的文件部分,而无需进一步的麻烦。
此外,由于您正在编写 VM(无论这对您意味着什么!),您应该了解典型的进程内存结构,因此学习 mmap
的作用是一个很好的练习。