| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 876 人关注过本帖
标题:[转载]Linux 那些事儿之我是U 盘
只看楼主 加入收藏
百年不亮
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:789
专家分:0
注 册:2006-4-14
结帖率:100%
收藏
 问题点数:0 回复次数:4 
[转载]Linux 那些事儿之我是U 盘
转载此文没有别的意思,只是为了让刚学编程的C初学者知道,C语言除了考二级和做谭老头的加减乘除题之外还有别的用处.

摘要
2005 年6 月,复旦大学微电子系本科毕业答辩上,老师问我:请你用一句话介绍一下usb 技
术.我回了一句:老师,你有病吧,要能用一句话介绍我还费这么大劲写这么长的文章干嘛?
关键词:Linux, Kernel, 2.6, bus, usb, device driver, mass storage, scsi,
urb, bulk, control, host, pipe, command, 林志玲
-------------------------------------------------------------------------------------------------
我不喜欢躺在床上听,而是喜欢一边听一边做
点别的事情,于是心血来潮的决定,写点文字吧,听着电波里别人分享心情,不妨也用文字来记
录自己的心情吧.
我首先想到的是写一些和Linux 相关的文字.事实上我并不喜欢Linux,学习Linux 完全是一
种无奈,工作中要用,迫于生计,不得不去学习,而学习Linux 的过程中唯一让我觉得还有些乐
趣的是当遇到问题的时候可以去网上问去网上查,很多人写了很多文档可以让我们这些菜鸟
们参考学习,这样才让我们在工作中走了很多弯路.挺感谢那些分享自己知识的人.碰巧最近
3
我也看了点冬冬,并且这些冬冬在网上的资料也比较少,所以我想我不妨也把自己那一夜的
收获写出来,或许以后也能给别人提供一些帮助,想想也是,整个Linux 社区不正是这样吗,像
陈奕迅唱的那样,”把一个人的温暖转移到另一个人的胸膛”.
我要写的是Linux 设备驱动程序相关的,主要分析的是Linux 中与U 盘相关的那部分代码.
过去也没有看过,但是今年4 月底的某一天,一个偶然的原因,我一时冲动就看了一遍.我们几
个同学在人大附近打麻将,打到夜深了,因为我们几人人住的位置都离得挺远的,各自回去都
得打车,于是决定不如去权金城开个房间,晚上就睡那得了.在权金城洗浴中心,和几个同学洗
浴过后,有人去按摩了,而我和另一个人则留在了房间里,无聊中,那位哥们见我带了电脑,说
他有部A 片,很不错,不是很大,所以他存在U 盘里的,他还挺逗的说这是2008 年北京奥运会
指定A 片,问我有没有兴趣,这还用问,当然有兴趣了,于是立马打开电脑,插入u 盘,然后不一
会我就傻了,因为我的电脑根本就不能识别U盘,首先我的电脑比较旧,装的是双系统,一个是
Win 98,这个没办法,没有U 盘驱动,另一个是Linux,2.6 的内核,按理应该是支持U 盘的,
问题是实际情况却是我没有看到U 盘,/dev/目录下面根本没有这么一个盘符,于是我没办法
了,一脸沮丧,而同学在旁边自然表示出了对Linux 很鄙视的神情.
过了一会,他去看电视了,正好有英超,我却没有心情看电视,想想就觉得奇怪,怎么会不能使
用U 盘呢,这不可能啊,一定是我自己对Linux 下面的一些冬冬没有弄清楚,于是我决定好好
看看问题到底出在哪,记得当时看了一下/var/log/messages 这个日志文件里边好像记录
了一些信息,感觉像是一些错误信息,但是看不明白它到底在说什么.同学开始劝我,算了算了,
改天再看吧,这话我可不愿意听,不是说Linux 内核源代码是公开的吗,大不了看看源代码,搞
清楚工作原理了还怕问题不能解决?无非就是一些C 代码而已,好歹哥们也是认真学过谭浩
强大哥那本C 程序设计的.而且当初那本书课后习题老师基本上都让我们做了,虽说是参考
了那本习题解答的书,可就算写代码不行,读代码还是没问题吧,语法什么的基本上还是很清
楚的,什么判断结构循环结构,包括goto 语句,还是记得的.
所以我就开始看了,正所谓梦想有多远,就能走多远.以前我只是玩CS 玩仙剑的时候能够整
晚整晚不睡,但那个晚上,为了告诉我同学,Linux 下也能看A 片,Linux 下遇到问题更适合自
己解决,我愣是从一点看到快天亮,终于把drivers/usb/storage/目录下面一万余行的代码
给看了一遍.当然没有看得太仔细,但是很显然把整个原理搞清楚了,问题也很快得以解决.
所以此刻,我整理了一下思路,决定把那晚看的冬冬用文字记录下来.也算为了纪念那个不寻
常的夜晚吧.不过我估计这个篇幅不会短,因为光那一万余行的代码贴出来就得占许许多多
页了,所以这件事情也许会占用我不少时间,然而,还好,每晚有北京不眠夜的陪伴,而且,也许
当我把心思投入到写这个故事的时候,能够把那些压力那些烦恼那种孤独那种郁闷以及那种
对生活的绝望给暂时忘记些许...............
原文地址:http://www.newsmth.net/att.php?p.299.44271.374.pdf
搜索更多相关主题的帖子: Linux 
2007-08-13 11:46
百年不亮
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:789
专家分:0
注 册:2006-4-14
收藏
得分:0 
再转一段:
[QUOTE]变态的模块机制
有一种感动,叫泪流满面,有一种机制,叫模块机制,十月革命一声炮响,给Linux 送来了模块机制.
显然,这种模块机制给那些Linux 的发烧友们带来了方便,因为模块机制意味着人们可以把庞大
的Linux 内核划分为许许多多个小的模块,对于编写设备驱动程序的那帮家伙来说,从此以后他
们可以编写设备驱动程序却不需要把她编译进内核,不用reboot 机器,她只是一个模块,当你需
要她的时候,你可以把她抱入怀中(insmod),当你不再需要她的时候,你可以把她一脚踢开,甚至,
你可以对她咆哮:"滚吧,贱人!"(rmmod).她不能成为你的手足,只能算你的衣服.
也许在现实世界里不会这样,但是在Linux 的虚拟世界里,确实可以是如此,time and time
again,我问自己,模块是否就像现实生活中的妓女一样呢?Linux 内核是嫖客,当他需要这个模块
的时候,他就把人家揽入怀中,当他不需要人家的时候,就把别人踢开,而且,模块总是能够逆来顺
受,尽管Linux 内核会一次次抛弃她,但是每当Linux 内核再次需要她的时候,当内核再次执行
insmod 的时候,模块依然会尽自己的能力去取悦内核,这是否太可悲了些!记得孔子曾经说过,读
懂Linux内核代码不难,难得是读懂Linux内核代码背后的哲学!难道这就是传说中的藏在Linux
代码背后的哲学!天哪!
抛开这见鬼的哲学吧.让我们从一个伟大的例子去认识模块.这就是传说中的"Hello World!",这
个梦幻般的名字我们看过无数次了,每一次她出现在眼前,就意味着我们开始接触一种新的计算
机语言了,或者,如此刻,开始描述一个新的故事.
请看下面这段代码,她就是Linux 下的一个最简单的模块.当你安装这个模块的时候,她会用她
特有的语言向你表白,"Hello,world!",千真万确,她没有说"Honey,I love you!",虽然,她可以这
7
么说,如果你要求她这么说.而后来你卸载了这个模块,你无情抛弃了她,她很伤心,她很绝望,但她
没有抱怨,她只是淡淡地说,"Goodbye,cruel world!"(再见,残酷的世界!)
++++++++++++++++++hello.c++++++++++++++++++++
1 #include <linux/init.h> /* Needed for the macros */
2 #include <linux/module.h> /* Needed for all modules */
3 MODULE_LICENSE("Dual BSD/GPL");
4 MODULE_AUTHOR("fudan_abc");
5
6 static int __init hello_init(void)
7 {
8 printk(KERN_ALERT "Hello, world!\n");
9 return 0;
10 }
11
12 static void __exit hello_exit(void)
13 {
14 printk(KERN_ALERT "Goodbye, cruel world\n");
15 }
16
17 module_init(hello_init);
18 module_exit(hello_exit);
++++++++++++++++++++++++++++++++++++++++++++++++
你需要使用module_init()和module_exit(),你可以称她们为函数,不过实际上她们是一些
宏(macro),现在你可以不用去知道她们背后的故事,只需要知道,在Linux Kernel 2.6 的世界里,
你写的任何一个模块都需要使用她们来初始化或退出,或者说注册以及后来的注销.当你用
module_[/QUOTE]
2007-08-13 11:48
百年不亮
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:789
专家分:0
注 册:2006-4-14
收藏
得分:0 
楼下的楼下说除了hello world什么都没说,要注意这里只是选取部分转载,1楼的主题贴结尾已经给了原文地址,文章很长,估计这里没有人有兴趣完整看一遍,选几段贴出来只是告诉不了解linux的人,学完C以后可以去看Linux源码,通读源码是成为真正意义上的hacker级程序员的前提.
有人嫌少就再贴一段:
想到达明天现在就要启程
既然知道了怎么编写一个模块,那么编写设备驱动程序自然也就不难了.我相信,每一个会写模块
的人都不会觉得写设备驱动有困难.对自己行不行不确定的话,可以去问一下葛优,他准说:"(神州
行),我看行."
真的,我没说假话.写驱动不是什么难事,你完全可以很自信的说,你已经可以写Device Driver 了.
对,没错,飘柔,就这么自信.
前面说了每一个模块都是以module_init 开始,以module_exit 结束,那么我们就来看一下U
盘的驱动的这个模块.在茫茫人海中,我们很容易找到这个文件:drivers/usb/storage/usb.c,
在这个文件中又不难发现下面这段:
/****************************************************************
*******
1056 * Initialization and registration
1057 **********************************************************
*************/
1058
1059 static int __init usb_stor_init(void)
1060 {
1061 int retval;
1062 printk(KERN_INFO "Initializing USB Mass Storage driver...\n");
1063
1064 /* register the driver, return usb_register return code if error */
1065 retval = usb_register(&usb_storage_driver);
1066 if (retval == 0)
1067 printk(KERN_INFO "USB Mass Storage support registered.\n");
1068
1069 return retval;
1070 }
1071
1072 static void __exit usb_stor_exit(void)
1073 {
1074 US_DEBUGP("usb_stor_exit() called\n");
1075
1076 /* Deregister the driver
1077 * This will cause disconnect() to be called for each
1078 * attached unit
1079 */
1080 US_DEBUGP("-- calling usb_deregister()\n");
1081 usb_deregister(&usb_storage_driver) ;
1082 }
1083
10
1084 module_init(usb_stor_init);
1085 module_exit(usb_stor_exit);
其实,module_init/module_exit 只是一个宏,通常写模块的人为了彰显自己的个性,会给自
己的初始化函数和注销函数另外起个名字,比如这里module_init(usb_stor_init)以及
module_exit(usb_stor_exit)实际上就是告诉这个世界,真正的函数是usb_stor_init 和
usb_stor_exit.这种伎俩在Linux 内核代码中屡见不鲜.见多了也就不必大惊小怪了,天要下雨
娘要嫁人,随她去吧.我们下面当然就从usb_stor_init 正式开始我们的探索之旅.
外面的世界很精彩
看代码之前,我曾经认真的思考过这么一个问题,我需要关注的仅仅是drivers/usb/storage/目
录下面那相关的3000 多行代码吗?就是这样几个文件就能让一个个不同的U盘在Linux 下面工
作起来吗? 像一开始那样把这个目录比作一个小城的话,也许,城里的月光很漂亮,她能够把人的
梦照亮,能够温暖人的心房.但我们真的就能厮守在这个城里,一生一世吗?
很不幸,问题远不是这样简单.外面的世界很精彩,作为U 盘,她需要与usb core 打交道,需要与
scsi core 打交道,需要与内存管理单元打交道,还有内核中许许多多其它模块打交道.外面的世界
很大,远比我们想象的大.
什么是usb core?她负责实现一些核心的功能,为别的设备驱动程序提供服务,比如申请内存,比
如实现一些所有的设备都会需要的公共的函数,事实上,在usb 的世界里,一个普通的设备要正常
的工作,除了要有设备本身以外,还需要有一个叫做控制器的冬冬,老外把它叫做host controller,
和这个控制器相连接在一起的有另一个咚咚,她叫root hub,hub 我们应该不会陌生,在大学里,
有的宿舍里网口有限,但是我们这一代人上大学基本上是每人一台电脑,所以网口不够,于是有人
会使用hub,让多个人共用一个网口,这是以太网上的hub,而usb 的世界里同样有hub,其实原
理是一样的,任何支持usb 的电脑不会说只允许你只能一个时刻使用一个usb 设备,比如你插入
了u 盘,你同样还可以插入usb 键盘,还可以再插一个usb 鼠标,因为你会发现你的电脑里并不只
是一个usb 接口.这些口实际上就是所谓的hub 口.而现实中经常是让一个usb 控制器和一个
hub 绑定在一起,专业一点说叫集成,而这个hub 也被称作root hub,换言之,和usb 控制器绑定
在一起的hub就是系统中最根本的hub,其它的hub可以连接到她这里,然后可以延伸出去,外接
别的设备,当然也可以不用别的hub,让usb 设备直接接到root hub 上.hub 干嘛用的我们知道
了,那么usb host controller 本身是干什么用的呢?controller,控制器,顾名思义,用于控制,控
制什么,控制所有的usb 设备的通信.通常计算机的cpu 并不是直接和usb 设备打交道,而是和控
制器打交道,他要对设备做什么,他会告诉控制器,而不是直接把指令发给设备,然后控制器再去负
责处理这件事情,他会去指挥设备执行命令,而cpu 就不用管剩下的事情,他还是该干嘛干嘛去,
控制器替他去完成剩下的事情,事情办完了再通知cpu.否则让cpu 去盯着每一个设备做每一件
事情,那是不现实的,那就好比让一个学院的院长去盯着我们每一个本科生上课,去管理我们的出
勤,只能说,不现实.所以我们就被分成了几个系,通常院长有什么指示直接跟各系领导说就可以了,
如果他要和三个系主任说事情,他即使不把三个人都召集起来开个会,也可以给三个人各打一个
电话,打完电话他就忙他自己的事情去了,比如去和他带的女硕士风花雪月.而三个系主任就会去
安排下面的人去执行具体的任务,完了之后他们就会像院长汇报.

[此贴子已经被作者于2007-8-13 19:42:08编辑过]

2007-08-13 11:53
nwpu063417
Rank: 3Rank: 3
等 级:论坛游民
威 望:8
帖 子:428
专家分:28
注 册:2007-5-11
收藏
得分:0 

给朵鲜花

挺好的,就是看不太懂呀


2007-08-13 16:53
大宝子
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2006-11-28
收藏
得分:0 
基本上是啥也没说,后面的那个程序就是Hello word!的儿子
不过那个2008指定A片听起来不错
2007-08-13 18:55
快速回复:[转载]Linux 那些事儿之我是U 盘
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017086 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved