linux筆記5

linux設(shè)備模型bus,device,driver
作者 codercjg10 十一月 2015, 2:43 下午

linux2.6提供了新的設(shè)備模型:總線、驅(qū)動(dòng)掉蔬、設(shè)備勾习∨ǖ桑基本關(guān)系簡(jiǎn)要的概括如下:
驅(qū)動(dòng)核心可以注冊(cè)多種類型的總線。
每種總線下面可以掛載許多設(shè)備巧婶。(通過kset devices)
每種總線下可以用很多設(shè)備驅(qū)動(dòng)乾颁。(通過包含一個(gè)kset drivers)}
每個(gè)驅(qū)動(dòng)可以處理一組設(shè)備。按照我的理解就是所有的設(shè)備都掛載到總線上粹舵,當(dāng)加載驅(qū)動(dòng)時(shí)钮孵,驅(qū)動(dòng)就支總線上找到自己對(duì)應(yīng)的設(shè)備⊙勐耍或者先把驅(qū)動(dòng)加載上巴席,來了一個(gè)設(shè)備就去總線找驅(qū)動(dòng)。
一:總線
總線是處理器與設(shè)備之間通道诅需,在設(shè)備模型中漾唉,所有的設(shè)備都通過總線相連。
關(guān)于總線的一些結(jié)構(gòu)體:bus_type堰塌,
(1)bus_type:
struct bus_type {
const char * name;//設(shè)備名稱
struct subsystem subsys;//代表自身
struct kset drivers; //當(dāng)前總線的設(shè)備驅(qū)動(dòng)集合
struct kset devices; //所有設(shè)備集合
struct klist klist_devices;
struct klist klist_drivers;
struct bus_attribute * bus_attrs;//總線屬性
struct device_attribute * dev_attrs;//設(shè)備屬性
struct driver_attribute * drv_attrs;
int (match)(struct device * dev, struct device_driver * drv);//設(shè)備驅(qū)動(dòng)匹配函數(shù)
int (
uevent)(struct device dev, char envp, int num_envp, char buffer, int buffer_size);//熱拔插事件
int (
probe)(struct device * dev);
int (
remove)(struct device * dev);
void (
shutdown)(struct device * dev);
int (
suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
在后面的實(shí)例當(dāng)中用到了里面的兩個(gè)成員
1:const char name;
2:int (
match)(struct device * dev, struct device_driver * drv);
設(shè)備驅(qū)動(dòng)匹配函數(shù)赵刑,這個(gè)匹配函數(shù)是很關(guān)鍵的東西,這是建立總線上設(shè)備與驅(qū)動(dòng)的橋梁场刑,當(dāng)一個(gè)新的設(shè)備或驅(qū)動(dòng)被添加到一個(gè)總線上時(shí)被調(diào)用般此。
(2)總線的操作:
注冊(cè):int bus_register(struct bus_type * bus)
注銷:void bus_unregister(struct bus_type bus);
(3)總線屬性 bus_attribute
struct bus_attribute {
struct attribute attr;
ssize_t (
show)(struct bus_type *bus, char buf);
ssize_t (
store)(struct bus_type *bus, const char *buf,size_t count);
};
BUS_ATTR(name, mode, show, store);
這個(gè)宏聲明一個(gè)結(jié)構(gòu), 產(chǎn)生它的名子通過前綴字符串 bus_attr_ 到給定的名子(bus_attr_name),然后利用bus_create_file來創(chuàng)建總線屬性
int bus_create_file(struct bus_type *bus, struct bus_attribute *attr);
參數(shù)中的attr牵现,即為bus_attr_name铐懊。
另外, 就是參數(shù)中的 show 方法,設(shè)置方法如下
static ssize_t show_bus_version(struct bus_type *bus, char *buf) {
return snprintf(buf, PAGE_SIZE, “%s\n”, Version);
}
總線屬性的刪除, 使用:
void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr);
(4)總線實(shí)例:
1:首先是要準(zhǔn)備一個(gè)總線bus_type.也就是定義一個(gè)bus_type瞎疼,然后給它填上一些成員科乎。定義如下:
struct bus_type my_bus_type = {
.name = “my_bus”,
.match = my_match,
};
這里就對(duì)其兩個(gè)成員賦值了。一個(gè)是名稱贼急。另一個(gè)則是匹配函數(shù):
2茅茂,總線本身也是要對(duì)應(yīng)一個(gè)設(shè)備的。還要為總線創(chuàng)建設(shè)備太抓。
struct device my_bus = {
.bus_id = “my_bus0″,
.release = my_bus_release
};
源代碼:

include <linux/module.h>

include <linux/kernel.h>

include <linux/init.h>

include <linux/device.h>

include <linux/string.h>

static char *version = “version 1.0″;
//用于判斷指定的驅(qū)動(dòng)程序是否能處理指定的設(shè)備空闲。
static int my_match(struct device *dev, struct device_driver *driver) {
return !strncmp(dev->bus_id, driver->name, strlen(driver->name));
}
static int my_bus_release(struct device *dev) {
return 0;
}
static ssize_t show_bus_version(struct bus_type *bus, char buf) {
return sprintf(buf, PAGE_SIZE, “%s\n”, version);
}
static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);
struct device my_bus = {//定義總線設(shè)備
.bus_id = “my_bus0″,
.release = my_bus_release,
};
EXPORT_SYMBOL(my_bus);
struct bus_type my_bus_type = { //定義總線類型
.name = “my_bus”,
.match = my_match,
};
EXPORT_SYMBOL(my_bus_type);
static int __init my_bus_init(void){
int ret;
ret = bus_register(&my_bus_type);//注冊(cè)總線
if(ret)
printk(“bus_register failed!\n”);
if(bus_create_file(&my_bus_type, &bus_attr_version))//創(chuàng)建總線屬性
printk(“Creat bus failed!\n”);
ret = device_register(&my_bus);//注冊(cè)總線設(shè)備
if (ret)
printk(“device_register failed!\n”);
return ret;
}
static void __exit my_bus_exit(void) {
bus_unregister(&my_bus_type);//刪除總線屬性
device_unregister(&my_bus);//刪除總線設(shè)備
}
module_init(my_bus_init);
module_exit(my_bus_exit);
MODULE_AUTHOR(“Fany”);
MODULE_LICENSE(“GPL”);
(5)測(cè)試
將bus.c以動(dòng)態(tài)加載的方式加載到內(nèi)核,insmod bus.ko走敌,在/sys/bus/目錄下會(huì)有一個(gè)my_bus目錄进副,這就是我們添加的總線。該目錄下有devices,drivers目錄影斑,因?yàn)樵摽偩€上沒有掛載任何設(shè)備和驅(qū)動(dòng),所以這兩個(gè)目錄都為空机打;同時(shí)矫户,在/sy/devices目錄下,還可看到my_bus0設(shè)備(總線本身也是一種設(shè)備)残邀。
二:設(shè)備:
關(guān)于設(shè)備的一些常用結(jié)構(gòu)體:device皆辽,
1:
struct device {
struct device * parent; //父設(shè)備,一般一個(gè)bus也對(duì)應(yīng)一個(gè)設(shè)備芥挣。
struct kobject kobj;//代表自身
char bus_id[BUS_ID_SIZE];
struct bus_type * bus; /
所屬的總線 /
struct device_driver driver; / 匹配的驅(qū)動(dòng)
/
void driver_data; / data private to the driver 指向驅(qū)動(dòng) /
void platform_data; / Platform specific data驱闷,由驅(qū)動(dòng)定義并使用
/
………..更多字段忽略了
};
注冊(cè)設(shè)備:int device_register(sruct device *dev)
注銷設(shè)備:void device_unregister(struct device dev);
2:設(shè)備屬性:
sysfs 中的設(shè)備入口可有屬性. 相關(guān)的結(jié)構(gòu)是:
struct device_attribute {
struct attribute attr;
ssize_t (
show)(struct device *dev, char buf);
ssize_t (
store)(struct device *dev, const char *buf,
size_t count);
};
這些屬性結(jié)構(gòu)可在編譯時(shí)建立, 使用這些宏:
DEVICE_ATTR(name, mode, show, store);
結(jié)果結(jié)構(gòu)通過前綴 dev_attr_ 到給定名子上來命名. 屬性文件的實(shí)際管理使用通常的函數(shù)對(duì)來處理:
int device_create_file(struct device *device, struct device_attribute *entry);
void device_remove_file(struct device *dev, struct device_attribute *attr);
3:創(chuàng)建設(shè)備實(shí)例:

