http://blog.csdn.net/HellDevil/article/details/5213888
我最近在调试Android系统的gadget功能,通过make menuconfig发现gadget是编译成module模式的。里面有很多可选项,其中有个Android的选项,其实就是提供ADB和Storage的功能的。
具体查看代码在/drivers/usb/gadget下,三个文件:android.c f_adb.c f_mass_storage.c
g_android.ko 是由这三个文件而来,其中android.c 依赖于f_adb.c 和f_mass_storage.c(这两个文件之间无依赖关系)
可以在android.c中的
- static int __init android_bind_config(struct usb_configuration *c)
- {
- struct android_dev *dev = _android_dev;
- int ret;
- printk(KERN_DEBUG "android_bind_config/n");
- ret = mass_storage_function_add(dev->cdev, c, dev->nluns);
- if (ret)
- return ret;
- return adb_function_add(dev->cdev, c);
- }
看到关系
============================================================
下面说说我的问题,
1.当我将Android编译成module模式,既g_android.ko时候,然后放入rootfs中手动加载,Okay, no problem!非常happy。但是,当我关闭adb进程,rmmod g_android的时候,出现死锁状态,打开代码进行查询,发现问题出现在
- struct usb_request *req_get(struct adb_dev *dev, struct list_head *head, int DD)
- {
- unsigned long flags;
- struct usb_request *req;
- spin_lock_irqsave(&dev->lock, flags);//被锁了,郁闷
- if (list_empty(head)) {
- req = 0;
- } else {
- req = list_first_entry(head, struct usb_request, list);
- list_del(&req->list);
- }
- spin_unlock_irqrestore(&dev->lock, flags);
- return req;
- }
一直死锁,通过打开kernel hacking中的spinlock debug发现 是自己把自己锁了,找阿找阿。。。。
看了下rmmod时候 函数调用过程当我rmmod的时候,首先会去执行__exit cleanup(void)中的usb_composite_unregister(&android_usb_driver)这句话中还调用composite.c中的函数 (不细说),反正最后会调到f_adb.c中的
adb_function_unbind(struct usb_configuration *c, struct usb_function *f)
看看这个函数
- static void
- adb_function_unbind(struct usb_configuration *c, struct usb_function *f)
- {
- struct adb_dev *dev = func_to_dev(f);
- struct usb_request *req;
- spin_lock_irq(&dev->lock);//锁死你个req_get,谁叫我们共用一个dev->lock
- while ((req=req_get(dev, &dev->rx_idle,0)))//被所到死
- {
- adb_request_free(req, dev->ep_out);
- }
- while ((req=req_get(dev, &dev->tx_idle,0)))
- {
- adb_request_free(req, dev->ep_in);
- }
- dev->online = 0;
- dev->error = 1;
- spin_unlock_irq(&dev->lock);
- misc_deregister(&adb_device);
- kfree(_adb_dev);
- _adb_dev = NULL;
- }
所以感觉 req_get代码中的spinlock有问题,没办法,只能写了个req_get_free_lock(不加锁)替代while循环中的req_get函数
rebuild 内核,Okay 卸载g_android.ko 没问题 哈哈。正当自己高兴的时候,发现乐极生悲了。。。
===========================================================
卸载完了g_android.ko 我再次insmod g_android.ko 挂了,不过不是kernel panic而是提示
"sysfs: duplicate filename 'usb_mass_storage' can not be created"
恩 这次出在f_mass_storage.c这个文件中,根据信息提示应该是没因为上次没卸载完全。没办法,在几个与insmod和rmmod的函数中加入打印信息。主要是mass_storage_function_add, fsg_function_bind,fsg_function_unbind三个函数,前两个是跟insmod有关,后者跟rmmod有关。
通过打印信息发现一个Android开发者的 小纰漏 导致的问题,就是在
- int __init mass_storage_function_add(struct usb_composite_dev *cdev,
- struct usb_configuration *c, int nluns)
- {
- int rc;
- struct fsg_dev *fsg;
- printk(KERN_INFO "mass_storage_function_add/n");
- rc = fsg_alloc();
- if (rc)
- return rc;
- fsg = the_fsg;
- fsg->nluns = nluns;
- spin_lock_init(&fsg->lock);
- init_rwsem(&fsg->filesem);
- kref_init(&fsg->ref);
- init_completion(&fsg->thread_notifier);
- the_fsg->buf_size = BULK_BUFFER_SIZE;
- the_fsg->sdev.name = DRIVER_NAME;
- the_fsg->sdev.print_name = print_switch_name;
- the_fsg->sdev.print_state = print_switch_state;
- rc = switch_dev_register(&the_fsg->sdev);//卸载的时候没有swith_dev_unregister
- if (rc < 0)
- goto err_switch_dev_register;
- wake_lock_init(&the_fsg->wake_lock, WAKE_LOCK_SUSPEND,
- "usb_mass_storage");
- fsg->cdev = cdev;
- fsg->function.name = shortname;
- fsg->function.descriptors = fs_function;
- fsg->function.bind = fsg_function_bind;
- fsg->function.unbind = fsg_function_unbind;
- fsg->function.setup = fsg_function_setup;
- fsg->function.set_alt = fsg_function_set_alt;
- fsg->function.disable = fsg_function_disable;
- rc = usb_add_function(c, &fsg->function);
- if (rc != 0)
- goto err_usb_add_function;
- return 0;
- err_usb_add_function:
- switch_dev_unregister(&the_fsg->sdev);
- err_switch_dev_register:
- kref_put(&the_fsg->ref, fsg_release);
- return rc;
- }
在掉用过/drivers/switch/class_switch.c 中的 switch_dev_register后,除了出错处理再也没作擦屁股的动作(unregister)汗,这不是占着XX不拉什么吗?没办法,去fsg_function_unbind函数中的
- for (i = 0; i < fsg->nluns; ++i) {
- curlun = &fsg->luns[i];
- if (curlun->registered) {
- switch_dev_unregister(&the_fsg->sdev);//加入擦屁股的一句
- device_remove_file(&curlun->dev, &dev_attr_file);
- device_unregister(&curlun->dev);
- curlun->registered = 0;
- }
- }
Okay 万事Okay 主阿!其实都不是什么大的问题拉。但是导致的现象确很恐怖。android developer太忙了,毕竟也是人阿。呵呵,以前都不敢改他们代码,总是推敲自己是不是哪边错了。想报bug去android开发者论坛,但是被该死的河蟹给和谐了,打不开report issue界面。感谢伟大的政府让我们这些P民,成为白痴和弱智。
草泥马的 !