• IO模型


    【1】IO模型
     1)阻塞IO
     2)非阻塞IO
     3)IO多路复用
     4)异步IO
     
    【2】IO多路复用
     多路复用在阻塞IO模型上封装的
     
     应用程序:
            int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
            功能:实现对文件描述符的监听(如果某一个文件描述符准备就绪,select立刻返回)
            函数本身阻塞函数,实现对文件描述符轮询检测

            void FD_CLR(int fd, fd_set *set);  从文件描述符集合中将描述符移除
            int  FD_ISSET(int fd, fd_set *set); 查看当期的文件描述符是否在文件描述符集合中
            void FD_SET(int fd, fd_set *set);  向文件描述符集合中将描述符添加
            void FD_ZERO(fd_set *set);         清空文件描述符集合
            
     驱动:
            unsigned int (*poll) (struct file *, struct poll_table_struct *);
            a)对可能引起设备文件状态变化的等待队列调用poll_wait函数,将对应的等待队列头添加到poll_table
               由内核检测poll_table
               
               static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
               功能:将等待队列加入到poll_table表
               参数:filep
                     wait_address  等待队列头
                     p    poll_table表     
               
            b)返回表示是否能对设备进行无阻塞读,写访问的掩码
                      POLLIN,POLLOUT,POLLRDNORM,POLLERR
                       可读    可写     正常        错误
                       
               return POLLIN|POLLRDNORM
    【3】异步IO
     异步通知的意思是:一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态
     
     应用程序:
        应用程序要捕捉SIGIO信号,注册信号
        signal(SIGIO, handler);  

         应用程序要指定进程为文件的属主
         当前文件描述符属于该进程,进程需要对该文件描述符状态发生改变之后,处理相应的任务
        fcntl(fd, F_SETOWN, getpid());
        
         int fcntl(int fd, int cmd, ... /* arg */ );
         参数:fd  文件描述符
               cmd  定义对文件描述符的操作
               arg  附件参数

        应用程序通过fcntl函数在设备中设置FASYNC标志
        oflags = fcntl(fd, F_GETFL);   获取当前文件描述符的标志位
        fcntl(fd, F_SETFL, oflags | FASYNC); 重新设置标志位

     
       驱动:
           1)支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID。不过此项工作已由内核完成,设备驱动无须处理。
           2)支持F_SETFL命令的处理,每当FASYNC标志改变时,驱动程序中的fasync()函数将得以执行。因此,驱动中应该实现fasync()函数
               fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
               功能:将文件描述符添加到异步通知队列中
               参数:fd  文件描述符
                     filep  
                     on  打开设备的标志位
                     fapp  异步通知队列       
           3)在设备资源可获得时,调用kill_fasync()函数激发相应的信号
              void kill_fasync(struct fasync_struct **fp, int sig, int band)
              功能:向应用程序发送信号
              参数:fp  异步通知队列
                    sig  发送的信号类型
                    band  掩码  POLLIN可读
                                POLLOUT可写
                                
    【4】Linux驱动中设备模型
     在Linux内核中,将对设备的操作代码抽象成一个对象(驱动)
                    将对设备的硬件描述抽象成一个对象(设备)
                    将该设备使用的总线抽象成一个对象(总线)
     
     在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成
     
     总线可以是物理存在的,也可以是虚拟的。内核中对应的结构为struct bus_type(描述一个总线对象)
       struct bus_type {
              const char        *name; 总线的名称
              int (*match)(struct device *dev, struct device_driver *drv); 实现设备与驱动的匹配
       }
     设备是连接到某条物理或者虚拟总线上的对象。可能是真正物理对象,也可能是虚拟对象。内核中对应的结构为struct device
       struct device{
             struct kobject kobj;  所有的设备对象的父亲
             const char        *init_name;   设备的名称
             struct bus_type    *bus;    总线的名称
             void        *platform_data;    私有数据,存放的是硬件的信息
             void    (*release)(struct device *dev);      卸载设备模块时,自动执行此函数    
       }
     
     驱动是用来和设备通信的软件程序。驱动可以从设备中获取数据,也可以把相应数据发给设备进行处理。内核中对应的结构为struct devicc_driver
       struct device_driver{
            const char        *name;  名称
            struct bus_type        *bus; 总线的名称
            struct module        *owner;  THIS_MODULE
            const struct of_device_id    *of_match_table;  设备树匹配
            int (*probe) (struct device *dev);  回调函数(一但设备与驱动匹配成功,自动执行此函数,存放对设备的操作的代码)
            int (*remove) (struct device *dev); 卸载函数(存放的与probe执行相反的代码)
            
       }
     
     如何实现Linux设备模型:
         1)构建总线对象,并且向内核完成注册
                注册:int bus_register(struct bus_type *bus)
                注销:void bus_unregister(struct bus_type *bus)
         2)构建设备对象,并且向内核完成注册
                注册:int device_register(struct device *dev)  
                注销:void device_unregister(struct device *dev)            
         3)构建驱动对象,并且向内核完成注册
                注册:int driver_register(struct device_driver *drv)
                注销:void driver_unregister(struct device_driver *drv)
         4)实现设备与驱动的匹配
                实现匹配操作
         5)实现驱动对设备的操作    
        
    【5】platform设备模型
     将设备,驱动,总线抽象成一个对象
     
     设备对象:描述硬件信息
         struct platform_device {
               const char    *name;  设备的名称
               struct device    dev;   描述设备对象的结构体
                      void    (*release)(struct device *dev);
               u32        num_resources;   描述硬件资源的数量
               struct resource    *resource;   描述硬件资源的信息
        };
        
        struct resource {
        resource_size_t start;   起始地址
        resource_size_t end;     结束地址
        unsigned long flags      标志-描述地址属性
        };    
        
        #define IORESOURCE_MEM        0x00000200  内存地址
        #define IORESOURCE_REG        0x00000300    寄存器的偏移量
        #define IORESOURCE_IRQ        0x00000400  中断
     
     驱动对象:描述驱动代码
        struct platform_driver {
             int (*probe)(struct platform_device *);    回调函数(一但设备与驱动匹配成功,自动执行此函数,存放对设备的操作的代码)
             int (*remove)(struct platform_device *);   卸载函数(存放的与probe执行相反的代码)
             struct device_driver driver;    描述所有驱动对象的结构体
                    const char        *name;
                    struct module        *owner;  
                    const struct of_device_id    *of_match_table;  实现设备树的匹配
             const struct platform_device_id *id_table;  匹配表
            };
     总线对象:描述总线信息
         struct bus_type platform_bus_type = {
               .name        = "platform",      总线的名称
               .match        = platform_match,  匹配方法
         };
     
     platform平台匹配方法
          static int platform_match(struct device *dev, struct device_driver *drv)
         {
        struct platform_device *pdev = to_platform_device(dev);
        struct platform_driver *pdrv = to_platform_driver(drv);

        /* Attempt an OF style match first */          设备树匹配
        if (of_driver_match_device(dev, drv))
            return 1;
        /* Then try to match against the id table */   匹配表匹配
        if (pdrv->id_table)  
            return platform_match_id(pdrv->id_table, pdev) != NULL;   

        /* fall-back to driver name match */
        return (strcmp(pdev->name, drv->name) == 0);    名字匹配
        }
     
     如何实现platform平台模型:
        1)构建设备对象,并且向内核完成注册
               注册:int platform_device_register(struct platform_device *pdev)
               注销:void platform_device_unregister(struct platform_device *pdev)           
        2)构建驱动对象,并且向内核完成注册
               注册:#define platform_driver_register(drv)   __platform_driver_register(drv, THIS_MODULE)
               注销:platform_driver_unregister(struct platform_driver *);
        3)实现设备与驱动的匹配
               匹配方法已实现
        4)实现驱动对设备的操作
               获取硬件资源,实现对设备操作
     

  • 相关阅读:
    GP服务之IDW GIS空间插值密度分布图
    Cesium添加标注
    arcgis时间滑块time slider工具
    ArcObjects和ArcEngine的区别
    Android 多媒体 1.1 获取多媒体信息[原创]
    Android 获取root权限 实现重启
    Android GIF 编解码
    中国的程序员只能支撑到30岁么。
    Android通过摇晃手机的频率来控制声音的频率
    Android ListView 下拉刷新 上拉更多[实例]
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/7294038.html
Copyright © 2020-2023  润新知