include <linux/module.h>

include <linux/kernel.h>

include <linux/init.h>

include <linux/device.h>

include <linux/string.h>

extern struct device my_bus; //這里用到了總線設(shè)備中定義的結(jié)構(gòu)體
extern struct bus_type my_bus_type;
static int my_device_release() {
return 0;
}
struct device my_dev={ //創(chuàng)建設(shè)備屬性
.bus = &my_bus_type,//定義總線類型
.parent = &my_bus,//定義my_dev的父設(shè)備。
.release = my_device_release,
};
static ssize_t mydev_show(struct device dev, char buf) {
return sprintf(buf, “%s\n”, “This is my device!”);
}
static DEVICE_ATTR(dev, S_IRUGO, mydev_show, NULL);
static int __init my_device_init(void){
int ret;
strncpy(my_dev.bus_id, “my_dev”, BUS_ID_SIZE); //初始化設(shè)備
ret = device_register(&my_dev); //注冊(cè)設(shè)備
if (ret)
printk(“device register!\n”);
device_create_file(&my_dev, &dev_attr_dev); //創(chuàng)建設(shè)備文件
return ret;
}
static void __exit my_device_exit(void) {
device_unregister(&my_dev);//卸載設(shè)備
}
module_init(my_device_init);
module_exit(my_device_exit);
MODULE_AUTHOR(“Fany”);
MODULE_LICENSE(“GPL”);
4:測(cè)試
將設(shè)備device.c空免,編譯成模塊空另,以動(dòng)態(tài)加載的方式加載到內(nèi)核。會(huì)發(fā)現(xiàn)在sys/bus/my_bus/devices/目錄下有一個(gè)my_dev設(shè)備蹋砚,查看屬性扼菠,它是掛在/sys/devices/my_bus0/my_dev目錄下,至此添加設(shè)備成功坝咐。
三:設(shè)備驅(qū)動(dòng):
1:關(guān)于驅(qū)動(dòng)的常用結(jié)構(gòu)體:device_driver
struct device_driver {
const char name; /驅(qū)動(dòng)程序的名字( 在 sysfs 中出現(xiàn) )
/
struct bus_type bus; /驅(qū)動(dòng)程序所操作的總線類型
/
struct module *owner;
const char mod_name; / used for built-in modules /
int (
probe) (struct device dev);
int (
remove) (struct device dev);
void (
shutdown) (struct device dev);
int (
suspend) (struct device dev, pm_message_t state);
int (
resume) (struct device *dev);
struct attribute_group *groups;
struct pm_ops pm;
struct driver_private p;
};
2:驅(qū)動(dòng)程序的注冊(cè)和注銷
/
注冊(cè)device_driver 結(jié)構(gòu)的函數(shù)是:
/
int driver_register(struct device_driver drv);
void driver_unregister(struct device_driver drv);
3:驅(qū)動(dòng)程序的屬性
/
driver的屬性結(jié)構(gòu)在:
/
struct driver_attribute {
struct attribute attr;
ssize_t (
show)(struct device_driver *drv, char buf);
ssize_t (
store)(struct device_driver drv, const char buf, size_t count);
};
DRIVER_ATTR(_name,_mode,_show,_store) /
屬性文件創(chuàng)建的方法:
/
int driver_create_file(struct device_driver * drv, struct driver_attribute * attr);//創(chuàng)建設(shè)備驅(qū)動(dòng)的屬性
void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr);
4:驅(qū)動(dòng)實(shí)例

