SylixOS I/O系统
2015-07-15 16:19
148 查看
SylixOS I/O系统简介
SylixOS 兼容标准的POSIX输入输出系统,使用户非常容易上手。SylixOS 的I/O概念与UNIX兼容系统相同,认为一切都是文件。这些文件有不同的类型,它们包括:目录文件:这个文件包含了其他文件的名字以及这些文件的指针。
块设备文件:这种文件提供的 I/O 接口标准符合 SylixOS 对块设备的定义。
字符设备文件:这是标准的不带缓冲的设备文件,系统中的设备不是块设备就是字符设备。
FIFO文件:管道通信文件。它对应了一个命名管道。
套接字(socket)文件:进程间或者主机间的网络通信。
在SylixOS中对文件的操作也同样遵循UNIX的方法,主要通过open、read、write、close等函数调用来操作文件。
SylixOS I/O驱动结构
SylixOS中I/O驱动结构分为ORIG型和NEW_1型,下面的两幅图分别对应了这两种类型的驱动结构。从两幅图可以看出NEW_1型驱动结构在ORIG型驱动结构的基础上增加了文件节点层(这一层相当于UNIX系统的vnode),这一层的引入,使SylixOS对文件的操作支持了记录锁,文件权限的功能。下面我重点学习一下文件节点层之下的各层。
SylixOS设备头
typedef struct { LW_LIST_LINE DEVHDR_lineManage; /* 设备头管理链表 */ UINT16 DEVHDR_usDrvNum; /* 设备驱动程序索引号 */ PCHAR DEVHDR_pcName; /* 设备名称 */ UCHAR DEVHDR_ucType; /* 设备 dirent d_type */ atomic_t DEVHDR_atomicOpenNum; /* 打开的次数 */ PVOID DEVHDR_pvReserve; /* 保留 */ } LW_DEV_HDR; typedef LW_DEV_HDR *PLW_DEV_HDR;
上面结构就是SylixOS设备头结构,此结构中包含以下一些信息:
DEVHDR_lineManage这是一个设备链表,设备安装时将自动链到系统设备链表上;
DEVHDR_usDrvNum设备驱动程序索引号,SylixOS内核维护了一个驱动表如上面的两个图所示,每一个SylixOS设备都对应了一个驱动表项,当然不同的设备可以对应到同一个驱动表项,也就是说可以拥有一套驱动方法;
DEVHDR_pcName设备名字,每一个SylixOS设备都应该有一个唯一的名字,如“/dev/hotplug”;
DEVHDR_ucType设备类型,例如,字符设备类型、块设备类型等;
DEVHDR_atomicOpenNum这个成员记录了设备的打开次数,内核提供了下面几个函数对它进行操作;
INT LW_DEV_INC_USE_COUNT(PLW_DEV_HDR pdevhdrHdr); /* 增加一次打开计数 */ INT LW_DEV_DEC_USE_COUNT(PLW_DEV_HDR pdevhdrHdr); /* 减少一次打开计数 */ INT LW_DEV_GET_USE_COUNT(PLW_DEV_HDR pdevhdrHdr); /* 获得打开计数 */
DEVHDR_pvReserve暂时保留。
所有安装的设备将被链到下面这个链表头上,系统进行统一管理。
LW_LIST_LINE_HEADER _S_plineDevHdrHeader; /* 设备表表头 */
SylixOS驱动结构
typedef struct { LONGFUNCPTR DEVENTRY_pfuncDevCreate; /* 建立函数 */ FUNCPTR DEVENTRY_pfuncDevDelete; /* 删除函数 */ LONGFUNCPTR DEVENTRY_pfuncDevOpen; /* 打开函数 */ FUNCPTR DEVENTRY_pfuncDevClose; /* 关闭函数 */ SSIZETFUNCPTR DEVENTRY_pfuncDevRead; /* 读设备函数 */ SSIZETFUNCPTR DEVENTRY_pfuncDevWrite; /* 写设备函数 */ SSIZETFUNCPTR DEVENTRY_pfuncDevReadEx; /* 读设备函数扩展函数 */ SSIZETFUNCPTR DEVENTRY_pfuncDevWriteEx; /* 读设备函数扩展函数 */ FUNCPTR DEVENTRY_pfuncDevIoctl; /* 设备控制函数 */ FUNCPTR DEVENTRY_pfuncDevSelect; /* select 功能 */ OFFTFUNCPTR DEVENTRY_pfuncDevLseek; /* lseek 功能 */ FUNCPTR DEVENTRY_pfuncDevFstat; /* fstat 功能 */ FUNCPTR DEVENTRY_pfuncDevLstat; /* lstat 功能 */ FUNCPTR DEVENTRY_pfuncDevSymlink; /* 建立链接文件 */ SSIZETFUNCPTR DEVENTRY_pfuncDevReadlink; /* 读取链接文件 */ FUNCPTR DEVENTRY_pfuncDevMmap; /* 文件映射 */ FUNCPTR DEVENTRY_pfuncDevUnmap; /* 映射结束 */ BOOL DEVENTRY_bInUse; /* 是否被使用 */ INT DEVENTRY_iType; /* 设备驱动类型 */ LW_DRV_LICENSE DEVENTRY_drvlicLicense; /* 驱动程序许可证 */ } LW_DEV_ENTRY; typedef LW_DEV_ENTRY *PLW_DEV_ENTRY;
上面就是SylixOS目前支持的驱动方法,基本上涵盖了设备的各种操作,当然, Linux程序员可能更习惯于struct file_operations,SylixOS为了兼容这部分,也加入了struct file_operations。
SylixOS字符设备驱动
通过上面的一个简单介绍,接下来我们写一个简单的字符设备驱动来简单的练习一下。下面的程序展示了一个SylixOS字符设备的编写方法,程序实现了一个字符设备的读、写。#define __SYLIXOS_KERNEL #include <SylixOS.h> typedef struct { LW_DEV_HDR CDEV_devhdr; CHAR CDEV_cBuf[64]; time_t CDEV_time; } CDEV; static INT devDrvNum = -1; static LONG devOpen (CDEV *pcdev, PCHAR pcName, INT iFlag, INT iMode) { if (!pcdev) { _ErrorHandle(EFAULT); return (PX_ERROR); } LW_DEV_INC_USE_COUNT(&pcdev->CDEV_devhdr); return ((LONG)pcdev); } static INT devClose (CDEV *pcdev) { if (!pcdev) { _ErrorHandle(EFAULT); return (PX_ERROR); } if (LW_DEV_GET_USE_COUNT(&pcdev->CDEV_devhdr)) { LW_DEV_DEC_USE_COUNT(&pcdev->CDEV_devhdr); } return (ERROR_NONE); } static ssize_t devRead (CDEV *pcdev, PVOID pvBuf, size_t stLen) { ssize_t stTempLen; stTempLen = min(stLen, 64); lib_memcpy(pvBuf, (PVOID)&pcdev->CDEV_cBuf[0], stTempLen); return (stTempLen); } static ssize_t devWrite (CDEV *pcdev, PVOID pvBuf, size_t stLen) { ssize_t stTempLen; stTempLen = min(stLen, 64); lib_memcpy((PVOID)&pcdev->CDEV_cBuf[0], pvBuf, stTempLen); return (stTempLen); } static INT devIoctl (CDEV *pcdev, INT iCmd, LONG lArg) { INT iError = ERROR_NONE; struct stat *pstatGet; switch (iCmd) { case FIOFSTATGET: pstatGet = (struct stat *)lArg; if (pstatGet) { pstatGet->st_dev = (dev_t)pcdev; pstatGet->st_ino = (ino_t)0; /* 相当于唯一节点 */ pstatGet->st_mode = 0666 | S_IFCHR; pstatGet->st_nlink = 1; pstatGet->st_uid = 0; pstatGet->st_gid = 0; pstatGet->st_rdev = 1; pstatGet->st_size = 0; pstatGet->st_blksize = 0; pstatGet->st_blocks = 0; pstatGet->st_atime = pcdev->CDEV_time; pstatGet->st_mtime = pcdev->CDEV_time; pstatGet->st_ctime = pcdev->CDEV_time; } else { errno = EINVAL; iError = (PX_ERROR); } } return (iError); } static struct file_operations fop = { .owner = THIS_MODULE, .fo_open = devOpen, .fo_close = devClose, .fo_read = devRead, .fo_write = devWrite, .fo_ioctl = devIoctl }; INT devDrvInstall (VOID) { if (devDrvNum > 0) { return (ERROR_NONE); } devDrvNum = API_IosDrvInstallEx(&fop); DRIVER_LICENSE(devDrvNum, "Dual BSD/GPL->Ver 1.0"); DRIVER_AUTHOR(devDrvNum, "xx.xxx"); DRIVER_DESCRIPTION(devDrvNum, "char dev driver."); return (devDrvNum > 0 ? ERROR_NONE : PX_ERROR); } INT devCreate (VOID) { CDEV *pcdev; INT iRet; pcdev = __SHEAP_ALLOC(sizeof(CDEV)); if (!pcdev) { return (PX_ERROR); } lib_bzero(pcdev, sizeof(CDEV)); iRet = API_IosDevAddEx(&pcdev->CDEV_devhdr, "/dev/cdev", devDrvNum, DT_CHR); if (iRet != ERROR_NONE) { __SHEAP_FREE(pcdev); return (PX_ERROR); } pcdev->CDEV_time = lib_time(LW_NULL); return (ERROR_NONE); } VOID devDelete (VOID) { PCHAR pcTail; PLW_DEV_HDR pdevhdr; pdevhdr = API_IosDevFind("/dev/cdev", &pcTail); API_IosDevDelete(pdevhdr); API_IosDrvRemove(devDrvNum, LW_TRUE); } void module_init (void) { INT iRet; iRet = devDrvInstall(); if (iRet == ERROR_NONE) { iRet = devCreate(); if (iRet != ERROR_NONE) { printk(KERN_ERR "Char device install failed.\n"); } } else { printk(KERN_ERR "Char driver install failed.\n"); } } void module_exit (void) { devDelete(); }
相关文章推荐
- java map
- iOS:Block写递归
- JS滚轮事件(mousewheel/DOMMouseScroll)了解
- 数组排序
- thinkphp最新版本上传bug与解决办法
- ansible错误
- zookeeper 原理
- quick-cocos2d-x游戏开发——StateMachine状态机
- slidingmenu_library
- workqueue
- 经典CUDA教程
- 网站
- MYSQL学习笔记(十)存储过程(续)
- 2015台湾移动游戏市场白皮书
- 日期对比
- Static Storage vs Heap vs Stack
- Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
- json详解
- 云计算和大数据时代网络技术揭秘(六)LISP协议
- iOS 语录