国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 服務器 > Web服務器 > 正文

Linux 塊設備驅動代碼編寫

2024-09-01 13:54:35
字體:
來源:轉載
供稿:網友

按照ldd的說法,linux的設備驅動包括了char,block,net三種設備。char設備是比較簡單的,只要分配了major、minor號,就可以進行讀寫處理了。相對而言,block和net要稍微復雜些。net設備姑且按下不談,我們在以后的博文中會有涉及。今天,我們可以看看一個簡單的block是怎么設計的。

為了將block和fs分開,kernel的設計者定義了request queue這一種形式。換一句話說,所有fs對block設備的請求,最終都會轉變為request的形式。所以,對于block設備驅動開發的朋友來說,處理好了request queue就掌握了block設備的一半。當然,block設備很多,hd、floppy、ram都可以這么來定義,有興趣的朋友可以在drivers/block尋找相關的代碼來閱讀。興趣沒有那么強的同學,可以看看我們這篇博文,基本上也能學個大概。有個基本的概念,再加上一個簡單淺顯的范例,對于一般的朋友來說,已經足夠了。

閑話不多說,我們看看一個ramdisk代碼驅動是怎么寫的,代碼來自《深入linux 設備驅動程序內核機制》,

#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h>  #include <linux/fs.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/vmalloc.h> #include <linux/blkdev.h> #include <linux/hdreg.h>  #define RAMHD_NAME "ramhd" #define RAMHD_MAX_DEVICE 2 #define RAMHD_MAX_PARTITIONS 4  #define RAMHD_SECTOR_SIZE 512 #define RAMHD_SECTORS 16 #define RAMHD_HEADS 4 #define RAMHD_CYLINDERS 256  #define RAMHD_SECTOR_TOTAL (RAMHD_SECTORS * RAMHD_HEADS *RAMHD_CYLINDERS) #define RAMHD_SIZE (RAMHD_SECTOR_SIZE * RAMHD_SECTOR_TOTAL) //8mb  typedef struct {   unsigned char* data;   struct request_queue* queue;   struct gendisk* gd; }RAMHD_DEV;  static char* sdisk[RAMHD_MAX_DEVICE] = {NULL}; static RAMHD_DEV* rdev[RAMHD_MAX_DEVICE] = {NULL};  static dev_t ramhd_major;  static int ramhd_space_init(void) {   int i;   int err = 0;   for(i = 0; i < RAMHD_MAX_DEVICE; i++){     sdisk[i] = vmalloc(RAMHD_SIZE);     if(!sdisk[i]){       err = -ENOMEM;       return err;     }          memset(sdisk[i], 0, RAMHD_SIZE);   }      return err; }  static void ramhd_space_clean(void) {   int i;   for(i = 0; i < RAMHD_MAX_DEVICE; i++){     vfree(sdisk[i]);   } }  static int ramhd_open(struct block_device* bdev, fmode_t mode) {   return 0; }  static int ramhd_release(struct gendisk*gd, fmode_t mode) {   return 0; }  static int ramhd_ioctl(struct block_device* bdev, fmode_t mode, unsigned int cmd, unsigned long arg) {   int err;   struct hd_geometry geo;      switch(cmd)   {     case HDIO_GETGEO:       err = !access_ok(VERIFY_WRITE, arg, sizeof(geo));       if(err)         return -EFAULT;                geo.cylinders = RAMHD_CYLINDERS;       geo.heads = RAMHD_HEADS;       geo.sectors = RAMHD_SECTORS;       geo.start = get_start_sect(bdev);              if(copy_to_user((void*)arg, &geo, sizeof(geo)))         return -EFAULT;              return 0;   }      return -ENOTTY; }  static struct block_device_operations ramhd_fops = {   .owner = THIS_MODULE,   .open = ramhd_open,   .release = ramhd_release,   .ioctl = ramhd_ioctl, };  static int ramhd_make_request(struct request_queue* q, struct bio* bio) {   char* pRHdata;   char* pBuffer;   struct bio_vec* bvec;   int i;   int err = 0;      struct block_device* bdev = bio->bi_bdev;   RAMHD_DEV* pdev = bdev->bd_disk->private_data;      if(((bio->bi_sector * RAMHD_SECTOR_SIZE) + bio->bi_size) > RAMHD_SIZE){     err = -EIO;     return err;   }      pRHdata = pdev->data + (bio->bi_sector * RAMHD_SECTOR_SIZE);   bio_for_each_segment(bvec, bio, i){     pBuffer = kmap(bvec->bv_page) + bvec->bv_offset;     switch(bio_data_dir(bio)){       case READ:         memcpy(pBuffer, pRHdata, bvec->bv_len);         flush_dcache_page(bvec->bv_page);         break;                case WRITE:         flush_dcache_page(bvec->bv_page);         memcpy(pRHdata, pBuffer, bvec->bv_len);         break;                default:         kunmap(bvec->bv_page);         goto out;     }          kunmap(bvec->bv_page);     pRHdata += bvec->bv_len;   }    out:   bio_endio(bio, err);   return 0; }  static int alloc_ramdev(void) {   int i;   for(i = 0; i < RAMHD_MAX_DEVICE; i++){     rdev[i] = kzalloc(sizeof(RAMHD_DEV), GFP_KERNEL);     if(!rdev[i]){       return -ENOMEM;     }   }      return 0; }  static void clean_ramdev(void) {   int i;      for(i = 0; i < RAMHD_MAX_DEVICE; i++){     if(rdev[i])       kfree(rdev[i]);   } }  static int __init ramhd_init(void) {   int i;      ramhd_space_init();   alloc_ramdev();      ramhd_major = register_blkdev(0, RAMHD_NAME);      for(i = 0; i < RAMHD_MAX_DEVICE; i++){     rdev[i]->data = sdisk[i];     rdev[i]->queue = blk_alloc_queue(GFP_KERNEL);     blk_queue_make_request(rdev[i]->queue, ramhd_make_request);          rdev[i]->gd = alloc_disk(RAMHD_MAX_PARTITIONS);     rdev[i]->gd->major = ramhd_major;     rdev[i]->gd->first_minor = i * RAMHD_MAX_PARTITIONS;     rdev[i]->gd->fops = &ramhd_fops;     rdev[i]->gd->queue = rdev[i]->queue;     rdev[i]->gd->private_data = rdev[i];     sprintf(rdev[i]->gd->disk_name, "ramhd%c", 'a' +i);     rdev[i]->gd->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;     set_capacity(rdev[i]->gd, RAMHD_SECTOR_TOTAL);     add_disk(rdev[i]->gd);   }      return 0; }  static void __exit ramhd_exit(void) {   int i;   for(i = 0; i < RAMHD_MAX_DEVICE; i++){     del_gendisk(rdev[i]->gd);     put_disk(rdev[i]->gd);     blk_cleanup_queue(rdev[i]->queue);   }      clean_ramdev();   ramhd_space_clean();   unregister_blkdev(ramhd_major, RAMHD_NAME); }  module_init(ramhd_init); module_exit(ramhd_exit);  MODULE_AUTHOR("dennis__chen@ AMDLinuxFGL"); MODULE_DESCRIPTION("The ramdisk implementation with request function"); MODULE_LICENSE("GPL"); 

