Chinaunix首页 | 论坛 | 博客
  • 博客访问: 136115
  • 博文数量: 39
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 237
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-23 10:59
文章分类

全部博文(39)

文章存档

2016年(2)

2015年(25)

2014年(10)

2013年(2)

我的朋友

分类: LINUX

2015-01-06 22:34:17

  U盘插入到主机的usb接口上会发生什么?在linux内核中会发生很多事情。
 首先,U盘插入后会触发主机上的usb控制器中断,并先后由主机控制器中断处理程序、usb核心(主机控制器的代码一般位于drivers/usb/host,而usb核心的代码位于/drivers/usb/core)来处理。进入到usb核心处理阶段会创建、注册这个新插入的设备--U盘。这个过程会根据U盘的vendor id和device id等等来把U盘和对应的驱动链接起来,然后U盘的驱动程序就会开始初始化这个U盘设备,这里的初始化是把它作为一个U“盘”来初始化,重点是“盘”,而usb core部分的初始化只是把它作为一个usb设备来初始化。
 另一方面,U盘它既是一个usb设备(遵循usb协议),又是一个盘---即一个storage设备,遵循的是scsi协议。那这两种特点是如何结合共存的呢?
 很简单,U盘挂在usb这个总线上,就要遵循usb协议,但是要使用U盘这个设备的功能就要遵守scsi协议(U盘具体的协议是bulk only)。读写U盘等等的操作都是通过scsi协议标准的命令来执行,一般这个过程分为:命令、数据和状态三个阶段。而这三个阶段传输的不论是命令、数据还是状态,说穿了它也就是一些数据信息(也就是bit位,而已),U盘驱动把这些scsi传输最后还是要封装成usb能够识别的bulk传输来进行,这样即照顾了scsi协议,也体谅了usb的感受。
 言归正传,usb core创建、注册的时候会把调用到U盘的驱动来初始化---主要是usb_storage_driver-->probe函数来实现,这个porbe的原型是storage_probe。在drivers/usb/strorage目录下的usb.c文件中有定义:

static struct usb_driver usb_storage_driver = {
  .name = "usb-storage",
  .probe = storage_probe,
  .disconnect = usb_stor_disconnect,
  .suspend = usb_stor_suspend,
  .resume = usb_stor_resume,
  .reset_resume = usb_stor_reset_resume,
  .pre_reset = usb_stor_pre_reset,
  .post_reset = usb_stor_post_reset,
  .id_table = usb_storage_usb_ids,
  .soft_unbind = 1,
};
 好,到这个地方,我们就需要引出我们的主角了:strorage_probe。
static int storage_probe(struct usb_interface *intf,const struct usb_device_id *id)
{
  struct us_data *us;
  int result;
  /*
     * If libusual is configured, let it decide whether a standard
     * device should be handled by usb-storage or by ub.
     * If the device isn't standard (is handled by a subdriver
     * module) then don't accept it.
  */
if (usb_usual_check_type(id, USB_US_TYPE_STOR) ||usb_usual_ignore_device(intf))
  return -ENXIO;
  /*
  * Call the general probe procedures.
  *
  * The unusual_dev_list array is parallel to the usb_storage_usb_ids
  * table, so we use the index of the id entry to find the
  * corresponding unusual_devs entry.
  */
  result = usb_stor_probe1(&us, intf, id,  (id - usb_storage_usb_ids) + us_unusual_dev_list);
  if (result)
    return result;

  /* No special transport or protocol settings in the main module */
  result = usb_stor_probe2(us);
  return result;
}
  代码不多而且也很简洁明了,probe分为两个阶段,usb_stor_probe1和usb_stor_probe2,在接下来的时光中我们将会详细讲述这两个函数。




阅读(1585) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~