现在的位置: 首页 >> 操作系统 >> FreeBSD >> FreeBSD 核心 (2)
添加时间:2005-8-21 来源:网教中国 作者:
FreeBSD 核心 (2)

@sys/uio.h)登记进程指定的buffer的位置和长度。
执行read()后,vn_read()向struct file设定登记的文件的读写位置,然后调用VOP_READ()。
根据读出来的byte数,读写位置相应增加。
VOP_READ()的call routine则是与v-node有关,就象下图一样。

vn_read()
文字型/块型 |
/------------------
| | file/directory
spec_read() ---------ffs_read()-------VOP_READ()
block型 | |
/---------------|char型 |
bread() device driver bread()
| |
spec_strategy() ---------------ufs_strategy() --VOP_STRATEGY()
| | |
| | |
device driver spec_strategy() -------------/
|
|
device driver


。普通的file/directory
调用ffs_read()(@ufs/ufs/ufs_readwrite.c)。对应指定的读写位置,计算block
的位置,然后用bread()读出来。读出来的数据送到进程所准备的缓冲区。从bread()
传递过来的block并不是物理block的位置,而是把file作为block列的一个理论值。
从理论块到物理块的变换由VOP_STARATEGY()完成。也就是说,ufs_strategy()先把
文件内位置转化为物理block位置,然后从v-node记录的i-node把表示物理设备的
v-node 去出来,这个VOP_STRATEGY就调用spec()(@miscfs/specfs/spec_vnops.c)
让它进行输入要求。
。特殊设备文件
通过调用spec_read()(@miscfs/specfs/spec_vnops.c),把它分为文字型和块型两类。
文字型 调用device driver的输入routine
块型 通过bread()进行输入处理

对文件的系统调用write()的场合也是类似的处理流程(ufs_write()->bwrite()),
ufs_write()则要考虑到文件大小的延伸。




FreeBSD核心探讨.8.驱动程序篇


2.3 Device Driver
进程的io要求到这里说的差不多了。上面也解说了对于文字型,块型的驱动程序接口,就
是dev_spec_vnodeop_opv_desc里定义的子函数那些。参考设备驱动程序,在sys/conf.h
里定义的结构体。block型是
struct bdevsw{
d_open_t *d_open;
d_close_t *d_close;
d_strategy_t *d_strategy;
d_ioctl_t *d_ioctl;
d_dump_t *d_dump;
d_psize_t *d_psize; /*得到容量*/
int *d_flags;
char *d_name; /*device 名*/
struct cdesw *d_cdev; /*对应的文字型*/
int d_maj; /*major号*/
}
文字型的则是
struct cdevsw{
d_open_t *d_open;
d_close_t *d_close;
d_read_t *d_read; /* rawread() */
d_write_t *d_write; /* rawwrite()*/
d_ioctl_t *d_ioctl;
d_stop_t *d_stop; /* nostop()*/
d_reset_t *d_reset; /* nullreset()*/
d_devtotty_t *d_devtotty; /* nodevtotty*/
d_select_t *d_select; /* deltrue*/
d_mmap_t *d_mmap; /* nommap*/
d_strategy_t *d_strategy
char *d_name; /*device名*/
struct bdevsw *d_bdev; /*对应block型*/
int d_may; /*major号*/
}


两方面共同的部分有
xx_open(dev_t dev,int oflags,int devtype,struct proc *p)
xx_close(dev_t dev,int fflag,int devtype,struct proc *p)
xx_ioctl(dev_t dev,int cmd,caddr_t data,int fflag,struct proc *p)
xx_open()用于打开device号的设备。xx_close()则用于关闭它。xx_ioctl()则对设备的
动作状态,机能的取得,设置等进行控制,它通过int cmd命令和参数caddr_t data对之
进行处理。xx_open()的oflags则是系统调用open()里指定的标志。xx_close()和
xx_ioctl()的fflag是每个文件描述符设定的标志。int devtype用来区别设备类型是文
字型的还是块型的。struct proc *p是本次要求的进程号。

在文字型的操作里,有这三个函数
xx_read(dev_t dev,struct uio *uio,int ioflag)
xx_write(dev_t dev,struct uio *uio,int ioflag)
xx_select(dev_t dev,int which, struct proc *p)
xx_read()/xx_write()是对device号的io,struct uio *uio 是io的buffer,int ioflag
标志io动作的option。例如,输入data没准备好的场合不用进入等待状态也可以。
xx_select()检查是否可以进行io要求。
在块设备的操作中,有一个函数
xx_strategy(struct buf *bp)
它处理io要求。struct buf *bp里面包含着device号,输入还是输出,io的buffer等。

