2009-12-08 48 views
1

我有一个磁盘映像,其中包含使用熔丝的标准映像。超级块包含以下内容,我有一个函数read_superblock(* BUF)返回下面的原始数据:将超级块读取到C结构中

Bytes 0-3: Magic Number (0xC0000112) 
     4-7: Block Size (1024) 
    8-11: Total file system size (in blocks) 
    12-15: FAT length (in blocks) 
    16-19: Root Directory (block number) 
    20-1023: NOT USED 

我很新的C和让我开始在这个项目上我很好奇,什么是简单的方法将其读入结构或某些变量,并使用printf将其打印到屏幕上进行调试。

我最初想做的事情就像下面的想法,我可以看到原始数据,但我认为情况并非如此。也没有结构,我试图把它看作是一个字符串,这似乎也是非常错误的。为我抓取数据。有没有办法让我指定结构并定义每个变量中的字节数?

char *buf; 
read_superblock(*buf); 
printf("%s", buf); 
+0

请注意,您还需要检查此假定的read_superblock()中的错误以及调用它的人...... – asveikau 2009-12-08 04:13:08

回答

4

是的,我认为你最好把它读入结构中。包含了有用的数据字段都为32位整数,所以你可以定义看起来像这样(使用标准的头文件stdint.h定义的类型)的结构:

typedef struct SuperBlock_Struct { 
    uint32_t magic_number; 
    uint32_t block_size; 
    uint32_t fs_size; 
    uint32_t fat_length; 
    uint32_t root_dir; 
} SuperBlock_t; 

,就可以把结构的char*调用read_superblock,像这样的时候:

SuperBlock_t sb; 
read_superblock((char*) &sb); 

我们打印出你的数据,你可以像下面这样的电话:

printf("%d %d %d %d\n", 
    sb.magic_number, 
    sb.block_size, 
    sb.fs_size, 
    sb.fat_length, 
    sb.root_dir); 

请注意,由于您正在读取整数数据(即您在读取数据时可能需要交换字节),因此在使用此类技术时,您需要了解您的平台的字节顺序。您应该能够快速确定使用第一个字段中的幻数。

请注意,通常最好传递一个像这样的结构而不需要铸造它;这使您可以利用编译器的类型检查并消除可能隐藏的潜在问题。但是,这需要将您的read_superblock的实现更改为直接将数据读取到结构中。这并不难,可以使用标准的C运行时函数来完成fread(假设你的数据在一个文件中,如在你的问题暗示),像这样:

​​
+0

谢谢,这非常有帮助。 – PKKid 2009-12-08 03:34:56

+0

你没有做任何事情来确保编译器不会插入用于对齐的填充。 – asveikau 2009-12-08 04:12:31

+0

我不能,因为我不知道原始海报使用的是什么编译器(结构打包相当于编译器特定的)。但你的观点是有效的;当使用我描述的第一种方法时(将结构转换为char *),通常必须打包结构以避免任何填充相关的问题。 – 2009-12-08 14:02:24

0

这并不难后打印数据您成功地将数据复制到Emerick提出的结构中。假设用于保存数据的结构实例名为SuperBlock_t_Instance。

然后你就可以打印出它的领域是这样的:

printf("Magic Number:\t%u\nBlock Size:\t%u\n etc", 
SuperBlock_t_Instance.magic_number, 
SuperBlock_t_Instance.block_size); 
1

两件事情在这里补充:

  1. 这是一个好主意,拉着原始数据转换成一个结构时,要设置结构来有零填充,即使它完全由32位无符号整数组成。在gcc中,你可以在结构定义之前使用#pragma pack(0)并在#pragma pack()之后使用。
  2. 为了解决潜在的字节顺序问题,需要查看的两个调用分别为ntohs()ntohl(),分别为16位和32位值。请注意,这些从网络字节顺序交换到主机字节顺序;如果它们是相同的(它们不在基于x86的平台上),它们什么都不做。您从主机到网络字节顺序使用htons()htonl()。但是,由于这些数据来自文件系统而不是网络,因此我不知道是否存在排序问题。通过比较你期望的值(例如块的大小)和你得到的值十六进制,你应该很容易找到答案。
+1

+1用于结构包装。然而,至于第2点......我会确认该结构实际​​上是使用网络字节顺序。根据格式的不同,可能是_big-endian_ CPU需要进行交换。 (这在磁盘上的结构中很常见,因为假设x86会更常见。) – asveikau 2009-12-08 04:11:17

+0

-1表示结构打包,-1表示使用非标准函数表示结尾。原始海报没有指定编译器,因此编译指示可能不可用。 ntohs()和ntohl()不是标准函数;由于没有指定编译器,因此再次无法获得具体信息。 – 2009-12-08 18:14:17