您的位置:首页 > 其它

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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: