设备管理

本文深入探讨了设备管理在操作系统中的关键作用,介绍了设备驱动程序的结构、缓冲区管理、设备分配和虚拟设备的概念。通过实例展示了如何在用户态编写键盘驱动程序并注册到内核,涉及Device、Buffer和DeviceTable的结构。
摘要由CSDN通过智能技术生成

设备管理

1.概念

设备管理的主要功能有缓冲区管理、设备分配、设备处理、虚拟设备及实现设备独立性等,由于I/O设备不仅种类繁多,而且他们的特性和操作方式往往相差甚大,使得设备管理称为操作系统中最繁杂且与硬件最紧密的部分,下面开始正式的学习1

2.相关结构体

设备管理模块主要的功能是管理每一个设备的驱动程序,从而可以对设备进行读写I/O操作,和其他操作;在该系统设计时,没有考虑字符设备和块设备的区别,简单的为所有的设备都划分2块缓冲区。

1.Buffer
//队列
//head出队
//tail入队
struct Buffer{
    char * buf;
    unsigned long bufferLength;
    unsigned long head;
    unsigned long tail;
};

Buffer结构体是一个队列(使用数组实现),head和tail是队列头和队列尾。

2.Device

Device对应一个具体的设备。

struct Device{
    unsigned long devID;
    //输入到cpu的buffer ----->CPU
    struct Buffer inBuffer;
    //输出到设备的buffer ----->设备
    struct Buffer outBuffer;
    //返回设备号
    unsigned long (* load)(struct Device *,unsigned long );//注册一个设备和并复制其驱动程序到内核
    unsigned long (* init)(unsigned long);//该设备的初始化函数
    unsigned long (* open)(unsigned long);//该设备的打开函数
    //2:输入的字符,3:字符长度 4:(0)inbuffer (1)outbuffer
    unsigned long (* write)(unsigned long,char * ,unsigned long,unsigned long);//写入该设备
    //2:字符长度 3:(0)inbuffer (1)outbuffer
    char (* read)(unsigned long,unsigned long,unsigned long);//读取该设备
    //返回设备号
    unsigned long (* close)(unsigned long);//该设备的关闭函数
    unsigned long (* exit)(unsigned long);//该设备的卸载函数
};

在注册设备的时候,会同时将设备的驱动程序复制到内核空间,并赋值给该结构体;每一个设备都有2个Buffer。

3.DeviceTable
struct DeviceTable{
    //管理系统的所有设备DeviceClass==255
    struct Device * devices[DeviceClass];
    //当前已经分配的设备数量
    unsigned long count;
};

可以使用函数registerDevice(void * deviceLoad,unsigned long bufferSize)注册一个设备到内核,函数详细说明见后。

3.使用

想要在用户态编写一个驱动程序,并注册到内核使用,可以使用下面的步骤(使用键盘设备为例):

1.编写设备init方法:
unsigned long keyboardInit(unsigned long devID){
    while(!is8042InBufReady());
    io_out8(CMDPort,0x60);
    while(!is8042InBufReady());
    io_out8(DataPort,initMode);
    return True;
}

该方法可以输入一个设备号,该函数的主要功能是初始化设备的寄存器,返回是否初始化成功。

2.编写设备Open,Close方法:
unsigned long keyboardOpen(unsigned long devID){
    return True;
}
unsigned long kerboardClose(unsigned long devID){
    return True;
}

该函数接受一个设备号输入,返回执行是否成功。

3.编写Read,Write方法:
unsigned char keyboardRead(unsigned long devID,unsigned long length,unsigned long InOrOutbuffer){
    unsigned long i;
    struct Buffer * buffer;
    if(InOrOutbuffer == 0)  buffer = &deviceTable.devices[devID]->inBuffer;
    else buffer = &deviceTable.devices[devID]->outBuffer;
    return deleteAndreturn(buffer);
}
unsigned long kerboardWrite(unsigned long devID,char * buf,unsigned long length,unsigned long InOrOutbuffer){
    unsigned long i;
    struct Buffer * buffer;
    if(InOrOutbuffer == 0)  buffer = &deviceTable.devices[devID]->inBuffer;
    else buffer = &deviceTable.devices[devID]->outBuffer;
    for(i=0;i<length;i++){
        char c = *(buf + i);
        insert(buffer,c);
    }
    return True;
}

这两个函数主要是读写该设备的inBuffer或者outBuffer,如果参数InOrOutbuffer==0则读写inBuffer,否则读写outBuffer。

4.编写load,exit方法:
unsigned long kerboardLoad(struct Device * device,unsigned long bufferSize){
    device->init = keyboardInit;
    device->open = keyboardOpen;
    device->read = keyboardRead;
    device->write = kerboardWrite;
    device->exit = kerboardExit;
    device->close = kerboardClose;
    return True;
}
unsigned long kerboardExit(unsigned long devID){
    return True;
}

load用来注册一个设备,函数可以直接使用上面的模板,赋值参数device的函数指针变量为上面步骤编写的(init,open,close,read,write)函数,参数bufferSize表示要初始化的inBuffer或者outBuffer的大小。

exit用来卸载一个设备,目前可以直接返回Ture。

5.注册

在用户态编写完上述代码后,可以使用系统调用(还未实现),该系统调用进入内核或最终会调用registerDevice(void * deviceLoad,unsigned long bufferSize)函数,该函数实现如下:

//向系统注册驱动程序,返回驱动程序的id号
unsigned long registerDevice(void * deviceLoad,unsigned long bufferSize){
    //向内核申请一块内存
    struct Device * device = (struct Device *) getMemoryBlock(sizeof(struct Device));
    device->devID = deviceTable.count;
    deviceTable.devices[deviceTable.count] = device;
    //复制用户态的load函数到内核态
    void * loadfun = (void *)getMemoryBlock(4096);
    copy((unsigned long) deviceLoad,(unsigned long) loadfun,4096);
    device->load =  loadfun;
    //loadDeviceFunTOKernel函数用来复制其他函数到内核
    if(device->load(device,bufferSize)){
        if(loadDeviceFunTOKernel(device)){
            device->init(device->devID);
        }
    }
    //初始化inBuffer和outBuffer
    initBuffer(&device->inBuffer,bufferSize);
    initBuffer(&device->outBuffer,bufferSize);
    deviceTable.count++;
    return device->devID;
}

该函数执行完后会把该驱动程序注册到内核的deviceTable表中。

4.详细

github

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值