• 块设备驱动框架分析(一)


    参考:写一个块设备驱动

    先上范例代码,用内存模拟块设备。内核模块加载后,测试信息如下:

    第94行    major = register_blkdev(0, "ramblock"); /* cat /proc/devices */

    第97行    sprintf(ramblock_disk->disk_name, "ramblock");/*ls -l /dev/ramblock*/

      1 #include <linux/module.h>
      2 #include <linux/moduleparam.h>
      3 #include <linux/init.h>
      4 
      5 #include <linux/sched.h>
      6 #include <linux/kernel.h> /* printk() */
      7 #include <linux/slab.h>   /* kmalloc() */
      8 #include <linux/fs.h>   /* everything... */
      9 #include <linux/errno.h> /* error codes */
     10 #include <linux/timer.h>
     11 #include <linux/types.h> /* size_t */
     12 #include <linux/fcntl.h> /* O_ACCMODE */
     13 #include <linux/hdreg.h> /* HDIO_GETGEO */
     14 #include <linux/kdev_t.h>
     15 #include <linux/vmalloc.h>
     16 #include <linux/genhd.h>
     17 #include <linux/blkdev.h>
     18 #include <linux/buffer_head.h> /* invalidate_bdev */
     19 #include <linux/bio.h>
     20 
     21 static struct gendisk * ramblock_disk;
     22 static struct request_queue  * ramblock_queue;
     23 
     24 static int major;
     25 
     26 static DEFINE_SPINLOCK(ramblock_lock);
     27 
     28 #define RAMBLOCK_SIZE (1024*1024)
     29 static unsigned char *ramblock_buf;
     30 
     31 static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
     32 {
     33     /* 容量=heads*cylinders*sectors*512 */
     34     geo->heads     = 2;
     35     geo->cylinders = 32;
     36     geo->sectors   = RAMBLOCK_SIZE/2/32/512;
     37     return 0;
     38 }
     39 
     40 
     41 static struct block_device_operations ramblock_fops = {
     42     .owner    = THIS_MODULE,
     43     .getgeo    = ramblock_getgeo,
     44 };
     45 
     46 static void do_ramblock_request(struct request_queue * q)
     47 {
     48     static int r_cnt = 0;
     49     static int w_cnt = 0;
     50     struct request *req;
     51     
     52     //printk("do_ramblock_request %d
    ", ++cnt);
     53 
     54     
     55     while ((req = blk_fetch_request(q))  != NULL) {
     56         /* 数据传输三要素: 源,目的,长度 */
     57         /* 源/目的: */
     58         unsigned long offset =blk_rq_pos(req) * 512;
     59 
     60         /* 目的/源: */
     61         // req->buffer
     62 
     63         /* 长度: */        
     64         unsigned long len =  blk_rq_cur_sectors(req) * 512;
     65 
     66         if (rq_data_dir(req) == READ)
     67         {
     68             printk("do_ramblock_request read %d
    ", ++r_cnt);
     69             memcpy(req->buffer, ramblock_buf+offset, len);
     70         }
     71         else
     72         {
     73             printk("do_ramblock_request write %d
    ", ++w_cnt);
     74             memcpy(ramblock_buf+offset, req->buffer, len);
     75         }        
     76         
     77         if(!__blk_end_request_cur(req, 0)) 
     78             break;
     79     }
     80 }
     81 
     82 
     83 static int ramblock_init(void)
     84 {
     85     /* 1. 分配一个gendisk结构体 */
     86     ramblock_disk = alloc_disk(16); /* 次设备号个数: 分区个数+1 */
     87 
     88     /* 2. 设置 */
     89     /* 2.1 分配/设置队列: 提供读写能力 */
     90     ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
     91     ramblock_disk->queue = ramblock_queue;
     92     
     93     /* 2.2 设置其他属性: 比如容量 */
     94     major = register_blkdev(0, "ramblock");  /* cat /proc/devices */    
     95     ramblock_disk->major       = major;
     96     ramblock_disk->first_minor = 0;
     97     sprintf(ramblock_disk->disk_name, "ramblock");/*ls -l /dev/ramblock*/
     98     ramblock_disk->fops        = &ramblock_fops;
     99     set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512);
    100 
    101     /* 3. 硬件相关操作 */
    102     ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
    103 
    104     /* 4. 注册 */
    105     add_disk(ramblock_disk);
    106 
    107     return 0;
    108 }
    109 
    110 static void ramblock_exit(void)
    111 {
    112     unregister_blkdev(major, "ramblock");
    113     del_gendisk(ramblock_disk);
    114     put_disk(ramblock_disk);
    115     blk_cleanup_queue(ramblock_queue);
    116 
    117     kfree(ramblock_buf);
    118 }
    119 
    120 module_init(ramblock_init);
    121 module_exit(ramblock_exit);
    122 MODULE_LICENSE("GPL");
  • 相关阅读:
    基于Maven的MyBatis Generator逆向工程
    JQuery对象调用reset方法:Uncaught TypeError: $(...).reset is not a function
    死锁编码及定位分析
    线程池的简介及底层原理
    转载:Mysql8.0忘记 root 密码, 如何修改?
    synchronized 和 Lock 有什么区别?
    java 中的阻塞队列及生产者-消费者中的简单应用
    java 中 CountDownLatch、CyclicBarrier 和 Semaphore 的简单使用
    java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
    Java 集合类的线程安全问题及解决方法
  • 原文地址:https://www.cnblogs.com/yangjiguang/p/6195543.html
Copyright © 2020-2023  润新知