分类: 嵌入式
2013-06-17 21:44:40
为了进一步加深对IO设备管理数据结构的理解,本节将分别对函数库ioLib、iosLib进行分析。
ioLib库为上层提供了7个基本的函数接口:creat(), remove(), open(), close(), read(), write()以及ioctl()。上层用户只需要对这7个函数进行操作就能够完成对硬件的访问。下面一次分析ioLib库中各个函数库的功能。
1. int creat
(
const char *name,
int flag
)
该函数提供了一个与设备无关的通用接口,用于创建一个文件(可以是普通的磁盘文件也可以是抽象的设备文件),该文件的路径为name,创建完毕后自动打开,打开的参数为flag。该函数的正常返回值为文件描述符,否则将会返回ERROR。
对照图2.8,该函数根据设备的名称,从链表中找到该设备对应的设备号drmNum(该数值即为函数返回的文件描述符),然后以此为下标就可以找到该类设备的de_create函数指针,从而找到该设备的create函数。
2. int open
(
const char *name,
int flags,
int mode
)
该函数打开一个文件以方便进行读、写或者更新,打开后返回该文件的文件描述符。open()函数的参数为文件名以及访问方式:
l O_RDONLY (0) 以只读方式打开
l O_WRONLY (1) 以只写方式打开
l O_RDWR (2) 以读写方式打开
l O_CREAT (0x0200)如果文件不存在,就创建一个文件并打开。
3. LOCAL int ioCreateOrOpen
(
const char *name,
int flags,
int mode,
BOOL create
)
这个函数其实是函数create()和open()函数的实现主体。create()和open()函数只是根据参数create简单调用函数ioCreateOrOpen()而已,真正的实现在函数ioCreateOrOpen()中。
4. STATUS unlink
(
char *name
)
该函数主要是和posix兼容,它的功能与remove完全相同。
5. STATUS remove
(
const char *name
)
调用函数iosDelete来删除文件。如果有符号链接,则需要沿着符号链接直接找到文件并删除。
6. STATUS close
(
int fd
)
调用函数ioClose函数关闭文件。
7. int rename
(
const char *oldname,
const char *newname
)
修改文件名。
并不是所有的设备都支持重命名操作,比如通常的dosFS和rt11FS都是支持重命名操作的,而netDrv和nfsDrv则不支持,因此在使用这个函数前需要明确设备是否支持重命名操作。
重命名操作主要通过调用函数ioctl (fd, FIORENAME, (int) newname)完成。
注意:调用函数ioctl (fd, FIORENAME, (int) newname)重命名前需要先打开文件open()。
8. int read
(
int fd,
char *buffer,
size_t maxbytes
)
调用函数iosRead实现读操作,maxbytes为读取的最大字节数,读取之后存放在buffer指定的地址空间,不过可能由于文件中字节数的限制等因素,实际读取的字节数可能会小于maxbytes,因此需要在最终的返回值中返回实际读取的字节数。
9. int write
(
int fd,
char *buffer,
size_t nbytes
)
调用函数iosWrite向指定的文件中写入数据,nbytes为期望写入的字节数,但是实际上可能会由于文件本身的限制导致实际写入的字节数小于nbytes,因此需要在返回值中记录实际写入的字节数。
10. int ioctl
(
int fd,
int function,
int arg
)
直接调用函数iosIoctl实现对文件的控制操作。
11. int lseek
(
int fd,
long offset,
int whence
)
设定一个文件的读写指针,下次读写操作将从设定的位置开始。
参数whence有三个数值:
l SEEK_SET (0) 设定到相对于文件起始位置偏移offset位置。
l SEEK_CUR (1) 设定到当前位置偏移offset的位置。
l SEEK_END (2) 相对于文件结束位置偏移offset的位置。
注意:如果指定的地址是无效的地址(超出了文件的范围),那么将返回错误指示。
12. int readv
(
int fd,
struct iovec *iov,
int iovcnt
)
从设备fd中读取数据,保存在iov起始地址为iov的数组中。iovcnt为结构iovec数组iov的元素的个数。iov是一个数组指针,它指向一个iovec结构数组,iovec结构中的元素iov_base指定了数据保存起始位置地址,而iovcnt则指定了iov数组的元素个数,因此总的读出的字节数为各个数组元素中保存数据的字节数之和。如图2.9所示。
图2.9 iovec结构示意图
13. int writev
(
int fd,
register struct iovec *iov,
int iovcnt
)
该函数调用iosWrite函数将几段分散的数据写入到fd设备中。
14. STATUS ioFullFileNameGet
(
char * pathName,
DEV_HDR ** ppDevHdr,
char * fullFileName
)
通常来说,一个完整的文件的路径包括两部分,该文件所在的设备路径,以及该文件在该设备上的相对路径,这两部分组合得到了一个完整的路径。这个函数的作用就是根据参数pathName制定的路径名,这个路径名可以是相对(相对麽默认的路径ioDefPath)路径名或者绝对路径名。函数ioFullFileNameGet的作用个就是根据提供的路径名找到该文件坐在的设备及其相对于该设备的路径。其中设备名结构变量指针的指针保存在DEV_HDR ** ppDevHdr参数中返回,相对于设备的文件名则存放在参数char * fullFileName中保存。
举例来说当前默认路径为“/dev/sd1/x/”,相对路径名为“y.txt”,该函数将会找到设备“/dev/sd1/”对应的DEV_HDR ** ppDevHdr指针返回,并将fullFileName设置为"x/y.txt"返回。
15. STATUS ioDefPathSet
(
char *name
)
设定默认路径,并将其复制到全局变量ioDefPath中,注意name必须是一个绝对路径,也就是说name指定的路径必须包含一个有效的设备(即从iosDevList中能够搜索到的设备)。
16. void ioDefPathGet
(
char *pathname
)
将ioDefPath复制到pathname中返回。
17. STATUS chdir
(
char *pathname
)
这个函数等价于函数ioDefPathSet(),可以认为是ioDefPathSet()函数的一个别名。
18. char *getcwd
(
char *buffer,
int size
)
ioDefPathGet()函数的别名。只是如果参数size指定的空间太小的话将返回ERROR。
19. char *getwd
(
char *pathname
)
ioDefPathGet()函数的别名。
20. STATUS ioDefPathCat
(
char *name
)
修改默认的路径。如果name是一个包含设备路径的一个绝对路径名,那么它就成为了一个新的默认路径。否则name将会被连接到当前默认路径从而更新了新的默认路径。
例如:如果默认路径为"sda/x",name="sda/y",则默认路径修改为"sda/y";如果name="/y",则默认路径修改为"sda/x/y".
21. void ioDefDevGet
(
char *devName
)
获取默认路径所属的设备的名称。
22. void ioDefDirGet
(
char *dirName
)
这个函数在新的版本中将会删除。它的主要作用就是获取默认路径相对于所属设备的相对路径。
如设备名为"sda",默认路径为"sda/x",则ioDefDevGet()函数获取了"sda"设备,而函数ioDefDirGet()则获取了相对路径。
23. void ioGlobalStdSet
(
int stdFd,
int newFd
)
文件ioLib中定义了一个数组LOCAL int ioStdFd [3],该数组表明标准文件描述符。这三个标准的文件描述符主要是:标准输入0、标准输出1、错误输出2。这个函数的作用,就是设置这个数组中某个元素的文件描述符。
stdFd:指的是ioStdFd数组中元素的下标,0~2有效。
newFd:数组中元素的数值。
24. int ioGlobalStdGet
(
int stdFd
)
获取数组ioStdFd中某个元素的数值,即文件描述符的数值。
25. void ioTaskStdSet
(
int taskId,
int stdFd,
int newFd
)
对VxWorks系统来说,并不是每个任务的标准输入、标准输出、错误输出都是相同的,多数任务的标准输入是键盘,标准输出是显示器等,但是对某些串口监控的任务来说,可以把它的标准输入设置为串口等等。
每个任务描述符中都有一个数组taskStd,表明这个任务的标准输入、标准输出以及错误输出,这个函数的功能,就是设置一个任务的标准输入、标准输出、错误输出。
26. int ioTaskStdGet
(
int taskId,
int stdFd
)
获取一个任务的标准输入、标准输出、错误输出
27. BOOL isatty
(
int fd /* file descriptor to check */
)
判断一个文件描述符是否是一个tty。最初的计算机没有键盘和显示器,输入输出都比较麻烦,后来有Teletype公司生产了一种字符型终端设备,因此有很多计算机操作系统都把字符型终端设备叫做tty设备。
关于文件路径的进一步详细操作可以参考函数库pathLib。