為了大家方便,順便也把Makefile放出來,看過前面blog的朋友都知道,這其實很簡單,

ifneq ($(KERNELRELEASE),) obj-m := ramdisk.o  else PWD := $(shell pwd) KVER := $(shell uname -r) KDIR := /lib/modules/$(KVER)/build all:   $(MAKE) -C $(KDIR) M=$(PWD) modules clean:   rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.* Module.* endif 

這段代碼究竟有沒有用呢?可以按照下面的步驟來做,

    a)make 一下,生成ramdisk.ko;

    b)編譯好了之后,就可以安裝驅動了,在linux下是這么做的,sudo insmod ramdisk.ko;

    c)安裝好了,利用ls /dev/ramhd*, 就會發現在/dev下新增兩個結點,即/dev/ramhda和/dev/ramhdb;

    d)不妨選擇其中一個節點進行分區處理, sudo fdisk /dev/ramhda,簡單處理的話就建立一個分區, 生成/dev/ramhda1;

    e)創建文件系統,sudo mkfs.ext3 /dev/ramhda1;

    f)有了上面的文件系統,就可以進行mount處理,不妨sudo mount /dev/ramhda1 /mnt;

    g)上面都弄好了,大家就可以copy、delete文件試試了,是不是很簡單。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到服務器教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 梧州市| 白水县| 翁牛特旗| 芮城县| 马龙县| 当雄县| 八宿县| 土默特左旗| 长岭县| 南郑县| 项城市| 长子县| 成武县| 桃园县| 依兰县| 县级市| 鄂州市| 青田县| 梁山县| 常州市| 靖州| 墨竹工卡县| 静乐县| 墨玉县| 磴口县| 定州市| 阜新| 大余县| 康保县| 隆安县| 镇赉县| 海伦市| 邵阳市| 富民县| 邳州市| 斗六市| 临汾市| 江永县| 抚宁县| 韶关市| 旬邑县|