分类: LINUX
2014-03-20 13:00:08
最近学习块设备驱动程序的编写,在网上发现一个题为“写一个块设备驱动“的教程,共包含15章,教程最先是在chinaunix论坛上发的,很多人的博客都转载了这组文章,是一个叫赵磊的大牛写的,拜读了一下,教程写得通俗易懂,很有收获。
本文对这组文章的内容进行了简要的概括,并附上每章的链接,当然,你google一下也能找到一大堆。
第一章内容概括:模块的编写,块设备的基础编程结构,gendisk及其request_queue的管理,简单块设备驱动的实现(初始化gendisk,实现request_queue的处理方法),对块设备进行格式化文件系统并使用。
链接1:%5Fustc/blog/item/9727723f780b50c57c1e7133.html
第二章内容概括:默认情况下,块设备的请求会经过内核IO调度器的处理,linux的IO调度器实现了anticipatory、cfq、deadline和noop四种管理算法,本章介绍了如何指定IO调度器的调度算法。
链接2:%5Fustc/blog/item/ba5d141107b24479cb80c43d.html
第三章内容概括:本章介绍如果绕过IO调度器这一层,使用blk_init_queue默认会使用__make_request作为request_queue的make request处理方法,而__make_request会使用IO调度器对请求进行合并处理。通过blk_queue_make_request初始化request_queue的make request方法,即可绕过IO调度器。
链接3:%5Fustc/blog/item/70026defd5abbf31adafd53e.html
第四章内容概括:对块设备进行分区,并引出确定块设备结构(磁头数,扇区数,柱面数等)的方法介绍。
链接4:%5Fustc/blog/item/8d10ca815aa9eddfbd3e1e3f.html
第五章内容概括:实现了gendisk的block_device_operations结构的getgeo方法,该方法用于获取块设备的结构信息,在该结构中需要对一个hd_geometry的sectors,heads,cylinders字段进行赋值。
链接6: %5Fustc/blog/item/8fb43b16435e5b56f2de3238.html
第六章内容概括:介绍如何使用基树来组织虚拟块设备的数据,基树是内核用来管理页高速缓存的数据结构。
链接6:%5Fustc/blog/item/9685c659a588202d2934f039.html
第七章内容概括:介绍了内存管理方面的知识,包括页的申请,释放等。修改第六章的代码,使用一次申请4个连续的页的方法来减少碎片,并通过观察/proc/buddyinfo来说明伙伴系统管理页的方法。
链接7:%5Fustc/blog/item/e8aeea0820a1e9920b7b823b.html
第八章内容概括:使用模块参数向块设备驱动传递设备大小,由于模块参数不支持64位数,故传递字符串(16M,1T),再进行解析。
链接8: 5Fustc/blog/item/4e1ca924550f2d34c995593b.html
第九章内容概括:考虑到设备驱动的安全性,其申请的数据空间可能包含有用的数据,在__get_free_page是加上__GFP_ZERO的标志,在申请到页后对其清零。另外对程序中出现的一些魔数,使用相应的宏代替。
链接9:5Fustc/blog/item/b973770049093916738b6504.html
第十,十一,十二章内容概括:考虑到__get_free_page只能从低端内存获取页,因高端内存没有固定映射的线性地址,故块设备驱动使用的内存被限制在896M一下,本章使用alloc_page来分配page描述符,使用kmap来映射页获取一个线性地址来使用,这样就能从高端内存获取页。在第10章的基础上,将make_request的方法重写,将实际拷贝数据的代码与其它的逻辑处理独立开来,而不是在一个函数实现,这样使得代码的条理更清晰。通过在申请页时指定__GFP_HIGHMEM优先从高端内存获取页。
链接10: %5Fustc/blog/item/395f513688698d360b55a906.html
链接11: %5Fustc/blog/item/1dcf92a8927579b6ca130c06.html
链接12: %5Fustc/blog/item/0b428873cb7f471b8601b007.html
第十三章内容概括:改进了free_mem方法,之前对分配的每个页,使用radix_tree_lookup查找到页描述符,然后将其从基树移除,释放这个页。可通过radix_tree_gang_lookup一次查找一组连续的页,然后将它们从基树上移除,释放这些页的空间。
链接13: %5Fustc/blog/item/910daaf490013fe87709d700.html
第十四章内容概括:实现内存延迟分配,即像真正的页高速缓存那样,只有往上面写数据的时候才会分配页,这时先要判断radix_tree_lookup的结果,如果为空,说明索引对应的页还没有分配过,需先分配空间。
链接14: %5Fustc/blog/item/02b9cb2227e7d4a34723e801.html
第十五章内容概括:在代码中对临界区进行加锁保护。
链接15: http://blog.csdn.net/cnctloveyu/archive/2009/06/16/4274544.aspx