Archive for 七月, 2009

在iceweasel中运行applet需要装一个plugin,不装,直接本地链接

cd ~/.mozilla/plugins
ln -s /usr/lib/jvm/java-6-sun/jre/plugin/i386/ns7/libjavaplugin_oji.so

弄完之后Enpiphany也可以运行了applet了

无题

以下照片全部在信远楼拍摄

P1 同行

img_2764

P2 凉爽的雨

img_2790

P3  信远4楼墙壁上的心情

img_2788

P4 看法

img_2795

USB驱动学习笔记(2)

1.期末考终于结束了,这下可以看看USB驱动了。
上次看了几个基本的数据结构,现在看看函数都是干嘛的。驱动被加载之后调用了usb_register函数,从这个函数又转到了usb_register_driver() 函数,然后在usb_register_driver()中调用了一个名为driver_register()的函数,从名字来看,显然是为了用来注册驱动的,这个函数的传入参数就是封装在struct usbdrv_wrap里面的driver成员。
在看driver_register()函数之前,注意到usb_register_driver()函数中一句:

725          new_driver->drvwrap.driver.bus = &usb_bus_type;

这个bus就是驱动程序要去挂牌的地方。

现在进入driver_register()函数去看看。在driver_register() 中,调用了driver_find(drv->name, drv->bus)函数,这里是干啥呢?这里是先去驱动打算挂牌的地方先查找一下,这个驱动是否已经挂牌(注册)过了。在哪里查找呢?代码中写得很清楚,去bus->p->drivers_kset中查找,看到这里,我决定这里不要再继续展开细细的分析,否则永远都无法把内核看明白,有时候必须对细节很了解,有时候只要明白他的工作原理就可以,不必太细碎。简单的看,drivers_kset就是一个klist链表,链表的节点都是内核对象,也就是kobject。kset中的kobject可以是不同“类型”的(different “type”),kset只是把一类需要用进行相同处理的kobject放在一起。driver_find函数其实也不干活,它是调用kset_find_obj函数去遍历链表根据drv->name去寻找,我不管找的过程,反正如果找到了driver_find()就返回指向已经注册的驱动的指针,如果没找到就返回NULL。
回到driver_register() ,如果驱动已经注册过了,那就退出好了。如果没有注册,接下来调用bus_add_driver(struct device_driver *drv) 函数注册驱动。这个函数有点长,主要作用就是把drv放到drv->bus->p->klist_drivers链表的尾部。到此就完成注册工作。
阅读了一些老手的笔记,看了一点内核代码,看了LDD,再加上自己的猜测,现在对驱动的工作机制有了一点认识。
内核在维护两条链表,一个用来记录devices,一个用来记录drivers。系统接电开机后,总线就扫一遍有哪些设备接到计算机上了,每个设备都对应一个设备对象,然后就把设备对象填入到记录devices的链表中。接着系统继续启动,到了加载驱动的过程,把驱动对象都填入到记录drivers的链表中。每加载一个驱动,就去遍历一次devices链表,看看有没有自己要服务的设备,如果有,就把该设备对象的驱动指针指向自己,同时把该设备对象加入到驱动程序维护的设备链表中,该设备链表记录了这个驱动能够服务的设备。这是在开机之前硬件就和计算机连接好的工作方式,但是现在更实用的是另外一种工作方式,就是热插拔。
热插拔意味着设备和驱动没有谁先谁后进入系统,因为都有可能。所以工作方式就是一旦有一个设备插入,总线把对应的设备对象加入到记录devices的链表后就去查找那条记录drivers链表,看看有没有能够驱动这个设备的驱动,如果有驱动对象和设备对象就互相指向,这样驱动就能为该设备服务。如果没有找到驱动呢?很简单,设备不工作呗。这个设备就只好等待自己需要的驱动被加载,驱动会去找他。反过来说,驱动可能在设备插入之前被加载,同样的,驱动没有在记录devices的链表上找到她要服务的设备,驱动也就只好等待设备被插入的时候来找她。
那么下一步,就应该看一下驱动和设备的联系过程了。假期就这样顺着设备和驱动的工作流程,慢慢看吧。希望在暑假结束时,能够对Linux平台的USB驱动有比较深入的理解和认识,不求自己能写出实际可用的驱动来,只要能明白驱动的工作机制就算是假期的收获了。