write的奥秘(1)

上传人:M****1 文档编号:502632965 上传时间:2023-08-04 格式:DOC 页数:16 大小:53KB
返回 下载 相关 举报
write的奥秘(1)_第1页
第1页 / 共16页
write的奥秘(1)_第2页
第2页 / 共16页
write的奥秘(1)_第3页
第3页 / 共16页
write的奥秘(1)_第4页
第4页 / 共16页
write的奥秘(1)_第5页
第5页 / 共16页
点击查看更多>>
资源描述

《write的奥秘(1)》由会员分享,可在线阅读,更多相关《write的奥秘(1)(16页珍藏版)》请在金锄头文库上搜索。

1、rie的奥秘 在Linux下我们在使用设备的时候,都会用到rite这个函数,通过这个函数我们可以象使用文件那样向设备传送数据。可是为什么用户使用wrte函数就可以把数据写到设备里面去,这个过程到底是怎么实现的呢? 这个奥秘就在于设备驱动程序的write实现中,这里我结合一些源代码来解释如何使得一个简简单单的writ函数能够完成向设备里面写数据的复杂过程。 这里的源代码主要来自两个地方。第一是oeilly出版的Linux device ivr中的实例,第二是LnuKen 2。2。14核心源代码。我只列出了其中相关部分的内容,如果读者有兴趣,也可以查阅其它源代码。不过我不是在讲解如何编写设备驱动程

2、序,所以不会对每一个细节都进行说明,再说有些地方我觉得自己还没有吃透。由于inx dvicede一书中的例子对于我们还是复杂了一些,我将其中的一个例程简化了一下.这个驱动程序支持这样一个设备:核心空间中的一个长度为1的数组buf1。我们可以通过用户程序open它,read它,wre它,coe它。这个设备的名字我称为shor_t.现在言归正传。对于一个设备,它可以在/dv下面存在一个对应的逻辑设备节点,这个节点以文件的形式存在,但它不是普通意义上的文件,它是设备文件,更确切的说,它是设备节点。这个节点是通过knod命令建立的,其中指定了主设备号和次设备号。主设备号表明了某一类设备,一般对应着确定

3、的驱动程序;次设备号一般是区分是标明不同属性,例如不同的使用方法,不同的位置,不同的操作。这个设备号是从pr/devices文件中获得的,所以一般是先有驱动程序在内核中,才有设备节点在目录中.这个设备号(特指主设备号)的主要作用,就是声明设备所使用的驱动程序。驱动程序和设备号是一一对应的,当你打开一个设备文件时,操作系统就已经知道这个设备所对应的驱动程序是哪一个了。这个”知道的过程后面就讲.我们再说说驱动程序的基本结构吧.这里我只介绍动态模块型驱动程序(就是我们使用inmo加载到核心中并使用rmmod卸载的那种),因为我只熟悉这种结构。模块化的驱动程序由两个函数是固定的:int iitmodu

