|
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内核定制参考 |