linux设备模型,bus,device,driver,实验遇到的问题
這個問題困擾了我好久,對于內核的不熟悉,一開始是出現了使用空指針的問題,部分錯誤提示如下
Unable to handle kernel NULL pointer dereference at virtual address 00000000?? ?
pgd = c3ab4000???????????????????????????????????????????????????????????????? ?
[00000000] *pgd=33b11031, *pte=00000000, *ppte=00000000??????????????????????? ?
Internal error: Oops: 17 [#1]????????????????????????????????????????????????? ?
last sysfs file: /sys/devices/virtual/vc/vcsa4/dev???????????????????????????? ?
Modules linked in: usb_driver(+) usb_device usb_bus??????????????????????????? ?
CPU: 0??? Not tainted? (2.6.32.2-FriendlyARM #1)?????????????????????????????? ?
PC is at strcmp+0x10/0x40????????????????????????????????????????????????????? ?
LR is at usb_bus_match+0x2c/0x60 [usb_bus]??
后面我幾經周轉發現是原來match函數中設備名為空,這個我是照著其他人寫的博客上面弄的,只知道照著弄,其他的就不清楚了,后面上網搜的下面這篇文章,本想自己總結一下,不過發現他們總結的很好了,而且我完全保留原作者的文章,沒有改動。
原文地址??http://hi.baidu.com/tracyangrad/blog/item/88437f5b188d74302934f042.html
實驗環境:
linux2.6.32.2
??? 在做bus驅動實驗的時候,出現了一個問題:
提示bus_id找不到。于是到內核源代碼找了一番,果然沒有看見。直接到device結構體中看,找到的最像的也就
const char *init_name; /* initial name of the device */
想到這個也可以作為標識,并且BUS_ID_SIZE也找不到,于是將strncpy(my_dev.init_name, "my_dev", BUS_ID_SIZE);注釋掉,直接在mydev中添
加.init_name="my_dev"。
??? 但是在注冊驅動時又出現了段錯誤,根據console打印,知道在strncmp時,也就是總線在比較驅動和設備的名字的時候出問題了。
于是在比較函數里加入
printk("dev->init_name:%s\tdriver->name:%s\n", dev->init_name, driver->name);
想看看到底是怎么比較的。結果console上打印出來的是
dev->init_name:<NULL>?? driver->name:my_dev?(與下面亮點關聯)
Unable to handle kernel NULL pointer dereference at virtual address 00000000
dev->init_name不存在?
??? 于是baidu了一下,發現了了下面網友的那段,我用對了init_name,卻沒直接在內核里搜到dev_name(dev),于是又在內核搜索一番。可以找到下面一段總線上的比較函數:
static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
{
????struct bttv_sub_driver *sub = to_bttv_sub_drv(drv);
??? int len = strlen(sub->wanted);
??? if (0 == strncmp(dev_name(dev), sub->wanted, len))
??? return 1;
??? return 0;
}
它用的是dev_name(dev)而不是dev->init_name。還是在match函數里加入輸出語句,打印如下:
dev_name(dev):my_dev?????? driver->name:my_dev
成功了!
??? 那我們深究下,dev_name()是什么東東呢?
static inline const char?*dev_name(const struct device *dev)
{
??? return?kobject_name(&dev->kobj);
}
├───static inline const char *kobject_name(const struct kobject *kobj)
??? {
??????? return?kobj->name;
??? }
其實就是kobj->name;
dev_name(dev)怎么和dev->kobj-name聯系上的呢?找遍“可見”代碼找不到,猜測很可能是在device_register里面。
從源碼里順蔓摸瓜:
└─device_register
????└─device_add
????????└─if (dev->init_name)
??????????? {
??????????????? dev_set_name(dev, "%s", dev->init_name);
????????????????dev->init_name = NULL;?(亮點!)
??????????? }
??????????????? dev_set_name
????????????????└─kobject_set_name_vargs?(看到希望了!)
????????????????????└─kobj->name= kvasprintf(GFP_KERNEL, fmt, vargs);(找到了,這個就是的了!)?
找到了!就是在注冊設備的時候將init_name成員賦給了kobj->name,發現那個"亮點"沒,不是說說寫得有多漂亮(也不是說寫得不漂亮,糾結了。。),“亮
點”的意思是發現了新大陸那種感覺,越說越遠。。看到前面我為了查錯誤從控制臺打出來的信息,dev->init_name:<NULL>?? driver->name:my_dev中,dev-
>init_name等于NULL就是在這個dev->init_name = NULL;“亮點”的地方被置空了。這也是為什么用strncmp比較會出錯的原因。
要感謝下面這個網友,才想到要到內核去搜一下dev_name。內核版本號不同,必然有一些改動,當我們發現不同后,要善于從中去找到不同,找到解決問題的方
法。
以下是轉載自
網友ying_seven的博客(看到其也是轉載的,但是并沒有注明來處)
--------------------------------------------------------------------------------------------------------------------------
按照國嵌的代碼(LDD那本書上的代碼也一樣):
struct device my_bus = {
??? .bus_id = "my_bus0",
??? .release = my_bus_release,
};
static int my_match(struct device *dev, struct device_driver *driver)
{
return !strncmp(dev->bus_id, driver->name, strlen(driver->name));
}
編譯時,提示 struct device 中沒有bus_id 這樣的錯誤。打開/lib/modules/2.6.35-28-generic/build/include/linux/device.h
找到struct device? 的定義,里面沒有bus_id,但有:
const char *init_name; /* initial name of the device */????????????????????? 這句。
可見,要把上面結構中的.bus_id = "my_bus0",???????? 改為?????? .init_name = "my_bus0",
同時上網搜到,return !strncmp(dev->bus_id, driver->name, strlen(driver->name));這句也要改成:
return !strncmp(dev_name(dev), driver->name, strlen(driver->name));
這樣編譯即可成功!
另注:
如果要設置設備的名字,也不再使用strncpy(my_dev.bus_id, "my_dev", BUS_ID_SIZE);???? 而改用:
dev_set_name(&dev, "name");
總結
以上是生活随笔為你收集整理的linux设备模型,bus,device,driver,实验遇到的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: *dev=filp-private_da
- 下一篇: 高人对libsvm的经典总结(全面至极)