Linux 核心以 C 語言編寫,大量使用 struct 模擬物件導向封裝。結構體不僅組織資料,更透過函數指標封裝操作,實現多態與繼承。本文深入解析結構體在核心中的角色、字節對齊優化、以及易誤的運算子優先級陷阱。
// 核心典型結構體:檔案操作介面(多態)
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
// ... 更多函數指標
};
// 繼承模擬:嵌入基礎結構體
struct cdev {
struct kobject kobj; // 基礎物件
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
核心透過:
container_of 宏實現向上轉型file_operations 實現動態分派struct { int n; char data[]; } 變長結構
#pragma pack(1) // 1 字節對齊(緊湊)
struct A { char c; int i; }; // sizeof=5
#pragma pack(4) // 4 字節對齊
struct B { char c; int i; }; // sizeof=8 (c+3填充+i)
#pragma pack() // 預設(通常 8/16)
struct C { double d; char c; int i; }; // sizeof=24 (d:8, c+7填充, i:4, 尾部填充4)
unsigned int flag:1; unsigned int mode:3; 極致壓縮__attribute__((packed)):GCC 強制無填充(可能導致非對齊存取效能損失或 SIGBUS)offsetof:編譯期計算偏移,配合 container_of 安全轉型最高優先級運算子:. -> () [](左結合)
struct { int len; char *str; } *p;
// 表達式 → 實際結合 → 結果
++p->len → ++(p->len) // len +1
(++p)->len → (++p)->len // p+1 後取 len
(p++)->len → (p++)->len // 取 len 後 p+1
*p->str → *(p->str) // 取 str 指向的字元
*p->str++ → *(p->str++) // 取字元後 str+1
(*p->str)++ → (*(p->str))++ // 字元值 +1
*p++->str → *(p++->str) // 取字元後 p+1
-> 優先於單目運算子(++、*)++ 結合緊密於前置 ++ 但語義不同__aligned() 顯式指定對齊(如 DMA 緩衝區需 64/128 位元組對齊)BUILD_BUG_ON(sizeof(struct) != EXPECTED) 編譯期斷言大小const,放入 .rodata 區精通結構體佈局、對齊與運算子語義,是寫出高效、正確、可維護核心代碼的基本功。這也是 C 語言「簡單但不簡單」的體現。