本文共 4247 字,大约阅读时间需要 14 分钟。
下面的程序可以在linux2.6内核直接读写硬盘的指定扇区,也是根据网上一个朋友的做法做了修改的;
有两个不是很明白的地方就是:1、bd_claim函数的使用,这个是个递归函数,像是匹配内存指针和设备,但是调用会返回错误;2、bdev = open_by_devnum(0x00800000, FMODE_READ | FMODE_WRITE); 中0x00800000数字的确认,不知从何而来:
#include <linux/module.h>
#include <linux/init.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/buffer_head.h>#include <linux/blkdev.h>#include <linux/msdos_fs.h>#include <linux/fcntl.h>#include <linux/delay.h>static int set_size = 512;
static int nr = 0;static char pages_addr[PAGE_SIZE];
static char pages_write_addr[PAGE_SIZE];module_param(set_size,int,S_IRUGO);
MODULE_PARM_DESC(set_size,"how many bytes you want to read,not more than 4096");module_param(nr,long,S_IRUGO);
MODULE_PARM_DESC(nr,"which sectors you want to read");MODULE_LICENSE("GPL");
static struct block_device *bdev;
static char *usage = "You can change the value:set_size nr devn";int bdev_write_one_page(struct block_device *bdev, unsigned long blocknr, void *page_addr)
{ int ret = -1; struct buffer_head *bh; if (!bdev || !page_addr) { printk("%s error ", __func__); return -1; } bh = __getblk(bdev, blocknr, PAGE_SIZE); if (!bh) { printk("get blk failed "); return -1; } memcpy(bh->b_data, page_addr, PAGE_SIZE); mark_buffer_dirty(bh); ll_rw_block(WRITE, 1, &bh); brelse(bh); ret = 0; return ret;}int bdev_read_one_page(struct block_device *bdev, unsigned long blocknr, void *page_addr)
{ int ret = -1; struct buffer_head *bh; if (!bdev || !page_addr) { printk("%s error ", __func__); return -1; }bh = __getblk(bdev, blocknr, PAGE_SIZE);
if (!bh) { printk("get blk failed "); return -1; }if (!buffer_uptodate(bh))
{ ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) { ret = -1; goto out; } } memcpy(page_addr, bh->b_data, PAGE_SIZE); ret = 0;out:
brelse(bh);return ret;
}void block_test(void)
{ struct block_device *bdev;// void *pages_addr = (void *)kmalloc(2048,GFP_KERNEL); void *holder = (void *)pages_addr; int cnt, ret; int blocknr; //bdev = bdget(MKDEV(16, 0)); int i = 0; printk("block_test:IN ---------2010-03-22\n"); //memset(pages_addr,0x00,sizeof(pages_addr)); printk("pages_addr:%x\n",pages_addr); printk("holder:%x\n",holder);#if 1 bdev = open_by_devnum(0x00800000, FMODE_READ | FMODE_WRITE); // bdev=0x800; if (IS_ERR(bdev)) { printk("bdget error, bdev=%08lx \n", (unsigned long)bdev); return; } printk("bdev:%x\n",bdev); bdev->bd_holder = holder;#if 0 if (bd_claim(bdev, holder)) { printk("claim failed \n"); goto out_bdev; } printk("after bd_claim\n");#endif #if 0// blocknr = *(unsigned long *)(pages_addr + 0x100000); //for (cnt = 0; cnt < 10 * 1024; cnt++, blocknr++) { printk("nr=%d\n",nr); memset(pages_addr,0xff,PAGE_SIZE); ret = bdev_read_one_page(bdev,nr, (void *)pages_addr); if (ret) printk("blk read failed ");}
printk("after bdev_read_one_page\n");// printk("get data:%0x,%0x\n,",pages_addr[510],pages_addr[511]); for( i = 0; i < 512; i++ ) { printk( "%02x ",(unsigned char)pages_addr[ i ] ); if(( i % 16 ) == 15) { printk( " \n" ); } } printk( " \n" );printk("nr=%d\n",nr);
memset(pages_write_addr,0xe7,PAGE_SIZE); ret = bdev_write_one_page(bdev,nr, (void *)pages_write_addr); if (ret) printk("blk write failed ");#endif { printk("nr=%d\n",nr); ret = bdev_read_one_page(bdev,nr, (void *)pages_addr); if (ret) printk("blk read failed ");}
printk("after bdev_read_one_page\n");// printk("get data:%0x,%0x\n,",pages_addr[510],pages_addr[511]); for( i = 0; i < 512; i++ ) { printk( "%02x ",(unsigned char)pages_addr[ i ] ); if(( i % 16 ) == 15) { printk( " \n" ); } } printk( " \n" );out_bdev:
// bd_release(bdev); // blkdev_put(bdev,FMODE_READ | FMODE_WRITE); blkdev_put(bdev);#endif return;}static int __init disk_rw_init(void){ // nr = 0;// set_size = PAGE_SIZE;block_test();
return 0;
}static void __exit disk_rw_exit(void){ printk("disk_rw_exit\n"); }module_init(disk_rw_init);
module_exit(disk_rw_exit);
Makefile:
ifneq ($(KERNELRELEASE),)
obj-m:=hw_disk_rw26.oelse KDIR =/usr/src/linux-2.6.33# KDIR = /usr/src/kernels/2.6.9-5.EL-i686 PWD:=$(shell pwd)default: $(MAKE) -C $(KDIR) M=$(PWD) modulesinstall: insmod hw_disk_rw26.kouninstall: rmmod hw_disk_rw26.koclean: $(MAKE) -C $(KDIR) M=$(PWD) cleanendif
转载地址:http://aggjx.baihongyu.com/