應用程序和驅動的簡易交互方式的實現
一般應用程序要操作設備, 都需要相應的設備驅動程序配合纔行, 因爲在應用層一般都把設備當成一個文件來操作, 所以,如果要給設備發送特殊的命令,一般要用ioctl函數纔行,這也就要求驅動必須實現ioctl的接口,實際上,驅動也可以簡單的把相關的命令或屬性註冊到sysfs下,這樣應用程序就只要讀寫相關屬性就能間接控制設備了,這樣應用層就只要使用cat, echo 等命令,而不用專門寫程序調用ioctl函數了。
Sysfs簡介:
sysfs 是 Linux 內核中設計較新的一種虛擬的基於內存的文件系統,它的作用與 proc 有些類似,但除了與 proc 相同的具有查看和設定內核參數功能之外,還有爲 Linux 統一設備模型作爲管理之用。相比於 proc 文件系統,使用 sysfs 導出內核數據的方式更爲統一,並且組織的方式更好,它的設計從 proc 中吸取了很多教訓。
sysfs 文件系統總是被掛載在 /sys 掛載點上。雖然在較早期的2.6內核系統上並沒有規定 sysfs 的標準掛載位置,可以把 sysfs 掛載在任何位置,但較近的2.6內核修正了這一規則,要求 sysfs 總是掛載在 /sys 目錄上;針對以前的 sysfs 掛載位置不固定或沒有標準被掛載,有些程序從 /proc/mounts 中解析出 sysfs 是否被掛載以及具體的掛載點,這個步驟現在已經不需要了。請參考附錄給出的 sysfs-rules.txt 文件鏈接。
sysfs 與 proc 相比有很多優點,最重要的莫過於設計上的清晰。一個 proc 虛擬文件可能有內部格式,如 /proc/scsi/scsi ,它是可讀可寫的,(其文件權限被錯誤地標記爲了0444 !,這是內核的一個BUG),並且讀寫格式不一樣,代表不同的操作,應用程序中讀到了這個文件的內容一般還需要進行字符串解析,而在寫入時需要先用字符串格式化按指定的格式寫入字符串進行操作;相比而言, sysfs 的設計原則是一個屬性文件只做一件事情, sysfs 屬性文件一般只有一個值,直接讀取或寫入。整個 /proc/scsi 目錄在2.6內核中已被標記爲過時(LEGACY),它的功能已經被相應的 /sys 屬性文件所完全取代。新設計的內核機制應該儘量使用 sysfs 機制,而將 proc 保留給純淨的“進程文件系統”。
驅動使用Sysfs流程:
1. 創建屬性,
一般用宏 DEVICE_ATTR來創建,原型是
#define DEVICE_ATTR(_name, _mode, _show, _store) \
structdevice_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
函數宏DEVICE_ATTR內封裝的是__ATTR(_name,_mode,_show,_stroe)方法,_show表示的是讀方法,_stroe表示的是寫方法。
當然_ATTR不是獨生子女,他還有一系列的姊妹__ATTR_RO宏只有讀方法,__ATTR_NULL等等, 如對設備的使用 DEVICE_ATTR ,對總線使用 BUS_ATTR ,對驅動使用 DRIVER_ATTR ,對類別 (class) 使用 CLASS_ATTR, 這四個高級的宏來自於<include/linux/device.h>
DEVICE_ATTR 宏聲明有四個參數,分別是名稱、權限位、讀函數、寫函數。其中讀函數和寫函數是讀寫功能函數的函數名。
2. 填充結構體struct attribute 變量:
注意, 屬性名字, 必須以dev_attr_爲前綴, 後跟屬性名
3. 封裝結構體static struct attribute_group
4. 註冊到sysfs中去
一般在驅動的probe函數中,利用sysfs_create_group(&pdev->dev.kobj,&dev_attr_grp);創建接口
5. 實現屬性讀寫函數:
以enable屬性爲例,讀寫函數爲:
通過以上簡單的5個步驟,就可以在sysfs相關的目錄下查看到接口了。當我們將數據 echo 到屬性中時,在上層實際上完成了一次 write 操作,對應到 kernel ,調用了驅動中的 “store”。同理,當我們cat 一個屬性時則會調用 “show” 。
參考: