本文代码参考《LINUX设备驱动程序》第十六章 块设备驱动程序

本文中的“块设备”是一段大小为PAGE_SIZE的内存空间(两个扇区,每个扇区512字节)

功能:向块设备中输入内容,从块设备中读出内容
注:ldd自带块设备驱动源码在2.6.32内核的发行版上编译时会提示很多API未定义,原因是kernel 2.6中block layer API已经变更了很多,本文的程序参考了http://hi.baidu.com/casualfish/item/7931bbb58925fb951846977d,感谢!
 
代码:
1. sbull.c
 #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/timer.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;
static int hardsect_size = SBULL_HARDSECT;
static int nsectors = ;
module_param(sbull_major, int, );
module_param(hardsect_size, int, );
module_param(nsectors, int, ); struct sbull_dev {
int size;
u8 *data;
short users;
spinlock_t lock;
struct request_queue *queue;
struct gendisk *gd;
}; static struct sbull_dev *device = NULL; static void sbull_transfer(struct sbull_dev *dev, unsigned long sector, unsigned long nsect, char *buffer, int write)
{
unsigned long offset = sector*KERNEL_SECTOR_SIZE;
unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE; if ((offset+nbytes) > dev->size)
{
return;
} if (write)
{
memcpy(dev->data+offset, buffer, nbytes);
}
else
{
memcpy(buffer, dev->data+offset, nbytes);
}
} static int sbull_xfer_bio(struct sbull_dev *dev, struct bio *bio)
{
int i;
struct bio_vec *bvec;
sector_t sector = bio->bi_sector; bio_for_each_segment(bvec, bio, i)
{
char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);
sbull_transfer(dev, sector, bio_cur_bytes(bio)>>, buffer, bio_data_dir(bio) == WRITE);
sector += bio_cur_bytes(bio)>>;
__bio_kunmap_atomic(bio, KM_USER0);
}
return ;
} static int sbull_xfer_request(struct sbull_dev *dev, struct request *req)
{
struct bio *bio;
int nsect = ; __rq_for_each_bio(bio, req) {
sbull_xfer_bio(dev, bio);
nsect += bio->bi_size/KERNEL_SECTOR_SIZE;
}
return nsect;
} static void sbull_full_request(struct request_queue *q)
{
struct request *req;
int sectors_xferred;
struct sbull_dev *dev = q->queuedata; while((req = blk_fetch_request(q)) != NULL)
{
if (req->cmd_type != REQ_TYPE_FS)
{
__blk_end_request_all(req, -EIO);
continue;
} sectors_xferred = sbull_xfer_request(dev, req); __blk_end_request_cur(req, );
}
} static int sbull_open(struct block_device *device, fmode_t mode)
{
struct sbull_dev *dev = device->bd_disk->private_data; spin_lock(&dev->lock);
dev->users++;
spin_unlock(&dev->lock);
return ;
} static int sbull_release(struct gendisk *disk, fmode_t mode)
{
struct sbull_dev *dev = disk->private_data; spin_lock(&dev->lock);
dev->users--;
spin_unlock(&dev->lock); return ;
} static struct block_device_operations sbull_ops = {
.owner = THIS_MODULE,
.open = sbull_open,
.release = sbull_release,
}; static void setup_device(struct sbull_dev *dev)
{
memset(dev, , sizeof(struct sbull_dev));
dev->size = nsectors*hardsect_size;
dev->data = vmalloc(dev->size);
if (dev->data == NULL)
{
return;
} spin_lock_init(&dev->lock); dev->queue = blk_init_queue(sbull_full_request, &dev->lock);
if (dev->queue == NULL)
{
goto out_vfree;
} blk_queue_logical_block_size(dev->queue, hardsect_size);
dev->queue->queuedata = dev; dev->gd = alloc_disk();
if (!dev->gd)
{
goto out_vfree;
} dev->gd->major = sbull_major;
dev->gd->first_minor = ;
dev->gd->fops = &sbull_ops;
dev->gd->queue = dev->queue;
dev->gd->private_data = dev;
snprintf(dev->gd->disk_name, , "sbull");
set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));
add_disk(dev->gd); return; out_vfree:
if (dev->data)
{
vfree(dev->data);
}
} static int __init sbull_init(void)
{
sbull_major = register_blkdev(sbull_major, "sbull");
if (sbull_major <= )
{
return -EBUSY;
} device = kmalloc(sizeof(struct sbull_dev), GFP_KERNEL);
if (device == NULL)
{
goto out_unregister;
} setup_device(device); return ; out_unregister:
unregister_blkdev(sbull_major, "sbull");
return -ENOMEM;
} static void sbull_exit(void)
{
struct sbull_dev *dev = device; if (dev->gd)
{
del_gendisk(dev->gd);
put_disk(dev->gd);
} if (dev->queue)
{
blk_cleanup_queue(dev->queue);
} if (dev->data)
{
vfree(dev->data);
} unregister_blkdev(sbull_major, "sbull");
kfree(device);
} module_init(sbull_init);
module_exit(sbull_exit);
MODULE_LICENSE("GPL");

2. sbull.h

 #ifndef _SBULL_H
#define _SBULL_H #define SBULL_MAJOR 0
#define SBULL_HARDSECT 512 #define KERNEL_SECTOR_SIZE 512 #endif

3. Makefile

 obj-m += sbull.o

 CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/kernels/$(LINUX_KERNEL) all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

4. 验证效果

1)#make

2)#insmod sbull.ko

3)#ls /dev/    //会显示sbull

4)#ls -lh /tmp/test1

-rw-r--r--. 1 root root 4.3k Dec 2 20:47 test1

