从 mmap() 读取时 ntohl() 返回 0
ntohl() returning 0 when reading from mmap()
晚上好,我正在尝试从 .img 文件中读取一些二进制信息。我可以从 ntohs() 中检索 16 位数字 (uint16_t),但是当我尝试使用 ntohl() 从同一位置检索时,它却给了我 0。
这是我程序的关键部分。
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <cmath>
int fd;
struct blockInfo {
long blockSize = 0;
long blockCount = 0;
long fatStart = 0;
long fatBlocks = 0;
long rootStart = 0;
long rootBlocks = 0;
long freeBlocks = 0;
long resBlocks = 0;
long alloBlocks = 0;
};
int main(int argc, char *argv[]) {
fd = open(argv[1], O_RDWR);
// Get file size
struct stat buf{};
stat(path, &buf);
size_t size = buf.st_size;
// A struct to hold data retrieved from a big endian image.
blockInfo info;
auto mapPointer = (char*) mmap(nullptr, size,
(PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
info.blockSize = ntohs((uint16_t) mapPointer[12]);
long anotherBlockSize = ntohl((uint32_t) mapPointer[11]);
printf("%ld", info.blockSize); // == 512, correct
printf("%ld", anotherBlockSize); // == 0, what?
}
我明白 blockSize
和 anotherBlockSize
不应该相等,但是 anotherBlockSize
至少应该是非零的,对吗?
别的,我去ntohs(pointer[16])
访问数据,应该是return2,但也是returns 0,这是怎么回事?任何帮助将不胜感激。
auto mapPointer = (char*) ...
这将 mapPointer
声明为 char *
。
... ntohl((uint32_t) mapPointer[11]);
您的明显意图是使用 mapPointer
从该位置检索一个 32 位值,一个 four-byte 值。
不幸的是,因为 mapPointer
是一个普通的 garden-variety char *
,表达式 mapPointer[11]
的计算结果是一个单独的 char
值。一个字节。这就是代码从 mmap
ed 内存块中读取的内容,位于距块开头的第 11 个偏移处。 (uint32_t)
不会从引用的地址 mapPointer+11
读取 uint32_t
。 mapPointer[11]
从 mapPointer+11
读取单个 char
值,因为 mapPointer
是指向 char
的指针,将其转换为 uint32_t
,并提供到 ntohl()
.
不,anotherBlockSize
不一定是non-zero
info.blockSize = ntohs((uint16_t) mapPointer[12]);
此代码从相对于 mapPointer 的偏移量 12 读取一个字符,将其转换为 uint16_t 并对其应用 ntohs()。
long anotherBlockSize = ntohl((uint32_t) mapPointer[11]);
此代码从相对于 mapPointer 的偏移量 11 读取一个字符,将其转换为 uint32_t 并对其应用 ntohl()。
显然,您正在从映射内存中读取 non-overlapped 数据(不同的字符),因此您不应期望 blockSize
和 anotherBlockSize
连接。
如果你试图以不同的方式读取相同的内存(如uint32_t和uint16_t),你必须做一些指针转换:
info.blockSize = ntohs( *((uint16_t*)&mapPointer[12]));
请注意,此类代码通常依赖于平台。这种在 x86 上完美运行的转换可能在 ARM 上失败。
晚上好,我正在尝试从 .img 文件中读取一些二进制信息。我可以从 ntohs() 中检索 16 位数字 (uint16_t),但是当我尝试使用 ntohl() 从同一位置检索时,它却给了我 0。
这是我程序的关键部分。
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <cmath>
int fd;
struct blockInfo {
long blockSize = 0;
long blockCount = 0;
long fatStart = 0;
long fatBlocks = 0;
long rootStart = 0;
long rootBlocks = 0;
long freeBlocks = 0;
long resBlocks = 0;
long alloBlocks = 0;
};
int main(int argc, char *argv[]) {
fd = open(argv[1], O_RDWR);
// Get file size
struct stat buf{};
stat(path, &buf);
size_t size = buf.st_size;
// A struct to hold data retrieved from a big endian image.
blockInfo info;
auto mapPointer = (char*) mmap(nullptr, size,
(PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
info.blockSize = ntohs((uint16_t) mapPointer[12]);
long anotherBlockSize = ntohl((uint32_t) mapPointer[11]);
printf("%ld", info.blockSize); // == 512, correct
printf("%ld", anotherBlockSize); // == 0, what?
}
我明白 blockSize
和 anotherBlockSize
不应该相等,但是 anotherBlockSize
至少应该是非零的,对吗?
别的,我去ntohs(pointer[16])
访问数据,应该是return2,但也是returns 0,这是怎么回事?任何帮助将不胜感激。
auto mapPointer = (char*) ...
这将 mapPointer
声明为 char *
。
... ntohl((uint32_t) mapPointer[11]);
您的明显意图是使用 mapPointer
从该位置检索一个 32 位值,一个 four-byte 值。
不幸的是,因为 mapPointer
是一个普通的 garden-variety char *
,表达式 mapPointer[11]
的计算结果是一个单独的 char
值。一个字节。这就是代码从 mmap
ed 内存块中读取的内容,位于距块开头的第 11 个偏移处。 (uint32_t)
不会从引用的地址 mapPointer+11
读取 uint32_t
。 mapPointer[11]
从 mapPointer+11
读取单个 char
值,因为 mapPointer
是指向 char
的指针,将其转换为 uint32_t
,并提供到 ntohl()
.
不,anotherBlockSize
不一定是non-zero
info.blockSize = ntohs((uint16_t) mapPointer[12]);
此代码从相对于 mapPointer 的偏移量 12 读取一个字符,将其转换为 uint16_t 并对其应用 ntohs()。
long anotherBlockSize = ntohl((uint32_t) mapPointer[11]);
此代码从相对于 mapPointer 的偏移量 11 读取一个字符,将其转换为 uint32_t 并对其应用 ntohl()。
显然,您正在从映射内存中读取 non-overlapped 数据(不同的字符),因此您不应期望 blockSize
和 anotherBlockSize
连接。
如果你试图以不同的方式读取相同的内存(如uint32_t和uint16_t),你必须做一些指针转换:
info.blockSize = ntohs( *((uint16_t*)&mapPointer[12]));
请注意,此类代码通常依赖于平台。这种在 x86 上完美运行的转换可能在 ARM 上失败。