理解 DEVICE_ATTR
DEVICE_ATTR
是 Linux 內核中用于創建設備屬性的宏,通常用于 sysfs 文件系統。通過 sysfs,用戶空間的程序可以讀取或修改內核中的設備屬性。DEVICE_ATTR
宏定義在 <linux/device.h>
頭文件中,用于聲明和定義一個設備屬性。
基本語法
DEVICE_ATTR
宏的基本語法如下:
DEVICE_ATTR(_name, _mode, _show, _store);
_name
:屬性的名稱,會在/sys/
下生成對應的文件。_mode
:文件的訪問權限,例如0644
表示用戶可讀寫,組和其他用戶只讀。_show
:當用戶讀取該屬性時調用的函數。_store
:當用戶寫入該屬性時調用的函數。
使用示例
以下是一個簡單的示例,展示如何使用 DEVICE_ATTR
:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>static char my_value[100] = "default";static ssize_t show_my_value(struct device *dev, struct device_attribute *attr, char *buf)
{return sprintf(buf, "%s\n", my_value);
}static ssize_t store_my_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{strncpy(my_value, buf, sizeof(my_value) - 1);my_value[sizeof(my_value) - 1] = '\0';return count;
}static DEVICE_ATTR(my_value, 0644, show_my_value, store_my_value);static struct device *my_device;static int __init my_module_init(void)
{int ret;my_device = &(some_device); // 需要替換為實際的設備結構體ret = device_create_file(my_device, &dev_attr_my_value);if (ret) {printk(KERN_ERR "Failed to create device file\n");return ret;}return 0;
}static void __exit my_module_exit(void)
{device_remove_file(my_device, &dev_attr_my_value);
}module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");
關鍵點
show
和store
函數是必須的,分別用于讀取和寫入屬性。如果不需要寫入功能,可以將_mode
設置為只讀(如0444
),并將_store
設置為NULL
。DEVICE_ATTR
宏會生成一個名為dev_attr_my_value
的結構體變量,其中my_value
是屬性的名稱。- 使用
device_create_file
和device_remove_file
來創建和刪除屬性文件。
訪問屬性
在用戶空間,可以通過以下方式訪問該屬性:
# 讀取屬性
cat /sys/.../my_value# 寫入屬性
echo "new_value" > /sys/.../my_value
注意事項
- 確保設備的
struct device
結構體已經正確初始化并注冊到內核中。 - 在
store
函數中,必須對用戶傳入的數據進行驗證,防止緩沖區溢出或其他安全問題。 - 如果設備被卸載或移除,務必刪除所有創建的屬性文件,否則可能導致內核崩潰。
其他變體
除了 DEVICE_ATTR
,Linux 內核還提供了其他類似的宏,例如:
DEVICE_ATTR_RO
:只讀屬性,無需提供store
函數。DEVICE_ATTR_WO
:只寫屬性,無需提供show
函數。DEVICE_ATTR_RW
:讀寫屬性,需要提供show
和store
函數。
這些宏的使用方式與 DEVICE_ATTR
類似,但更加簡潔。