2010年1月4日 星期一

__attribute__((packed))

通常在PC上寫程式時,很少會去管struct會佔掉多少記憶體。
當要使用到時,也不會想去用手算到底佔掉多少,大多是直接使用sizeof來做計算。
然而sizeof計算出來的值往往不會如我們想的一樣。因為compiler為了效能考量,會自動地為我們
做最佳化,也就是資料對齊。為了這個目的,compiler會為struct多準備一些記憶體。
我們可以看以下的code:
struct ABC {
int index;
char name[6];
int score;
};

struct DEF{
int att;
char name[3];
};

int main(void)
{
printf("sizeof(ABC) = %d\n", sizeof(struct ABC));
printf("sizeof(DEF) = %d\n", sizeof(struct DEF));
return 0;

}
說明:
1. 若我們直接去計算struct ABC和strcut DEF時,
struct ABC = 4 + 6 + 4 = 14 (struct ABC用掉14個byte)
strcut DEF = 4 + 3 = 7 (struct DEF用掉7個byte)
2. 但真的是這樣嗎?程式執行出來的結果卻是,
sizeof(ABC) = 16
sizeof(DEF) = 8
3. 這就是compiler為我們做了對齊的最佳化,將這二個的struct都調整成2的次方。
這樣有利於運算。

這樣的做法在PC上通常沒有問題,但若是在嵌入式系統上,記憶體必需要錙珠必較時
,我們就必須要考量到使用struct所佔掉的記憶體空間,上次和Tick討論Linux kernel
裡的List結構時,遇到了這個問題。他告訴我可以使用__attribute__((packed));這個關鍵字,
它的作用在於叫compiler不要為我們做對齊的最佳化,因此,計算的結果就會如同我們所想的一樣了。
struct ABC {
int index;
char name[6];
int score;
} __attribute__((packed));;

struct DEF{
int att;
char name[3];
} __attribute__((packed));;

int main(void)
{
printf("sizeof(ABC) = %d\n", sizeof(struct ABC));
printf("sizeof(DEF) = %d\n", sizeof(struct DEF));
return 0;

}
這樣就會得到以下的結果了。
sizeof(ABC) = 14
sizeof(DEF) = 7

這裡沒有哪一種用法比較好的問題,端看在使用上的需求,
要運算速度快,就需要資料對齊。要節省記憶體的使用,就取消對齊。 


轉錄於http://zylix666.blogspot.com/2007/10/cstruct.html

坦克版 pci 資訊

BB:DD:FF  VID :DID   DevClass  IRQ  Device Type

01:0D:00  8086:2E70  0C:03:20  04   USB Controller (EHCI)
01:0D:01  8086:2E70  0C:03:20  04   USB Controller (EHCI)

pci read

pciread32(uint bus, uint device, uint function, uint reg)


DESCRIPTION These functions provide access to PCI configuration space. All of the functions take
parameters for the bus, device, function, and register to be accessed. The pciwrite functions
also take a parameter val, which is the value to be written to the specified register. For the
pcimod functions, mask identifies which bits in the specified register are to be modified (i.e.
which bits in val are significant).
Although physical PCI configuration space accesses must be 32-bits wide, these functions
allow safe accesses of smaller widths as well as accesses that cross register boundaries. For
example,



pciread32(0, 0, 0, 2)






would return a 32-bit value constructed from bytes 2 and 3 of the register at offset 0 and
bytes 0 and 1 of the register at offset 4







returns : 

 The pciread functions return the value read from the specified register.