![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
《Linux那些事儿之我是USB》
文章平均质量分 81
fudan_abc
这个作者很懒,什么都没留下…
展开
-
《Linux那些事儿之我是USB》前言
1992年,那是一个春天。不过其实1991年又何尝不是一个春天呢,因为正是在那一年,Linux诞生了。又因为开放源代码的缘故,十几年来Linux是越来越火,熊熊火焰也烧到了华夏大地。诸多高校开始开设Linux相关的课程,诸多企业开始招聘Linux相关的人才。市面上关于Linux的书籍也层出不穷,而这其中大致分为两类,一类是应用方面的,比如介绍如何组建各种服务器啊,另一类是内核方面的,主要都是对内核源代码的进行分析,这方面的书籍则以《Linux设备驱动程序》和《深入理解Linux内核》为经典代表。而从眼下国内原创 2010-07-29 12:34:00 · 19948 阅读 · 19 评论 -
《Linux那些事儿之我是USB》我是U盘(21)传说中的URB
有人问,怎么写一个驱动写这么久啊?的确,一路走来,大家都不容易,但既然已经走到今天,我们能做的也只有是坚持下去。usb_stor_acquire_resources(),从名字上来看是获取资源。什么是资源?之前不是申请了一大堆内存了吗?写个USB设备驱动程序怎么这么麻烦啊?不是专门为USB Mass Storage设备准备了一个struct us_data这么一个结构体了吗?不是说故事已经原创 2011-10-19 21:25:15 · 10240 阅读 · 2 评论 -
《Linux那些事儿之我是USB》我是U盘(22)彼岸花的传说(一)
彼岸花,花语是悲伤的回忆。很久很久以前,城市的边缘开满了大片大片的曼珠沙华,它的花香有一种魔力,可以让人想起自己前世的事情。守护曼珠沙华的是两个妖精,一个是花妖叫曼珠,一个是叶妖叫沙华。他们守候了几千年,可是从来没有见过面,因为开花时,就没有叶子,有叶子时没有花。他们疯狂地想念着彼此,并被这种痛苦折磨着。终于有一天,他们决定违背神的规定偷偷地见一次面。那一年的曼珠沙华红艳艳的花被惹眼的绿色衬托原创 2011-10-20 22:02:52 · 11919 阅读 · 3 评论 -
《Linux那些事儿之我是USB》我是U盘(23)彼岸花的传说(二)
如果让大家投票的话,usb_stor_control_thread()这个函数中的代码无疑是整个模块中最为精华的代码。我们只需要它中间306行的for(;;)就知道,这是一个死循环,即使别的代码都执行完了,即使别的函数都退出了,这个函数也仍然像永不消逝的电波一般,经典常驻。显然,只有死循环才能代表永恒,才能代表忠诚。这是每一个守护者的职责。usb_stor_control_thread(),其原创 2011-10-25 18:12:33 · 11015 阅读 · 1 评论 -
《Linux那些事儿之我是USB》我是U盘(24)彼岸花的传说(三)
前面已经说了,回到usb_stor_acquire_resources()函数中,返回了0。于是咱们终于回到了storage_probe()函数中来。1008行,scsi_add_host()函数被执行,之前申请的us->host被作为参数传递给它,同时,intf->dev也被传递给它,这个东西是被用来注册sysfs的。前面已经说过,在scsi_host_alloc之后,必须执行scsi_ad原创 2011-10-26 20:38:21 · 11086 阅读 · 0 评论 -
《Linux那些事儿之我是USB》我是U盘(25)彼岸花的传说(四)
我们刚刚跟着storage_probe()几乎完整地走了一遍,貌似一切都该结束了,可是你不觉得你到目前为止还根本没有看明白设备究竟怎么工作的吗?U盘,不仅仅是USB设备,还是“盘”,它还需遵守USB Mass Storage协议,以及Transparent SCSI规范。从驱动程序的角度来看,它和一般的SCSI磁盘差不多。正是因为如此,所以U盘的工作真正需要的是四个模块,usbcore,scsi_原创 2011-10-30 18:51:09 · 16051 阅读 · 8 评论 -
《Linux那些事儿之我是USB》我是U盘(28)彼岸花的传说(七)
很显然,我们是把为INQUIRY命令准备的数据保存到了我们自己定义的一个结构体中,即structdata_ptr[36],但是我们是为了回应一个SCSI命令,最终需要知道答案的是SCSI核心层。正是它们传递了一个scsi_cmnd结构体下来,即srb。struct scsi_cmnd中有两个成员,即unsigned request_bufflen和void *request_buffer,应该把d原创 2011-11-21 18:50:33 · 12087 阅读 · 0 评论 -
《Linux那些事儿之我是USB》我是U盘(29)彼岸花的传说(八)
对于use_sg为0的情况,我们接下来再看168行,offset是函数调用传递进来的参数,注释里说得很清楚,就是用来标志偏移量的,每次复制几个字节它就增加几个字节,最大它也不能超过request_bufflen,这是显然的。usb_stor_access_xfer_buf()这个函数所做的事情就是从srb->request_buffer往buffer里边复制数据,或者反过来从buffer往srb-原创 2011-11-24 23:24:11 · 12162 阅读 · 1 评论 -
《Linux那些事儿之我是USB》我是U盘(30)彼岸花的传说(The End)
解决了这个INQUIRY的问题,我们就可以继续往下走了,372行,这就是真正的批量传输的地方,proto_handler()就是正儿八经的处理SCSI命令的函数指针。而usb_stor_control_thread之前的所有代码就是为了判断是不是有必要调用函数proto_handler(),比如超时了,比如模块该卸载了,比如设置断开flag了,比如要处理的就是这个有问题的INQUIRY等,这些情况原创 2011-11-29 20:00:36 · 11955 阅读 · 0 评论 -
《Linux那些事儿之我是USB》我是U盘(31)SCSI命令之我型我秀
usb_stor_control_thread()基本讲完了,但是其中下面这几行,正是高潮中的高潮。所谓的批量传输,所谓的Bulk-Only协议。正是在这里体现出来的。371 /* we've got a command, let's do it! */372 else {373 US_DEBUG(usb_stor_s原创 2011-12-01 22:49:50 · 16234 阅读 · 2 评论 -
《Linux那些事儿之我是USB》我是U盘(26)彼岸花的传说(五)
下面讲一下usb_stor_control_thread()函数。唤醒它的是来自queuecommand的up(&(us->sema)),us->srb被赋值为srb,而srb是来自SCSI核心层在调用queuecommand时候传递进来的参数。聚焦usb_stor_control_thread()。314行,前面说过,关于dev_mutex这把锁我们必须在看完整个模块之后再来从较高的角度来看。原创 2011-11-10 21:09:52 · 11410 阅读 · 0 评论 -
《Linux那些事儿之我是USB》我是U盘(27)彼岸花的传说(六)
我们继续接着上一节往下看。fill_inquiry_response(),这个函数来自drivers/usb/storage/usb.c中。266 void fill_inquiry_response(struct us_data *us,unsigned char *data,267 unsigned int data_len)268 {269原创 2011-11-13 22:15:17 · 14684 阅读 · 5 评论 -
《Linux那些事儿之我是USB》我是U盘(32)迷雾重重的批量传输(一)
374行,us->proto_handler()其实是一个函数指针,知道它指向什么吗?我们早在storage_probe()中,确切地说,在get_protocol()就赋了值,当时只知道是get protocol,却不知道究竟干什么用,现在该用上了,一个指针要是没什么用人家才不会为它赋值呢。当初我们就讲了,对于U盘,proto_handler被赋值为usb_stor_transparent_sc原创 2011-12-06 21:56:32 · 15835 阅读 · 3 评论 -
《Linux那些事儿之我是USB》我是U盘(33)迷雾重重的批量传输(二)
其实故事已经讲了很久,但如果你觉得到这里你已经把故事都看明白了,那么你错了。不仅仅是错了。不信,我们就继续看,先看512行,us->transport(),这个函数指针同样是在storage_probe时被赋值,对于U盘,它遵守的是Bulk-Only协议,因此us->transport()被赋值为usb_stor_Bulk_transport()。来看usb_stor_Bulk_transport原创 2011-12-15 22:15:35 · 13216 阅读 · 3 评论 -
《Linux那些事儿之我是USB》我是U盘(34)迷雾重重的批量传输(三)
在usb_stor_Bulk_transport()中,这个函数中调用的第一个最重要的函数,那就是usb_stor_bulk_transfer_buf()。仍然是来自drivers/usb/stroage/transport.c:391 int usb_stor_bulk_transfer_buf(struct us_data*us, unsigned int pipe,392原创 2011-12-26 19:58:11 · 14827 阅读 · 2 评论 -
《Linux那些事儿之我是USB》我是U盘(35)迷雾重重的批量传输(四)
有时候我也被这个问题所困扰,我不知道是我不明白,还是这世界变化太快。连Linux中都引入了过期这么一个概念。设置一个时间,如果时间到了该做的事情还没有做完,那么某些事情就会发生。比如需要烤蛋糕,现在是8点30,而我们要烤45分钟,所以希望闹钟9点一刻响,当时间到了,闹钟就如期待的一样,响个不停。在计算机中,也需要做这样的事情,有些事情,需要时间控制,特别是网络、通信等,凡是涉及数据传输,就得考原创 2012-01-05 23:16:21 · 16356 阅读 · 6 评论 -
《Linux那些事儿之我是USB》我是U盘(36)迷雾重重的批量传输(五)
在讲数据传输阶段之前,先解决刚才的历史遗留问题。usb_stor_bulk_transfer_buf()中,406行,有一个很有趣的函数interpret_urb_result()被调用。这个函数同样来自drivers/usb/storage/transport.c中:265 static int interpret_urb_result(struct us_data*us, unsign原创 2012-03-08 22:09:34 · 15477 阅读 · 1 评论 -
《Linux那些事儿之我是USB》第二版 前言
从开始写Linux那些事儿系列文字开始,到如今已有四年多了,而从整理出版第一版到现在也已经一载有余了。期间不断有认识或不认识的朋友问我,怎么会想起写这么多如此可爱的文字,我的回答都是:娱乐自己,娱乐大家而已!或许,大家早已经默认技术本是一个沉重或者说枯燥的话题,我们无法用一种娱乐的心态去看待它,甚至说很多人早已丧失了从中获取乐趣的能力。但是,一切本不该如此的,对于不管什么原因踏入这个行业的我们原创 2012-04-15 19:23:14 · 16987 阅读 · 6 评论 -
《Linux那些事儿之我是USB》我是U盘(16)冬天来了,春天还会远吗?(二)
打开unusual_devs.h吧,之前我们看了它的最后几行,但是如果你仔细看的话会发现最后几行和前面的一些行有着明显的不同。最后几行都是USUAL_DEV的宏,而前面则全是UNUSUAL_DEV的宏,随便看一下,发现每一行就是这么一个宏,毫无疑问它对应一种设备,我们从其中挑一个原创 2011-09-28 21:32:42 · 7313 阅读 · 3 评论 -
《Linux那些事儿之我是USB》我是U盘(20)通往春天的管道
1991年,一个在Linux中引入了管道这个概念,并且把管道用在很多地方,如文件系统、设备驱动中。于是后来我们看到在Linux中有了各种各样的管道。但是相同的是,所有管道都是用来传输东西的,只不过有些管道传输的是实实在在的物质,而有些管道传输的是数据。眼下我们在USB代码中看原创 2011-10-18 21:38:29 · 4748 阅读 · 4 评论 -
《Linux那些事儿之我是USB》我是U盘(17)冬天来了,春天还会远吗?(三)
从两张表得到了我们需要的东西,然后下面的代码就是围绕着这两个指针来展开了。(unusual_dev和id)继续看get_device_info()。497行,把unusual_dev给记录在us里面,反正us里面也有这么一个成员。这样记录下来以后使用起来就方便了,因为us是贯原创 2011-10-08 19:31:59 · 4087 阅读 · 1 评论 -
《Linux那些事儿之我是USB》我是U盘(1)小城故事
这个故事中使用的是2.6.22的内核代码。原创 2010-08-02 23:35:00 · 14251 阅读 · 2 评论 -
《Linux那些事儿之我是USB》我是U盘(2)Makefile
“出来混,迟早要还的。”原创 2010-08-05 22:35:00 · 12033 阅读 · 1 评论 -
《Linux那些事儿之我是USB》我是U盘(4)想到达明天现在就要启程
真的,我没说假话,写驱动不是什么难事,你完全可以很自信地说,你已经可以写设备驱动了。对,没错,“飘柔,就这么自信。”原创 2010-08-11 08:24:00 · 10076 阅读 · 4 评论 -
《Linux那些事儿之我是USB》我是U盘(5)外面的世界很精彩
看代码之前,我曾经认真地思考过这么一个问题,需要关注的仅仅是drivers/usb/storage/目录下面那相关的3000多行代码吗?就是这样几个文件就能让一个个不同的U盘在Linux下面工作起来吗?像一开始那样把这个目录比成一个小城的话,也许,城里的月光很漂亮,她能够把人的梦照亮,能够温暖人的心房。但我们真的就能厮守在这个城里,一生一世吗?原创 2010-08-19 22:28:00 · 8886 阅读 · 5 评论 -
《Linux那些事儿之我是USB》我是U盘(6)未曾开始却似结束
这一切,不禁让人产生了一种幻觉,让人分不清故事从哪里开始,又从哪里结束,一切都太短暂了。仿佛开始在结束时开始,而结束却在开始时就早已结束。原创 2010-09-13 09:36:00 · 9259 阅读 · 0 评论 -
《Linux那些事儿之我是USB》我是U盘(7)狂欢是一群人的孤单
Linux设备模型中三个很重要的概念就是总线、设备和驱动,即bus、device和driver。而实际上内核中也定义了这么一些数据结构,他们是structbus_type,struct device,struct device_driver,这三个重要的数据结构都来自同一个地方,称include/linux/device.h。原创 2011-06-30 12:22:00 · 10801 阅读 · 10 评论 -
《Linux那些事儿之我是USB》我是U盘(8)总线、设备和驱动(上)
struct bus_type中为设备和驱动准备了两个链表,而代表设备的结构体struct device中又有两个成员,struct bus_type *bus和struct device_driver *driver。同样,代表驱动的结构体struct de原创 2011-07-06 16:25:34 · 8327 阅读 · 5 评论 -
《Linux那些事儿之我是USB》我是U盘(9)总线、设备和驱动(下)
bus上的两张链表记录了每一个设备和驱动,那么设备和驱动这两者之间又是如何联系起来的呢?此刻,必须抛出这样一个问题,先有设备还是先有驱动?在以前,先有的是设备,每一个要用的设备在计算机启动之前就已经插好了,插放在它应该在的位置上,然后计算机启动,然后操作系统开始初始化,总线开始扫原创 2011-07-11 12:26:12 · 5645 阅读 · 0 评论 -
《Linux那些事儿之我是USB》我是U盘(10)我是谁的他?
probe,disconnect,id_table,这三个元素中首先要登场亮相的是id_table,它是干什么用的呢?我们说过,一个设备只能绑定一个驱动,但驱动并非只能支持一种设备。道理很简单,比如我有两块U盘,那么我可以一起都插入,但是我只需要加载一个模块,usb-storag原创 2011-07-14 23:14:43 · 5984 阅读 · 2 评论 -
《Linux那些事儿之我是USB》我是U盘(11)从协议中来到协议中去
任何事物都有其要遵守的规矩。USB设备要遵循的就是USB协议。 不管是软件还是硬件,在设计的开始,总是要参考USB协议。怎么设计硬件?如何编写软件?不看USB协议,谁也不可能凭空想象出来。原创 2011-07-26 10:51:02 · 9216 阅读 · 4 评论 -
《Linux那些事儿之我是USB》我是U盘(12)梦开始的地方
对于整个usb-storage模块,usb_stor_init()函数是它的开始,然而,对于U盘驱动程序来说,它真正驱使U盘工作却是始于storage_probe()函数。两条平行线只要相交,就注定开始纠缠一生,不管中间是否短暂分离。USB Core为设备找到了适合它的驱动程原创 2011-09-18 22:57:59 · 8746 阅读 · 5 评论 -
《Linux那些事儿之我是USB》我是U盘(13)设备花名册
storage_probe这个函数挺有意思,总长度不足100行,但是干了许多事情,这就像足球场上的后腰,比如切尔西的马克莱莱,在场上并不起眼,但是却为整个团队做出了卓越的贡献。我们继续看storage_probe的代码:972 mutex_init(&(us->原创 2011-09-19 23:31:25 · 4843 阅读 · 0 评论 -
《Linux那些事儿之我是USB》我是U盘(14)冰冻三尺非一日之寒
罗马不是一天建成的。在让U盘工作之前,其实我们的驱动做了很多准备工作。我们继续跟着感觉走,storage_probe(),972行至975行,一系列的以init_*命名的函数在此刻被调用,这里涉及了一些锁机制,等待机制,不过只是初始化,暂且不理睬,到后面用到时再细说,不过请记原创 2011-09-21 22:58:16 · 7798 阅读 · 1 评论 -
《Linux那些事儿之我是USB》我是U盘(15)冬天来了,春天还会远吗?(一)
在整个usb-storage模块的代码中,其最灵魂的部分在一个叫做usb_stor_control_thread()的函数中,而那也自然是我们整个故事的高潮。这个函数的调用有一些特殊,是从usb_stor_acquire_resources()函数进入的,而后者我们即将遇到,它在原创 2011-09-25 22:03:16 · 7221 阅读 · 1 评论 -
《Linux那些事儿之我是USB》我是U盘(18)冬天来了,春天还会远吗?(四)
结束了get_device_info,我们继续沿着storage_probe一步一步地走下去。继续,这就是我们前面提到过的三个函数,get_transport、get_protocol和get_pipes。一旦结束了这三个函数,我们就将进入本故事的高潮部分。而在这之前,我们只能一原创 2011-10-10 21:49:01 · 6767 阅读 · 3 评论 -
《Linux那些事儿之我是USB》我是U盘(19)冬天来了,春天还会远吗?(五)
看完了get_transport()继续看get_protocol()函数和get_pipes()函数。仍然是来自drivers/usb/storage/usb.c中:672 static int get_protocol(struct us_data *us)673原创 2011-10-13 22:28:41 · 5220 阅读 · 2 评论 -
《Linux那些事儿之我是USB》我是U盘(37)迷雾重重的批量传输(六)
usb_stor_bulk_transfer_sglist()函数有一定的“蛊惑性”,我们前面说过,之所以采用sglist,就是为了提高传输效率。我们更知道,sg的目的就是让一堆不连续的buffers在一次DMA操作都传输出去。其实在USB的故事中,事情并非如此。不过如果你对USB Core里边的行为不关心的话,那就无所谓了。423行,424行,退出或者断链接,就不要传递数据。然后429行原创 2012-05-07 13:09:04 · 15922 阅读 · 0 评论