千家信息网

Linux中块设备驱动代码编写的示例分析

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章将为大家详细讲解有关Linux中块设备驱动代码编写的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。为了将block和fs分开,kernel的设计者定
千家信息网最后更新 2026年11月02日Linux中块设备驱动代码编写的示例分析

这篇文章将为大家详细讲解有关Linux中块设备驱动代码编写的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

为了将block和fs分开,kernel的设计者定义了request queue这一种形式。换一句话说,所有fs对block设备的请求,最终都会转变为request的形式。所以,对于block设备驱动开发的朋友来说,处理好了request queue就掌握了block设备的一半。当然,block设备很多,hd、floppy、ram都可以这么来定义,有兴趣的朋友可以在drivers/block寻找相关的代码来阅读。兴趣没有那么强的同学,可以看看我们这篇博文,基本上也能学个大概。有个基本的概念,再加上一个简单浅显的范例,对于一般的朋友来说,已经足够了。

闲话不多说,我们看看一个ramdisk代码驱动是怎么写的,代码来自《深入linux 设备驱动程序内核机制》,

#include  #include  #include   #include  #include  #include  #include  #include  #include   #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文件试试了,是不是很简单。

关于"Linux中块设备驱动代码编写的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

设备 代码 驱动 朋友 处理 设备驱动 文件 篇文章 示例 分析 兴趣 形式 更多 系统 面的 生成 不错 实用 浅显 一句话 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 南京欣网互联网络科技 广东万易互联网科技有限公司惠州分公司 上海睿民互联网科技有限公司 广州淘业互联网络科技 互联网巨头反垄断金融科技 互联网科技社 互联网公司 科技公司 互联网养老 桔豆科技 四个字互联网科技公司取名 济南和联互联网科技有限公司 欧洲十大科技互联网公司 世界互联网科技公司市值排名 中国航天科技大学国际工业互联网 开一家科技互联网公司需要多少钱 互联网金融科技公司的优势 电子商务与互联网科技的关系 广东鹅鹅鹅互联网科技有限公司 互联网时代科技型公司的机会 互联网科技的前景 上海互联网科技园景观 咖啡 高科技互联网 互联网科技工作委员会毛军 新华互联网科技学校 兼蜜互联网科技 互联网科技实习生岗位职责 厦门千工互联网科技有限公司 电子科技大学互联网创业大赛 互联网第三次科技革命特征 江苏互联网智能科技软件
0