2009-12-08 49 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