<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 塊設備驅(qū)動程序的編寫驅(qū)動之用內(nèi)存模擬磁盤

          塊設備驅(qū)動程序的編寫驅(qū)動之用內(nèi)存模擬磁盤

          作者: 時間:2016-11-21 來源:網(wǎng)絡 收藏
          // 參考:
          // driversblockxd.c
          // driversblockz2ram.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
          #include
          #include
          static struct gendisk *ramblock_disk;
          static request_queue_t *ramblock_queue;
          static int major;
          static DEFINE_SPINLOCK(ramblock_lock);
          #define RAMBLOCK_SIZE (1024*1024)
          static unsigned char *ramblock_buf;
          static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
          {
          // 容量=heads*cylinders*sectors*512
          geo->heads = 2;
          geo->cylinders = 32;
          geo->sectors = RAMBLOCK_SIZE/2/32/512;
          return 0;
          }
          static struct block_device_operations ramblock_fops = {
          .owner = THIS_MODULE,
          .getgeo = ramblock_getgeo,
          };
          static void do_ramblock_request(request_queue_t * q)
          {
          static int r_cnt = 0;
          static int w_cnt = 0;
          struct request *req;
          //printk("do_ramblock_request %dn", ++cnt);
          while ((req = elv_next_request(q)) != NULL) {
          // 數(shù)據(jù)傳輸三要素: 源,目的,長度
          // 源/目的:
          unsigned long offset = req->sector * 512;
          // 目的/源: (寫的時候buffer是源,讀的時候buffer是目的,從扇區(qū)里讀出來放在buffer里)
          // req->buffer
          // 長度:
          unsigned long len = req->current_nr_sectors * 512;
          if (rq_data_dir(req) == READ)
          {
          //如果是操作硬盤的話在這個位置放置讀取硬盤的函數(shù)就可以了
          //printk("do_ramblock_request read %dn", ++r_cnt);
          memcpy(req->buffer, ramblock_buf+offset, len);
          }
          else
          {
          //如果是操作硬盤的話在這個位置放置寫硬盤的函數(shù)就可以了
          //printk("do_ramblock_request write %dn", ++w_cnt);
          memcpy(ramblock_buf+offset, req->buffer, len);
          }
          end_request(req, 1);
          }
          }
          static int ramblock_init(void)
          {
          // 1. 分配一個gendisk結(jié)構(gòu)體
          ramblock_disk = alloc_disk(16); // 次設備號個數(shù): 分區(qū)個數(shù)+1 ,表示有15個分區(qū)
          // 2. 設置
          // 2.1 分配/設置隊列: 提供讀寫能力
          ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);//do_ramblock_request隊列處理函數(shù)
          ramblock_disk->queue = ramblock_queue;
          // 2.2 設置其他屬性: 比如容量
          major = register_blkdev(0, "ramblock"); // cat /proc/devices
          ramblock_disk->major = major;
          ramblock_disk->first_minor = 0;
          sprintf(ramblock_disk->disk_name, "ramblock");
          ramblock_disk->fops = &ramblock_fops;
          set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512); //在內(nèi)核里面對于文件系統(tǒng)那一層,認為 //扇區(qū)永遠是512字節(jié),即為扇區(qū)數(shù)
          //塊設備的操作是以扇區(qū)為單位的。
          // 3. 硬件相關操作
          ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
          // 4. 注冊
          add_disk(ramblock_disk);
          return 0;
          }
          static void ramblock_exit(void)
          {
          unregister_blkdev(major, "ramblock");
          del_gendisk(ramblock_disk);
          put_disk(ramblock_disk);
          blk_cleanup_queue(ramblock_queue);
          kfree(ramblock_buf);
          }
          module_init(ramblock_init);
          module_exit(ramblock_exit);
          MODULE_LICENSE("GPL");
          ==============================================================
          框架:
          app: open,read,write "1.txt"
          --------------------------------------------- 文件的讀寫
          文件系統(tǒng): vfat, ext2, ext3, yaffs2, jffs2 (把文件的讀寫轉(zhuǎn)換為扇區(qū)的讀寫)
          -----------------ll_rw_block----------------- 扇區(qū)的讀寫
          1. 不像字符設備那樣提供讀寫函數(shù),而是把"讀寫"放入隊列
          2. 調(diào)用隊列的處理函數(shù)(優(yōu)化/調(diào)順序/合并)后再執(zhí)行
          塊設備驅(qū)動程序
          ---------------------------------------------
          硬件: 硬盤,flash
          分析ll_rw_block
          for (i = 0; i < nr; i++) {
          struct buffer_head *bh = bhs[i];
          submit_bh(rw, bh);
          struct bio *bio; // 使用bh來構(gòu)造bio (block input/output)
          submit_bio(rw, bio);
          // 通用的構(gòu)造請求: 使用bio來構(gòu)造請求(request)
          generic_make_request(bio);
          __generic_make_request(bio);
          request_queue_t *q = bdev_get_queue(bio->bi_bdev); // 找到隊列
          // 調(diào)用隊列的"構(gòu)造請求函數(shù)"
          ret = q->make_request_fn(q, bio);
          // 默認的函數(shù)是__make_request
          __make_request
          // 先嘗試合并
          elv_merge(q, &req, bio);
          // 如果合并不成,使用bio構(gòu)造請求
          init_request_from_bio(req, bio);
          // 把請求放入隊列
          add_request(q, req);
          // 執(zhí)行隊列
          __generic_unplug_device(q);
          // 調(diào)用隊列的"處理函數(shù)"
          q->request_fn(q);
          怎么寫塊設備驅(qū)動程序呢?
          1. 分配gendisk: alloc_disk
          2. 設置
          2.1 分配/設置隊列: request_queue_t // 它提供讀寫能力
          blk_init_queue
          2.2 設置gendisk其他信息 // 它提供屬性: 比如容量
          3. 注冊: add_disk
          參考:
          driversblockxd.c
          driversblockz2ram.c
          測試3th,4th:
          在開發(fā)板上:
          1. insmod ramblock.ko
          2. 格式化: mkdosfs /dev/ramblock
          3. 掛接: mount /dev/ramblock /tmp/
          4. 讀寫文件: cd /tmp, 在里面vi文件
          5. cd /; umount /tmp/
          6.再次掛接: mount /dev/ramblock /tmp/,后查看文件還依然存在
          7. cat /dev/ramblock > /mnt/ramblock.bin
          8. 在PC上查看ramblock.bin
          sudo mount -o loop ramblock.bin /mnt
          測試5th:
          1. insmod ramblock.ko
          2. ls /dev/ramblock*
          3. fdisk /dev/ramblock
          注:
          1、對塊設備進行讀寫操作時可能不會立即響應,先放入隊列一段時間后一起執(zhí)行,如果想讓讀寫操作立即執(zhí)行可以運行:sync命令,即同步命令進行同步,此時會執(zhí)行沒有執(zhí)行的相關操作。
          2、對于磁盤容量=磁頭數(shù)*柱面數(shù)*扇區(qū)數(shù)*512,柱面數(shù)就是有多少環(huán),每個扇區(qū)512字節(jié)
          對于flash是有多少塊,每塊有多少扇區(qū),每個扇區(qū)可以存多少字節(jié)




          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();