include <linux/module.h>

include <linux/kernel.h>

include <linux/init.h>

include <linux/device.h>

include <linux/string.h>

extern struct bus_type my_bus_type;
static int my_probe(struct device *dev) {
printk(“Driver found device!\n”);
return 0;
};
static int my_remove(struct device *dev) {
printk(“Driver unpluged!\n”);
return 0;
};
struct device_driver my_driver = {
.name = “my_dev”,
.bus = &my_bus_type,
.probe = my_probe,
.remove = my_remove,
};
//定義設(shè)備驅(qū)動(dòng)屬性
static ssize_t my_driver_show(struct device_driver *driver, char *buf) {
return sprintf(buf, “%s\n”, “This is my driver!”);
};
static DRIVER_ATTR(drv, S_IRUGO, my_driver_show, NULL);
static int __init my_driver_init(void){
int ret;
//注冊(cè)設(shè)備驅(qū)動(dòng)
ret = driver_register(&my_driver);
if(ret)
printk(“driver_register failed!\n”);
//創(chuàng)建設(shè)備驅(qū)動(dòng)屬性
ret = driver_create_file(&my_driver, &driver_attr_drv);
if(ret)
printk(“create_driver_file failed!\n”);
return ret;
}
static void __exit my_driver_exit(void){
driver_unregister(&my_driver);//注銷設(shè)備驅(qū)動(dòng)
}
module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_AUTHOR(“Fany”);
MODULE_LICENSE(“GPL”);
5:測(cè)試
當(dāng)加載驅(qū)動(dòng)程序時(shí)循榆,終端界面上打印
Driver found device!
說明驅(qū)動(dòng)找到了匹配的設(shè)備,看到打印這個(gè)時(shí)墨坚,想到在windows下插U盤秧饮,立馬彈出“發(fā)現(xiàn)可移動(dòng)設(shè)備”,有點(diǎn)相像泽篮!
再看看相應(yīng)的目錄:/sys/bus/my_bus/drivers/盗尸,多了一個(gè)my_dev。

