SylixOS I/O系统

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型,下面的两幅图分别对应了这两种类型的驱动结构。

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();
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值