zoukankan      html  css  js  c++  java
  • test

    obj-m := sbull.o
    KDIR := /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)

    default:
    $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
    clean:
    $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
    rm -rf Module.markers modules.order Module.symvers

    include <linux/module.h>

    include <linux/moduleparam.h>

    include <linux/init.h>

    include <linux/sched.h>

    include <linux/kernel.h>

    include <linux/slab.h>

    include <linux/fs.h>

    include <linux/errno.h>

    include <linux/types.h>

    include <linux/fcntl.h>

    include <linux/hdreg.h>

    include <linux/kdev_t.h>

    include <linux/vmalloc.h>

    include <linux/genhd.h>

    include <linux/blkdev.h>

    include <linux/buffer_head.h>

    include <linux/bio.h>

    include "sbull.h"

    static int sbull_major = SBULL_MAJOR; //主设备号 0
    static int nsectors = 16384; //设备大小
    static int hardsect_size = 512; //扇区大小

    module_param(sbull_major,int,0);
    module_param(nsectors,int,0);
    module_param(hardsect_size,int,0);

    struct sbull_dev
    {
    int size; //以扇区为单位设备的大小
    u8 *data; //数据数组(存储磁盘数据队列)
    struct request_queue *queue; //请求队列(用于互斥)
    struct gendisk *gd; //gendisk结构
    spinlock_t lock; //设备自旋锁
    };

    static struct sbull_dev *Devices = NULL;

    static int sbull_open(struct inode *inode,struct file *filp)
    {
    return 0;
    }

    static int sbull_release(struct inode *inode,struct file *filp)
    {
    return 0;
    }

    static int sbull_ioctl(struct inode inode,struct file filp,unsigned int cmd,unsigned long arg)
    {
    int ret = 0;
    int err = 0;
    //检测命令的有效性
    if(_IOC_TYPE(cmd) != SBULL_IOC_MAGIC)
    {
    return -EINVAL;
    }
    if(_IOC_NR(cmd) > SBULL_IOC_MAXNR)
    {
    return -EINVAL;
    }
    //根据命令类型,检测用户空间是否可以访问
    if(_IOC_DIR(cmd) & _IOC_READ)
    {
    err = !access_ok(VERIFY_WRITE,(void
    )arg,_IOC_SIZE(cmd));
    }
    else if(_IOC_DIR(cmd) & _IOC_WRITE)
    {
    err = !access_ok(VERIFY_READ,(void
    )arg,_IOC_SIZE(cmd));
    }
    if(err)
    {
    return -EFAULT;
    }
    switch(cmd)
    {
    case SBULL_IOCGETMAJOR: //得到主设备号
    ret = __put_user(sbull_major,(int __user)arg);
    break;
    case SBULL_IOCGETSECTORS: //得到扇区总数
    ret = __put_user(nsectors,(int __user
    )arg);
    break;
    case SBULL_IOCGETSIZE: //得到块设备大小
    ret = __put_user(nsectors * hardsect_size,(int __user*)arg);
    break;
    default:
    return -EFAULT;
    }
    return ret;
    }

    static void sbull_transfer(struct sbull_dev *dev,sector_t sector,unsigned long nsect,char *buffer,int write)
    {
    unsigned long offset = sector << 9;
    unsigned long nbytes = nsect << 9;
    if( (offset + nbytes) > dev->size )
    {
    printk(KERN_NOTICE "Beyond-end write (%ld %ld) ",offset,nbytes);
    return;
    }
    if(write)
    {
    printk(KERN_NOTICE "writing to disk ");
    memcpy(dev->data + offset,buffer,nbytes);
    }
    else
    {
    printk(KERN_NOTICE "readding from disk ");
    memcpy(buffer,dev->data + offset,nbytes);
    }

    }

    static void sbull_request(struct request_queue *q)
    {
    struct request *req;
    req = blk_fetch_request(q);
    while( req != NULL )
    {
    struct sbull_dev *dev = req->rq_disk->private_data;
    if(!blk_fs_request(req))
    {
    printk(KERN_NOTICE "Skip non-fs request ");
    __blk_end_request_all(req,0);
    continue;
    }
    sbull_transfer(dev,blk_rq_pos(req),blk_rq_cur_sectors(req),req->buffer,rq_data_dir(req));
    if( !__blk_end_request_cur(req,0))
    {
    req = blk_fetch_request(q);
    }
    }
    }

    static struct block_device_operations sbull_ops =
    {
    .owner = THIS_MODULE,
    .open = sbull_open,
    .release= sbull_release,
    .ioctl = sbull_ioctl,
    };

    static int __init sbull_init(void)
    {
    //注册块设备驱动程序
    sbull_major = register_blkdev(sbull_major,"sbull");
    if(sbull_major <= 0)
    {
    printk(KERN_WARNING "unable to get major number ");
    return -EBUSY;
    }

    Devices = kmalloc(sizeof(struct sbull_dev),GFP_KERNEL);
    if(Devices == NULL)
    goto out_unregister;
    memset(Devices,0,sizeof(struct sbull_dev));

    //初始化sbull_dev数据结构
    Devices->size = nsectors * hardsect_size;
    Devices->data = vmalloc(Devices->size);
    if(Devices->data == NULL)
    {
    printk(KERN_NOTICE "vmalloc failure. ");
    goto out_kfree;
    }
    memset(Devices->data,0,Devices->size);
    //对自旋锁进行分配和初始化
    spin_lock_init(&Devices->lock);

    //分配请求队列
    Devices->queue = blk_init_queue(sbull_request,&Devices->lock);
    if(Devices->queue == NULL)
    {
    printk(KERN_NOTICE "request queue error");
    goto out_vfree;
    }
    //设置扇区大小
    blk_queue_logical_block_size(Devices->queue, hardsect_size);
    //分配、初始化及安装相应的gendisk结构
    Devices->gd = alloc_disk(1);
    if( !Devices->gd )
    {
    printk(KERN_NOTICE "alloc_disk failure ");
    goto out_vfree;
    }
    Devices->gd->major = sbull_major;
    Devices->gd->first_minor = 0;
    Devices->gd->fops = &sbull_ops;
    Devices->gd->queue = Devices->queue;
    Devices->gd->private_data = Devices;
    strcpy(Devices->gd->disk_name,"sbull0");
    set_capacity(Devices->gd,nsectors * (hardsect_size / KERN_SECTOR_SIZE));
    add_disk(Devices->gd);
    return 0;

    out_vfree:
    vfree(Devices->data);
    out_kfree:
    kfree(Devices);
    out_unregister:
    unregister_blkdev(sbull_major,"sbull");
    return -ENOMEM;
    }

    static void __exit sbull_exit(void)
    {
    struct sbull_dev *dev = Devices;
    if(dev->gd)
    {
    del_gendisk(dev->gd);
    put_disk(dev->gd);
    printk("Release gendisk success. ");
    }
    if(dev->queue)
    {
    blk_cleanup_queue(dev->queue);
    printk("rmmod module success. ");
    }
    if(dev->data)
    {
    vfree(dev->data);
    printk("Release diskdata success. ");
    }
    unregister_blkdev(sbull_major,"sbull");
    printk("Blockdevice unregister success. ");
    kfree(Devices);
    }

    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_AUTHOR("LvYongQiang");
    module_init(sbull_init);
    module_exit(sbull_exit);

    ifndef _SBULL_H

    define _SBULL_H

    include <linux/types.h>

    include <linux/ioctl.h>

    include <linux/fcntl.h>

    define SBULL_MAJOR 0

    define KERN_SECTOR_SIZE 512

    //定义幻数

    define SBULL_IOC_MAGIC 'x'

    //定义命令

    define SBULL_IOCGETMAJOR _IOR(SBULL_IOC_MAGIC,1,int)

    define SBULL_IOCGETSECTORS _IOR(SBULL_IOC_MAGIC,2,int)

    define SBULL_IOCGETSIZE _IOR(SBULL_IOC_MAGIC,3,int)

    define SBULL_IOC_MAXNR 3

    endif

  • 相关阅读:
    第009讲:了不起的分支和循环3
    Term_Application
    十大编程算法助程序员走上高手之路
    每天工作4小时的程序员
    编程真相_节选
    Sublime_Snippet
    VIM资源管理
    微信企业号开发资源整理
    vitruviano
    VIM_git
  • 原文地址:https://www.cnblogs.com/xiaoran991/p/13678210.html
Copyright © 2011-2022 走看看