struct kobject 是裝置模型的原子單位,**不單獨使用**,嵌入於 struct device、struct cdev、struct device_driver 等容器中,提供:
kref) 生命週期管理。parent) 構建樹狀拓撲。kset) 實現分組管理。ktype) 定義行為 (釋放、sysfs 屬性)。sysfs_dirent) 對應 /sys 目錄。struct kobject {
const char *name; // 物件名稱 (sysfs 目錄名)
struct list_head entry; // 掛入 kset->list
struct kobject *parent; // 父物件
struct kset *kset; // 所屬集合
struct kobj_type *ktype; // 類型描述
struct sysfs_dirent *sd; // sysfs 目錄項
struct kref kref; // 參考計數
unsigned int state_initialized:1; // 已初始化
unsigned int state_in_sysfs:1; // 已在 sysfs 中
unsigned int state_add_uevent_sent:1;// add 事件已發送
unsigned int state_remove_uevent_sent:1; // remove 事件已發送
unsigned int uevent_suppress:1; // 抑制 uevent
};
| 函數 | 用途 |
|---|---|
kobject_init(kobj, ktype) | 初始化 kref、list、state、ktype |
kobject_set_name(kobj, fmt, ...) | 設定名稱 |
kobject_add(kobj, parent, fmt, ...) | 設定 parent/name,掛入 kset、建立 sysfs 目錄、發送 add uevent |
kobject_init_and_add(kobj, ktype, parent, fmt, ...) | 上述三步合一 |
kobject_get(kobj) | 引用計數 +1 |
kobject_put(kobj) | 引用計數 -1,歸零調用 ktype->release() |
kobject_del(kobj) | 從層次移除、sysfs 目錄刪除、發送 remove uevent |
kobject_unregister(kobj) | del + put |
struct kobj_type {
void (*release)(struct kobject *kobj); // 釋放回調 (kref 歸零時)
const struct sysfs_ops *sysfs_ops; // 屬性讀寫操作表
const struct attribute **default_attrs; // 預設屬性陣列 (NULL 結尾)
};
struct sysfs_ops {
ssize_t (*show)(struct kobject *kobj, struct attribute *attr, char *buf); // 讀屬性
ssize_t (*store)(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count); // 寫屬性
};
struct attribute {
const char *name; // 屬性檔名稱
struct module *owner; // 擁有模組
mode_t mode; // 權限 (S_IRUGO 等)
};
常用巨集: __ATTR_RO(name)、__ATTR_WO(name)、__ATTR_RW(name)、__ATTR(name, mode, show, store)。
kobject 的容器 (如「所有 USB 裝置」)。/sys 中的父目錄位置。uevent_ops)。struct kset {
struct subsystem *subsys; // 所屬子系統 (舊架構)
struct kobj_type *ktype; // 成員共享類型
struct list_head list; // 成員 kobject 雙向鏈表
struct kobject kobj; // 內嵌 kobject (代表集合自身)
struct kset_uevent_ops *uevent_ops; // 熱插拔事件回調
};
kset_init(kset) → 初始化內嵌 kobj、list
kset_register(kset) → kobject_register(&kset->kobj)
kset_unregister(kset) → kobject_unregister(&kset->kobj)
kset_get/put(kset) → 作用於內嵌 kobj
kset_find_obj(kset, name) → 在列表中按名稱查找 kobject
struct subsystem {
struct kset kset;
struct rw_semaphore rwsem; // 保護 list 的讀寫鎖
};
現代核心 **直接使用 kset**,subsystem 已被廢棄僅為相容保留。bus_type、class 等直接內嵌 kset。
mount -t sysfs sysfs /sys
# 根目錄七大標準子目錄
/sys/
├── block/ ← 區塊裝置 (sda, loop0...)
├── bus/ ← 總線視圖 (usb, pci, i2c, platform...)
├── class/ ← 功能類別視圖 (net, tty, block, input...)
├── devices/ ← 裝置拓撲樹 (完整親子關係)
├── firmware/ ← ACPI, EDD, EFI 等韌體介面
├── module/ ← 載入核心模組
└── power/ ← 系統級電源管理
kobject_add() 時決定位置:
parent → /sys/parent_path/namekset → /sys/kset_path/name/sys/name (掛在 kernel_kobj 下)default_attrs 陣列中每個 attribute 在目錄下建立同名檔案。sysfs_ops->show/store()。kobject_del() → 遞歸刪除目錄與屬性檔,發送 remove uevent。方式 A:靜態 default_attrs (在 ktype 中定義)
static struct attribute *my_attrs[] = {
&dev_attr_foo.attr,
&dev_attr_bar.attr,
NULL
};
static struct kobj_type my_ktype = {
.default_attrs = my_attrs,
.sysfs_ops = &my_sysfs_ops,
.release = my_release,
};
方式 B:動態群組 sysfs_create_group (運行時靈活增減)
static struct attribute *runtime_attrs[] = { &attr_baz.attr, NULL };
static struct attribute_group runtime_group = { .attrs = runtime_attrs };
// 在 kobject 已加入 sysfs 後
sysfs_create_group(kobj, &runtime_group); // 新增
sysfs_remove_group(kobj, &runtime_group); // 移除
// 1. 定義屬性
static ssize_t foo_show(struct kobject *k, struct attribute *a, char *buf) {
return sprintf(buf, "foo value\n");
}
static ssize_t foo_store(struct kobject *k, struct attribute *a, const char *buf, size_t n) {
// 解析 buf 更新內部狀態
return n;
}
static struct attribute foo_attr = __ATTR_RW(foo);
// 2. 定義 ktype
static struct attribute *attrs[] = { &foo_attr, NULL };
static struct kobj_type my_ktype = {
.default_attrs = attrs,
.sysfs_ops = &kobj_sysfs_ops, // 通用 ops
.release = my_release,
};
// 3. 模組初始化
static struct kobject *my_kobj;
int __init my_init(void) {
my_kobj = kobject_create_and_add("my_dev", kernel_kobj); // /sys/kernel/my_dev
if (!my_kobj) return -ENOMEM;
return 0;
}
void __exit my_exit(void) {
kobject_put(my_kobj); // 觸發 release → kfree 容器
}
容器結構 (device, cdev, driver...)
│
├── embedded kobject
│ ├── name, kref, parent, kset, ktype, sd
│ │
│ ├── kref → 生命週期 (get/put → release)
│ ├── parent → 樹狀父節點
│ ├── kset → 所屬集合 (列表成員)
│ ├── ktype → 行為定義 (release, sysfs_ops, default_attrs)
│ └── sd → sysfs 目錄項
│
└── sysfs 映射
/sys/.../parent/name/ ← 目錄
├── attr1 (show/store)
├── attr2
└── uevent (add/remove/change)
kobject、kset、ktype、sysfs 四位一體,構建了 Linux 核心「物件導向」的裝置管理基礎設施。掌握其結構體欄位、API 流程、映射規則,能讓你在驅動開發中:正確註冊裝置、暴露可配置屬性、處理熱插拔事件、診斷 /sys 異常,打下堅實內功。
SecureCRT 使用 rz/sz 實現 Linux 與 Windows 文件高速傳輸
Linux 桌面環境大比較:Plasma、GNOME、Unity、Cinnamon、MATE、Xfce、LXQt、Budgie、Pantheon 怎麼選?
CentOS 上搭建 LNMP 生產環境完整指南(Nginx 前端 + Apache 後端)
Linux 設備驅動開發:競態條件、阻塞 I/O 與可重入代碼實戰
解決 Linux 下 SQLPlus 操作困擾:使用 rlwrap 實現命令歷史與編輯功能