下面的程式可以在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 ");
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)
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);
out:
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
// 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
out_bdev:
// bd_release(bdev);
// blkdev_put(bdev,fmode_read | fmode_write);
blkdev_put(bdev);
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.o
else
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) modules
install:
insmod hw_disk_rw26.ko
uninstall:
rmmod hw_disk_rw26.ko
clean:
$(make) -c $(kdir) m=$(pwd) clean
endif