device号中的major号,对文字型的struct cdevsw *cdevsw[],对块型的struct
bdevsw *bdevsw[],作为配列的添加字使用。向这些配列登记,就可以调出device driver
的登记routine。
对cdevsw[]登记的过程在kern/kern_conf.c,它使用
int cdevsw_add(
dev_t *descrip, /*收集device号的变量的指针*/
struct cdevsw *newentry,/*设置struct cdevsw的指针*/
struct cdevsw **oldentry,/*旧的设定内容的返回领域*/
)
另一方面,对bdevsw[]的登记过程则使用
int bdevsw_add_generic(
int bdev, /*block型的major号*/
int cdev, /*文字型的major浩*/
struct bdevsw *bdevsw, /*设定struct bdevsw的指针,对应d_cdev*/
)
block型的device和char型的device有着一定的对应关系。这些结构体相互参考。
bdevsw_add_generic()从block的结构体开始,对作为char型的device的结构体进行初始化。
还有,network interface的devive driver,并没有向cdevsw[]和bdevsw[]登记。而且也没有
device号。网络间的package流,和进程间与网络间的package流也没有特别指明。
调用登记routine的时候,可以把文件系统的modules作为特殊设备文件参考。登记
routine在什么地方都可以调用。
。main()(@kern/init_mail.c)的初始化过程中登记的routine调用的时候,各个
device driver的modules里由宏SYSINIT()准备进行。
。确认device driver里的io设备的存在的时候,调用登记routine。
当调用登记程序段的时候,如果major号和/dev/MAKEDEV的major号有冲突的时候,
就调用全部无关性device file的处理routine,也可能没有预期的的灾难事情。还有别的
以外事情,就是当/dev里没有对应的特殊设备文件的时候,也就不能从进程进行参考。



FreeBSD核心探讨.9.驱动程序篇


2.3.1驱动程序初始化
从文件系统的模块可以看出来,如果要对驱动程序的物理设备进行io,必须
先对它们进行初始化,否则不能处理process的io。核心初始化的过程里,一共登记
了两个基本的操作过程。
1.probe 确认io设备
2.attach 设置device driver内部的数据结构,使它能够对io设备
进行操作。登记中断子程序。
在device driver中的处理过程有:
1.i/o地址
i/o命令使用的地址,使io设备的控制硬件和数据交换。
2.中断号
io设备的状态变化的时候,向cpu发出通知。
3.共有内存地址
根据设备的不同,使用一部分内存空间进行cpu和数据的交换。
4.DMA通道
不用通过cpu做中介,设备和内存直接交换数据时候采用的通道的识别号。
cpu可以在数据传送的时候同时执行它的机器语言。
前两种是必须有的。设备根据他连接的总线设备不一样,处理过程也

上一页 [1] [2] [3] [4]  下一页


上一篇:FreeBSD 核心 (1) 下一篇:FreeBSD内核定制参考
大部分文章摘自网上,如有侵犯您的权益请与我们联系,我们会第一时间进行处理,谢谢! [ 打印文章 ] [ 关闭窗口 ]
推荐文章
·FreeBSD handbook中文版 9 配制F
·FreeBSD 升级系统
·Ports & Package
·FreeBSD kernel 编译大法(二)ker
·FreeBSD 上使用Kerberos 5认证
·FreeBSD 5.x 中 gbfs 的修正,及
·FreeBSD 安装Linuxigd
·FreeBSD 使用cvsd创建安全的cvs
·FreeBSD trafcount命令介绍
·FreeBSD入门安装及汉化
相关文章
·FreeBSD 核心 (1)
·FreeBSD4.8 IPFW How to!
·FreeBSD下的内存文件系统
·FreeBSD内核定制参考
·freebsd系统日志与备份
·关于FreeBSD4.4网络源代码接口层
·FreeBSD 5.2.1 boot0(启动扇区代
·FreeBSD中的设备命名规则
·FreeBSD 5内核源代码分析之copyi
·FreeBSD 5内核源代码分析之系统
最新文章
·FreeBSD连载(94):基于NAT的负载
·FreeBSD连载(93):反向代理负载
·FreeBSD连载(92):基于DNS的负载
·FreeBSD连载(91):提升静态网页
·FreeBSD连载(90):单服务器性能
·FreeBSD连载(89):CGI和SSI的安
·FreeBSD连载(88):安全连接方式S
·FreeBSD连载(87):基于用户的访
·FreeBSD连载(86):对IP地址和域
·FreeBSD连载(85):配置Apache服(
Google