說明添加驅(qū)動(dòng)成功
原文地址:http://blog.chinaunix.net/uid-23254875-id-341060.html

分類: Linux驅(qū)動(dòng) | 評(píng)論

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末咪辱,一起剝皮案震驚了整個(gè)濱河市振劳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌油狂,老刑警劉巖历恐,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異专筷,居然都是意外死亡弱贼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門磷蛹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吮旅,“玉大人,你說我怎么就攤上這事”硬” “怎么了檬嘀?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)责嚷。 經(jīng)常有香客問我鸳兽,道長(zhǎng),這世上最難降的妖魔是什么罕拂? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任揍异,我火速辦了婚禮,結(jié)果婚禮上爆班,老公的妹妹穿的比我還像新娘衷掷。我一直安慰自己,他們只是感情好柿菩,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布戚嗅。 她就那樣靜靜地躺著,像睡著了一般碗旅。 火紅的嫁衣襯著肌膚如雪渡处。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天祟辟,我揣著相機(jī)與錄音医瘫,去河邊找鬼。 笑死旧困,一個(gè)胖子當(dāng)著我的面吹牛醇份,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吼具,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼僚纷,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了拗盒?” 一聲冷哼從身側(cè)響起怖竭,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎陡蝇,沒想到半個(gè)月后痊臭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡登夫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年广匙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恼策。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸦致,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情分唾,我是刑警寧澤抗碰,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站绽乔,受9級(jí)特大地震影響改含,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜迄汛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骤视。 院中可真熱鬧鞍爱,春花似錦、人聲如沸专酗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祷肯。三九已至沉填,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佑笋,已是汗流浹背翼闹。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蒋纬,地道東北人猎荠。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蜀备,于是被迫代替她去往敵國(guó)和親关摇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容