• 块设备驱动框架


    以RAM模拟一个分区为例

    框架入口源文件:armblock.c

    (可根据入口源文件,再按着框架到内核走一遍)

    内核版本:linux_2.6.22.6     硬件平台:JZ2440

    以下是驱动代码  armblock.c :

    #include <linux/module.h>
    #include <linux/errno.h>
    #include <linux/interrupt.h>
    #include <linux/mm.h>
    #include <linux/fs.h>
    #include <linux/kernel.h>
    #include <linux/timer.h>
    #include <linux/genhd.h>
    #include <linux/hdreg.h>
    #include <linux/ioport.h>
    #include <linux/init.h>
    #include <linux/wait.h>
    #include <linux/blkdev.h>
    #include <linux/blkpg.h>
    #include <linux/delay.h>
    #include <linux/io.h>
    
    #include <asm/system.h>
    #include <asm/uaccess.h>
    #include <asm/dma.h>
    
    
    // ram_block_disk  独立的磁盘设备或则分区
    static struct gendisk *ram_block_disk;
    
    //定义一个request_queue 结构体
    static struct request_queue *ram_block_req;
    
    //定义一个自旋锁
    static DEFINE_SPINLOCK(ramblock_lock);
    
    
    //定义一个主设备号
    static int major;
    
    //磁盘大小
    #define GENDISK_SIZE (1024*1024)  
    
    //缓存起始地址
    static unsigned char *gendisk_buffer;
    
    //getgeo 获得驱动器信息
    static int gendisk_getgeo(struct block_device *dev, struct hd_geometry *geo)
    {
      geo->heads = 2;
      geo->cylinders = 32;
      geo->sectors = (GENDISK_SIZE/2/32/512);
      return 0;
    }
    
    
    static struct block_device_operations gendisk_fops=
    {
       .owner = THIS_MODULE,
       .getgeo = gendisk_getgeo,
    };
    
    //请求函数
    static void ram_block_req_fn(request_queue_t * q)
    {
        struct request *req;
        unsigned long offset=0, len=0;
        
        while((req =  elv_next_request(q))!=NULL)
        {
           offset = req->sector*512;
           len = req->current_nr_sectors*512;
           
           if(rq_data_dir(req) == READ)  memcpy( req->buffer,gendisk_buffer+offset,len  );  //read   dest src len
            else                    memcpy( gendisk_buffer+offset, req->buffer, len ); // write
    
          end_request(req,1);
        }
    }
    
    
    static int ram_block_init(void)
    {
       //申请gendisk
       ram_block_disk = alloc_disk(16);
    
       //设置gendisk
           //绑定请求函数
           ram_block_req = blk_init_queue(ram_block_req_fn,&ramblock_lock);
           ram_block_disk->queue = ram_block_req;
           //设置gendisk参数       注册blk
           major = register_blkdev(0, "armblock" );   /* cat /proc/devices */
           sprintf(ram_block_disk->disk_name, "armblock");
           ram_block_disk->fops  = &gendisk_fops;
           ram_block_disk->first_minor   = 0;
           ram_block_disk->major         = major;
           set_capacity(ram_block_disk, GENDISK_SIZE/512);
           gendisk_buffer = kzalloc(GENDISK_SIZE,GFP_KERNEL);    //磁盘起始地址
           
       //添加gendisk
       add_disk(ram_block_disk);
       return 0;
    }
    
    
    
    static void ram_block_exit(void)
    {
        del_gendisk(ram_block_disk);
        put_disk(ram_block_disk);
    
        blk_cleanup_queue(ram_block_req);
    
        unregister_blkdev(major,"armblock");
        
        kfree(gendisk_buffer);
    }
    
    module_init(ram_block_init);
    module_exit(ram_block_exit);
    
    MODULE_LICENSE("GPL");

    以下是编译驱动的Makefile:

    KERN_DIR = /work/systems/kernel/linux-2/linux-2.6.22.6
    
    all:
        make -C $(KERN_DIR) M=`pwd` modules 
    
    clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf modules.order
    
    obj-m    += armblock.o
  • 相关阅读:
    第三周作业
    面向过程(或者叫结构化)分析方法与面向对象分析方法到底区别在哪里?请根据自己的理解简明扼要的回答。
    移动APP开发使用什么样的原型设计工具比较合适?
    java 从上至下打印二叉树
    Qt applendPlainText()/append() 多添加一个换行解决方法
    tolua 转换 std::shared_ptr
    cmake add_custom_command 使用
    Boost使用笔记(Smart_ptr)
    webpack4 安装
    git安装管理
  • 原文地址:https://www.cnblogs.com/zsy12138/p/10392758.html
Copyright © 2020-2023  润新知