《Linux设备驱动程序》精华笔记
Linux设备驱动程序学习(1)-字符设备驱动程序Linux设备驱动程序学习(0)-Hello,world!模块Linux设备驱动程序学习(2)-调试技术Linux设备驱动程序学习(3)-并发和竞态Linux设备驱动程序学习(4)-高级字符驱动程序操作[(1)loct|and||seek]Linux设备驱动程序学习(5)-高级字符驱动程序操作[(2)阻塞型I/O和休眠]Linux设备驱动程序学习(6)-高级字符驱动程序操作[(3)设备文件的访问控制]Linux设备驱动程序学习(7)-内核的数据类型Linux设备驱动程序学习(9)-与硬件通信Linux设备驱动程序学习(8)-分Linux设备驱动程序学习(1)字符设备驱动程序-imw设备驱动程序- Tekkaman nn些重要的数据结构大邹分基本的驱动程序操作涉及及到三个重要的内棱数据绐构,分别是 file operations、file和 linde,它们的定义都在< linux/fsh>。字符设备的注册内核内部使用 struct cdev结构来表示字符设备。在内核调用设备的操作之前,必须分配并注册一个或多个 truct cdev。代码应包含,它定义了 struct cdev以及与其相关的一些辅助函数注册一个独立的cdev没备的基本过程如下1、为 struct cdev分配空间(如果已经特 struct cdev入到自己的设备的特定结构体中,并分配了空间,这步略过!)struct cdev *my cdev cdev_ alloc():2、初始化 struct cdevvoid cdev_init(struct cdev *cdev. const struct file operations"faps)3、初始化 cdev. ownerdev owner E THIS MODULE4、cdev设置完成,通知内核 struct cdev的信息(在执行这步之前必须确定你对 struct cdev的以上设置已经完成!)int cdev addt struct cdev'p, dev t dev, unsigned count)从系统中移除一个字符设各: void cdev del( struct cdev*p)以下是sc山中的初始化代码(之前已经为 struct scull dev分配了空间):+ Eet ap che chat dev structure for thLs deviceS七⊥Cv⊥以岛C口118 etup cdev!aE山Cscu11de"ce,⊥n且dexint err, devne MKDEv(scull_ma orr scull_ninor+dex)idew__init(&dew->cdev, scull_)i/这句可以省略,在 cdev ir it中已绎做过adev_add (sdev->这步值得注意+f cerrprintk(KERN_NOTICE Error sd adding EculIid', err, index)i四、scul模型的内存使用hp:/ olce is.eu:4474/ showart. pha?id-44289[2009-8-277:54:52Lin凵x设眚驱动程序学习(1)-字符设备驱动程序- Linux设备驱程序- Tekkaman NniaScull deviced*dsa指向一个指针数组(量子集truct scull gset率data指向第一个3cm11_ase加零soll gsetDataQuattLinux设备驱动程序学习(1)字符设备驱动程序-imw设备驱动程序- Tekkaman nnScull devicevid**dta指向一个指针纹组〔量予集strust seul9雪电t军dat向第个3 ull_gsetScull etScull gsctDataDataQuatum卡 Quanturn指向QuatumQuantum字节大小的内面tumOutturnQuatumQuantum以下是scu模型的结构体:t Representation af soull cantu set.astruct scull_ qsetvoid *tdataa七ue2cu11_qae*nets工CLsc山11devstruct scull qaet *datai / FaInter to flrat quantun aetnt quansun;/* the current guantum aize*/nt 4set:/w Lhi current arcey slze./unsigned long size; / amount cf data stored here *Auns Igned int access_ key i / used by seuliuid and scullprlwstruct semaphore sem; y* autual exclusion semaphore./truct cdevcdev;Char sev上组工C上山工escu|驱动程序引入了两个Lnux内核中用于内存管理的核心函数,它们的定义都在:void *km alloc( size t size, int flags)void kfree(void*ptr)以下是sc山l模块中的一个放整个数据区的函数(类似清零),将在scu以写方式打开和 scull cleanup_ module中被调用:int scull trim(struct scull dev *dev)Lnt dset=dev-qset;/+量了中了的个数/fcr(dptx=dey->ata;ptx;dptr=next)(/*环su1aa个数次,直到山pr为NUL为止,+/dpta)Ifor(⊥=0;1cata1]);/·其中一个量了的空间”hp:/ olce is.eu:4474/ showart. pha?id-44289[2009-8-277:54:52i设奋驱动程序学习()字符设备动程序,im设备动序- Tekkaman Nniakfre(dptr->aaab;释放当前的 scull se的量了集的空间dptx->data=MU;}·释放一个 scull set中的void”·data指针”next=dptx->next.;/”准备下个 scull set的指针”FEree{dptx);1·放当前 scul set”dey->si2=0;”当前 soull device所存的效据为0字节*dev> cantu:t-8cu1 l__quantum;/划始化一个量了的大小LinLI设备驱动程岸学习(1)-字符设备驱动程序-1nux设备驱动程序- Tekkaman n nikfree(dptr->data};/”释放当前的 scull set的量了集的空间ptr-> data=Mmt;}释一个 still set中wnid…data指针”next=dptr->next;/”在帝下个 scull set的指针”/kee(dptx};/·释放当前 N scull set”dev->sz=p/当前的 scll device所存的数据为0字节*dev-> c1-1antLitL=scu11 opaqUe;/”初始化一个量了的大小”dev->q9et=scu11qset;"初始化一个量子中量了的个数”dew->data=Muu;"释放当前的 scull deviceifjstrLcl scull gset,data指”return dF以下是sC山模块中的一个沿链表前行得到正确 scull set指针的函数,将在read和 write方法咔被调用:struct scull_ qset *scull_follow (struct acul_dew +dev, int nstrucT sculL qset *qs= dev>data;R110Cate王1E日pe上 aLy 1 need be⊥E(!qs= dev->data= kmalloc(sizeof (stuct scull gset I, GEP_ KERNEL)FIE (CB ==NULLurr WLL; t Newer nin白”/itemset(qe, 0, sizeof(struct soull gset))Fhert Ec11ae1⊥a上whle (n--) I⊥f《!qs->next)gs->next kmalloc(sizeof(struct scull_gset), GEP_KERNEL)⊥f(qs->next==U)return NULL;/+ Never mlndm岛eL{日>next,0rs⊥2e(rue自u119些et))s=0s-2neXtpcontinue其实这个函数的实质是:如果已经存在这个 scull set,就返回这个 scull set的指针。如果不存在这个 scull set,一边沿链表为 scull set分配空间一边沿链表前行,直到所需要的 scull set被分配到空间并初始化为止,就返回这个 scull set的指针。五、。pen和re1easeopen方法提供给驱动程序以初始化的能力,为以后的操作作准备。应完成的工作如下(1)检查该备特定的错误(如设备未就绪或硬件问题2)如果该备是首次打开,则对其进行初始化;(3)如有必要,豇新t。p指针;(4)分配并填写置于filp- private_ data里数据结构。htlp: //bleng.chin aur ix. etul/34474/shewart Ph zid=+04280[2009-8-277: 54: 5 21u设备軍动程序学习(1)-字符设备驱动程序-inux设备驱动程序- Tekkaman Ninja而根据scu实际情况,他的open函数只要完成第四步(将初始化过的 struct scull dey dev的指针传递到f|lp-> private_ data里,以备后用)就好了,所以pen函数很筒单,但是其中用到了定义在中的 container of宏,源码如下fcefine co tainer_of(ptr, =yDe, member )(1const tyoeoft ((type *)0)->member(tvpe *)((char* nptr-oifsetof(typer member):I其家队源码可以希出,其作用就是·通江指tr,获得包含ptr所指向数据(是 member结构体的ype特构体的指针,即是用指针得到Lux设备动程序学习(1)字符设备驱动程序-Lnux设备驱动程序- Tekkarna Ninj=而根据scu实际情况,他的ppen函数只要完成第阿步(将初始化过 struct scull dev dey的指针传递到f|p-> private data里,以备后用)就好了,所以open函数恨单。但是其中用到了定义在lnux/ kernel.h>中的 container of:,源码如下:tdefine container_,eber)((canst typeof(((type *>0)->member )+ mptr=(pt)i[tvpe *)((char *) mpt.r -(typer member )i1其实从源码可以看出,其作用就是:通过指针pr,获得包含pt所指向数据(是 member结构体的type结构体的指针。即是用指针行到另外一个指针。release法提供释放内存,关团设备的功能。应完成的工作如下:(1)放由oren分的、保存在e-> private data中的所有内容;(2)在最后一次关闭操作时关闭设备由于前面定义了scu是一个全局且持久的内存区,所以他的 release什么都不徽六、read和wrteread和 write方法的主要作用就是实现内核与用户空间之间的教据拷贝。因为rux的内核空门和用广空间隔离的,所以要实现数据考贝就必须使用在中定义的unsigned long copy_.o_user, void user *LCrpoid t froruna⊥qned1 ong count);unsigned long copy_From_Lserivoid +Loconst. void user from,unsigned long count )i而低得一提的是以上两个函数和py_from_ user (to, from, n)(mencpy (to,(vbid force *i fror, n), 0)fcefine__copy_to_user(tor Ersmr n) (re coy((void force *)to, from, n)r 0)之间的关系:通过码可知,前者调用后者,但前者在调用前对用户空间指针进行了检查。至于read和 write的具函数上较简单,就在实验中验证好了。七、模块实验这次模块实验的使用是友蓍之臂SBC2440V4,使用Lnux26,222内核。模块程序链接:scu块凘猩序模块测试程序链接:駃迦淢程序测试结果:量了大小为6[Tekkaman2440@SBC2440 V4]* cd /lib/ modules/ [Tekkaman2440@SBC2440v4]#insmod scull. koscull quantum- 6[Tekkaman2440@SBC2 440V4] cat /praG/ devicesCharacter devices.1 memhup: //blog chinar ix. et'u134474/showartphp?id-404280[2009-8-277: 54: 52Lix设备惠动程字学习(1)字符设驱动程序-imux设驱动程序 Te ketran nin运2 ptys ttypd/dev/ve/ott4 tty s5/dev/tly5/dev/c。nsoe5/dev/ pmxIi山设备动程学习(1)字符设驱动程序-Linx设餐驱动程序- Tekkaman Ninj2 ptys ttypd/dev/vc/04 ttys5/dev/ti5/dev/console5/dev/ ptm1a misc13 input14 sound81wd色a4nuX89 12093 mtc116 alsa128 ptm136 pts180 usb189 usb device204 5302410 serial53 usb endpoint254 rtcBlock dav ces1 ram disk2E6 rfdF loop31 mtablock93 nftl93 infl19 mmcTekkam an2440@SBC2440V4]* mknod-m 666 scullOc 2520Tekkaman2440@SBC2440V4mknod-m 666 scull C 252 1[Tekkaman2440@SBC2 44014] mknod -m 666 scull2 c 252 2[Tekkam an2440@SBC2440V4] mknod -m 666 scull C 252 3肩动测试科序[Tekkam an2440@SBC2 440V4]- soull testwrite error i code= 6write error l code=6write error I code= 6write okI code 2read errorI code= 6read error code= 6read error code= 6read ok code= 2[0]=0[1]=1[2]=2[3]=3【4]=4[5]=5[6]=6[7]=7[8]=8[9]=9http://blog.chinaunix.et/ul/34474/showartphp?id-4042802009-8-277:54:521Lix设备惠动程字学习(1)字符设备驱动程序-imux设驱动程序 Te karat nin运[10]=10[11]=11[12]=12[13=1314=14[15]=15[1E]=16[17]=17[18]=1819]=19改变量了大小为歌认值4000ITekkaman2440(@SBC2440V4]#cd /lb/modulesITekkaman2440SBC2440V4]# rmmod scullI Tekkaman 2440@SBC2440V4]# insm od scull. koIi山设备动程学习(1)字符设驱动程序-Linx设餐驱动程序- Tekkaman Ninj10]=10[11]=11[12]=12[13]=13:141]=14[15]=15[15」=16L1/]=1118=1819]=19改变量了大小为款认值4000I Tekkaman2440(@SBC2440V4# cd/lb/ modules.I Tekkaman 2440@SBC2440V4]#rm mod seullI Tekkaman 2440 @SBC2440V4]# insm od soull, ko启动测试序ITekkaman2440@SBC2440V4]#. /scull testwrite ok code= 20read ok! code= 200]=0[1l=1[2]=2[3]=3[4]=4l5|=b[E|=6[/」=1[B]=8[⑨」=910]=10[1=11[12]=12[1=13[14]=14115]=15[6]=16[17]=17[18=18[19]=19ITekkaman2440@SBC2440V4]#改变量了大小为6,虽了集大小为2ITekkaman2440@SBC2440V4]# cd/lib/modules/ITekkaman2440@SBC2440V4]# rm mod scull[Tekkaman2440SBC2440V4]# insmod scull. ko scull quantu=6 scull_ qset 2后动测试序ITekkaman2440@SBC2440V4]#.scull_ testwrite error code arite error code= 6write errorI code= 6write okl code 2read errorI code= 6ead error code= 6read error code= 6d k code= 20]=0[1=1[2]=2[3]=3[4]=45=5[el=6[7]=7[8]=8[9]=910]=10[1]=11[12]=12[1al=13[14]=1415]=15[6]=16[17]]=17[18=18[19]=19实验不仅測试了模块的读写能力,还测试了量子读写是否有效。hitp / /blog. chinaunix. et/ul/34474 showart php?i=4042802009-8-277: 541imx设耶动程序学习(0)- HelL, world!横块linn投缶动程序,ckm=nNmjLinux设备动程序学习(0)Hello w or|d!模块个学习Lu备事动序都会能到的第一个例程⊥ gluteinclude liNux/nodule. 1%H日L=c4sua1 BS/GEL"1katie int relle init (roilPrint (RERK MBRT Hello, Tehkeann Ninga I n"yir出rD胜t已vidh11ae主t{ wDidprints(RERF_ MERT"Goodbye Tekkamen Ninja I \ n Iave Lt tuk I Lave MRM Itve Kele 1\n"J:module init《heL1c⊥tmodule exit the LIc exit. F我将其复到我工作匚录,并編写了一个单 Makefile文件KERNELDIR -/hame/takkaman wacking/SBC2440/1irux-26.22.2t The current directory is passed to sue=makes as arguerINETMTD-R -/ore,tekkaman/warking rot fa/liai'inddulesCROSE-COHPILP-s(Cs工E}出obj-o: he -.o3 IMMKE)-C31EERNELDIRI M-3IEWD modulesmodu1est上a12cp helLo. ko S( ERYClearlr-·rer,★,巴md青.k,PHW: nodule当od台:ia】2C1ea门说实话,以上是食参了nux没驱动程序(窜3版)净的 Makefile诉码修改得来的。我对 Makefile是很了解,是该好好学习学习了后就是 make mo u3, make modules inst al。[root@Tekkam an-Ninja Helloworld]* make modulesmake-C/hom aftakkaman/working/'sBC2440rlinux-2-6 22.2 M-thorma'takkam an working/ Linux driver Helloworld modulesmake[ 1]: Enter ing directory /home/lekkam an/wrorking'SBG2440/ linux-2..22. 2Building nodules, stage 2MODPOST 1 modulescC /home tekkaman/working Linuxdriver Hallow orld hello. mod. oLD [M /homartakkaman working/ Linuxdriver/ Hellcworld/hello. komake[ 1]: Leaving directory/hom a/tekkan an/ worki 1g sB C2440/linux..22.2roat@Tek kam an-Ninja Helloworld]* make modules_ installcp helio. ko/ham e te(11)所有模块代码都应该指定所使用的许可证:MODULE L- CENSE L"Eual ERU/GPL">i还有可途的其触消述性定义:BODULE AOTECR("IiMDDE_ DESCELPTT("”};MODULE VERSION ["")3MDDR品LIM("}MODULE_ DEVICE_BBLE (")i上述u声明忘惯上放在文件最后。(12)初始化和关闭初始化的实乐定义通常妇下:static nt ic3 t inicia1⊥t主 r fncA:EI(vc主+婚化代码bttp/Ecg chir aurEx tte u134474abowiarLphP'sxd=4072/2..277: 5543]mux设金驱动程片学习to)-Helo,wol!横块-lnx舍驱动序1 karnan Niniamodule itit 4inLEislizat iot EuretiocL清除函数的实际定义通常如下static int. exit cleanup function(waidy除代严
下载地址
用户评论
就是自己整理的一些读书笔记而已
自己整理的,但页面不清晰,排版有问题,但内容不错。
不是特别清晰的资源
太垃圾了!!完全就是糊弄人的,还需要这么多的积分!就是纯粹弄了个东西赚积分的!!千万别下载
书很不错,但是有些模糊,不是很清晰~谢谢!