5)#dd if=/tmp/test1 of=/dev/sbull bs=512 count=2    //将test1中两个扇区的内容输入到块设备sbull中

6)#dd if=/dev/sbull of=/tmp/test2 bs=512 count=2    //将块设备sbull中两个扇区的内容输入到临时文件test2中

7)#ls -lh /tmp/test2

-rw-r--r--. 1 root root 1.0k Dec 2 21:19 test2

8)#vim test2    //test2中的内容跟test1前1024个字节的内容相同

简单linux块设备驱动程序的更多相关文章

  1. (linux)块设备驱动程序

      1.4.1  Linux块设备驱动程序原理(1) 顾名思义,块设备驱动程序就是支持以块的方式进行读写的设备.块设备和字符设备最大的区别在于读写数据的基本单元不同.块设备读写数据的基本单元为块,例如 ...

  2. 简单linux字符设备驱动程序

    本文代码参考<LINUX设备驱动程序>第三章 字符设备驱动程序 本文中的“字符设备”是一段大小为PAGE_SIZE的内存空间 功能:向字符设备写入字符串:从字符设备读出字符串 代码: 1. ...

  3. 《Linux Device Drivers》第十六章 块设备驱动程序——note

    基本介绍 块设备驱动程序通过主传动固定大小数据的随机访问设备 Linux核心Visual块设备作为基本设备和不同的字符设备类型 Linux块设备驱动程序接口,使块设备最大限度地发挥其效用.一个问题 一 ...

  4. linux系统下块设备驱动程序

    顾名思义,块设备驱动程序就是支持以块的方式进行读写的设备.块设备和字符设备最大的区别在于读写数据的基本单元不同.块设备读写数据的基本单元为块,例 如磁盘通常为一个sector,而字符设备的基本单元为字 ...

  5. 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入

    字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...

  6. Linux中块设备驱动程序分析

    基于<Linux设备驱动程序>书中的sbull程序以对Linux块设备驱动总结分析. 開始之前先来了解这个块设备中的核心数据结构: struct sbull_dev {         i ...

  7. 深入理解Linux内核-块设备驱动程序

    扇区: 1.硬盘控制器将磁盘看成一大组扇区2.扇区就是一组相邻字节3.扇区按照惯例大小设置位512字节4.存放在块设备中的数据是通过它们在磁盘上的位置来标识,即首个扇区的下标和扇区的数目.5.扇区是硬 ...

  8. Linux 0.11源码阅读笔记-块设备驱动程序

    块设备驱动程序 块设备驱动程序负责实现对块设备数据的读写功能.内核代码统一使用缓冲块间接和块设备(如磁盘)交换数据,缓冲区数据通过块设备驱动程序和块设备交换数据. 块设备的管理 块设备表 内核通过一张 ...

  9. Linux块设备驱动(一) _驱动模型

    块设备是Linux三大设备之一,其驱动模型主要针对磁盘,Flash等存储类设备,本文以3.14为蓝本,探讨内核中的块设备驱动模型 框架 下图是Linux中的块设备模型示意图,应用层程序有两种方式访问一 ...

随机推荐

  1. bootstrap-下拉菜单

    <!-- 1.给父级添加class为dropdown,或者给父级添加定位属性 2.给button添加data-toggle="dropdown"属性,并添加dropdown- ...

  2. rails4.2.6配置发送邮件

    调试了很久,最后终于可以发送了 1 在config/environments/development.rb文件里配置邮件信息 config.action_mailer.raise_delivery_e ...

  3. Dede cms文章内容管理系统安全漏洞!如何有效防止DEDE织梦系统被挂木马安全设置

    第一.安装Dede的时候数据库的表前缀,最好改一下,不要用dedecms默认的前缀dede_,可以改成ljs_,随便一个无规律的.难猜到的前缀即可. 第二.后台登录一定要开启验证码功能,将默认管理员a ...

  4. C++学习18 派生类的析构函数

    和构造函数类似,析构函数也是不能被继承的. 创建派生类对象时,构造函数的调用顺序和继承顺序相同,先执行基类构造函数,然后再执行派生类的构造函数.但是对于析构函数,调用顺序恰好相反,即先执行派生类的析构 ...

  5. 运行测试Caused by: java.lang.UnsatisfiedLinkError: no attach in java.library.path错误解决

    解决办法:看到错误里面有个Caused by,说我的jdk运行到了32位的了,于是我查看环境变量,发现是昨天设置成32位的没有设置回来,于是设置回64位的jdk就ok了

  6. rman异机恢复(RAC双节点恢复到单节点)

    一.数据库全备 RUN {ALLOCATE CHANNEL ch00 DEVICE TYPE disk;ALLOCATE CHANNEL ch01 DEVICE TYPE disk;backup as ...

  7. Sqlserver中存储过程,触发器,自定义函数(二)

    Sqlserver中存储过程,触发器,自定义函数: 自定义函数:1.函数类型:2.函数的参数和返回值: 1.函数类型:标量值函数,返回的是一个标量值表值函数:内联表值函数:多语句表值函数. 标量值函数 ...

  8. java静态内部类

    public class StaticInnerClass {        int x=100;    static class inner{        void doitInner()     ...

  9. FileZilla - Windows XP经典软件系列

    官网: https://filezilla-project.org/ 下载: http://sourceforge.net/projects/filezilla/ 版本:V3.9.0.1 (支持XP最 ...

  10. 带你快速了解CODESOFT 2015

    CODESOFT是知名的条码标签设计打印软件,现在又推出了最新版CODESOFT 2015,其新功能.大改进让人为之一振.下面跟随小编的脚步,走进CODESOFT 2015,看一看CODESOFT 2 ...