4、le(voi) ;vodclenuoule(void)。前者在isod的时候执行,后者在rm的时候执行。nt_ndle在执行的时候,进行一些驱动程序初始化的工作,其中最主要的工作有三件:注册设备;申请O端口地址范围;申请中断RQ。这里和我们想知道的事情相关的只有注册设备。下面是一个典型的ini_mdule函数:int it_mdue(vid)int result = chk_regin(sotbs,1);/ 察看端口地址*/eqest_egi(shor_bae,1,short”); /* 申请端口地址*/rest regisecrde(sotmajo,”shrt, shr_fops); /*

5、注册设备*/result = rust_rq(hort_q, shorinterupt, _INTRUT, sr”,NULL); /*申请IRQ/retu 0;/ init_modle/上面这个函数我只保留了最重要的部分,其中最重要的函数是resul= gist_hrdev(sort_maor,shrt,ort_fo);这是一个驱动程序的精髓所在!当你执行inmo命令时,这个函数可以完成三件大事:第一,申请主设备号(hortajor),或者指定,或者动态分配;第二,在内核中注册设备的名字(hort”);第三,指定fops方法(&sort_fp)。其中所指定的fops方法就是我们对设备进行操作的

6、方法(例如ra,wrt,seek,di,opn,releas等),如何实现这些方法,是编写设备驱动程序大部分工作量所在。现在我们就要接触关键部分了如何实现ops方法。我们都知道,每一个文件都有一个fi的结构,在这个结构中有一个的结构体,这个结构体指明了能够对该文件进行的操作。下面是一个典型的结构:uct l_t(*llseek) (sruct file, lf_t, int);ssize_t (ed)(srutfe *,chr , et,lo_t*);siet (wite)(suct file , costchar ,size, of_t );in(*dir)(srt fl , vod*,fl

7、r_t);sne n (*pl) (stuct file, srct plaleruc *);int (ioctl)(stuc inoe *, strt fil,unsed int, uigndln);it (mmp)(struct file*,strucvm_ae_strut);n (op) (ruct node *, stuct file *);in (*lush) (struct file );int(*release) (structid *, suctfle );nt (snc) (uct fe , suctdntry );int(*fsync) (in, sruct fil , i

8、t);int (check_miahange) (kdv_t dev);it (realidate)(det de);nt(lck) (stuct file *,int,strct *);;我们可以看到它实际上就是许多文件操作的函数指针,其中就有wit,其它的我们就不去管它了。这个wre指针在实际的驱动程序中会以程序员所实现的函数名字出现,它指向程序员实现的设备wte操作函数.下面就是一个实际的例子,这个write函数可以向核心内存的一个数组里输入一个字符串。it short_rite (structne id, stct fe*fip, cost a buf,incont)it retv =

9、 cn;externnsigne char kbuf1;i(count0)coun=10;cpy_f_use(kb, buf, ount);returnretval;/* shorwrite /设备shr_t对应的ops方法是这样声明的:struct horfop ULL,/o_lse /short_rd,shor_write,ULL, /* shrt_radi /ULL, / shrt_pol NULL, *hort_ioctl NLL, srt_mmap /shorte,shrt_relse,LL, / short_fsc/NUL,/* sort_fnc / otingmre, fil w

10、ithNLs /;其中NLL的项目就是不提供这个功能。所以我们可以看出sot_t设备只提供了ead,write,oen,rlease功能。其中wr功能我们在上面已经实现了,具体的实现函数起名为shorti。这些函数就是真正对设备进行操作的函数,这就是驱动程序的一大好处:不管你实现的时候是多么的复杂,但对用户来看,就是那些常用的文件操作函数.但是我们可以看到,驱动程序里的wrte函数有四个参数,函数格式如下:shrt_rite (trctinde inode, strut il ilp, cont char uf, intoun)而用户程序中的函数只有三个参数,函数格式如下:we(in fd,

11、ha uf, int count)那他们两个是怎么联系在一起的呢?这就要靠操作系统核心中的函数ys_wre了,下面是nuxKerne 2。中ys_wrte中的源代码:aslnag ize_sys_wr(ungned int fd, const cha* bu, size_t cut)ssze_t ret;suctil file;stuc inode * iode;sizet (*wi)(struct fie*,cns ar , sze_t,of *);/ 指向驱动程序中的wrte函数的指针lc_kernel();ret = EBAF;fil = fget(fd);/通过文件描述符得到文件指针/

12、if (!ile)goto bad_file;f(!(fif_mode &FMO_WRITE)got out;ine =file-_dentry-d_inod; / 得到ide信息 /ret = ock_vriy_ae(FLK_VEIFYWRITE,inode, file, ile-f_pos,con);i(t)gtout;et = EINAL;if (!fil-fop | !(write =filefopwr)/ 将函数开始时声明的writ函数指针指向os方法中对应的wri函数 /goto ut;down(&inoeisem);ret wre(il, uf, cont, fiefos); 使

13、用驱动程序中的rite函数将数据输入设备,注意看,这里就是四个参数了/up(&ino-i_em);out:fpt(file);bad_file:nokkrnel();retr ret;我写了一个简单的程序来测试这个驱动程序,该程序源代码节选如下(该省的我都省了):in()int f,cunt=0;unsigncha buf10;fd=pen(dev/shortt”,O_RDWR);pi(input string:);scanf(s,bu);cuntstren(bu);if(count10)count=10;countwie(f,buf,cut);lose(fd);reur 1;现在我们就演示一下用户使用wrte函数将数据写到设备里面这个过程到底是怎么实现的:,inm

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号