日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux设备模型,bus,device,driver,实验遇到的问题

發布時間:2024/9/21 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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,实验遇到的问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。