linux2.6硬盘扇区直接读写程序

下面的程序可以在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.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

时间: 2024-11-12 11:40:40

linux2.6硬盘扇区直接读写程序的相关文章

C语言编写的bmp读写程序

C语言编写的bmp读写程序 建议先把bmp的数据存储格式了解下 [cpp] view plaincopy <span style="font-size:16px;">#include "Windows.h" #include "stdio.h" #include "string.h" #include "malloc.h" unsigned char *pBmpBuf;//读入图像数据的指针 i

分配粒度和内存页面大小(x86处理器平台的分配粒度是64K,内存页是4K,所以section都是0x1000对齐,硬盘扇区大小是512字节,所以PE文件默认文件对齐是0x200)

分配粒度和内存页面大小 x86处理器平台的分配粒度是64K,32位CPU的内存页面大小是4K,64位是8K,保留内存地址空间总是要和分配粒度对齐.一个分配粒度里包含16个内存页面. 这是个概念,具体不用自己操心,比如用VirtualAllocEx等函数,给lpAddress参数NULL系统就会自动找一个地方分配你要的内存空间.如果需要自己管理这个就累了...... 一个分配粒度是64K,这就是为什么Null指针区域和64K进入区域都是 64K的原因,刚好就是一个分配粒度.一个内存页是4K,这就是

How to fix &#39;sudo: no tty present and no askpass program&#39;以及硬盘序列号的读写

在调用system命令读写硬盘序列号的过程中遇到问题,报错如下: sudo: no tty present and no askpass program 发现此问题是由于帐号并没有开启免密码导致的 . 查找资料,解决方法如下: 方法一: sudo isudo 然后在最末尾添加: username ALL = NOPASSWD: /fullpath/to/command,/fullpath/to/othercommand eg: john ALL = NOPASSWD: /sbin/powerof

WIN32和Kernel)直接读写硬盘扇区

第一篇写技术的文章哦,以前好少写文章,我的文字表达很差劲,大家不要笑哦.前几天仙剑4通关了,感觉好惆怅,什么都不想去做.今天看了一下书发现一篇比较好玩的文章,于是自己静静地实践一番.文章是<基于硬盘保留扇区的软件保护方法(作者:熊志勇)>,内容是介绍了怎么读写硬盘保留扇区.以下是我的学习日记. 这里是摘自文章里的一个表:硬盘的总体结构***********************************************************************编号       名

硬盘扇区、柱面的基本知识;

转自:http://www.intohard.com/article-436-1.html 概述:本文介绍硬盘的扇区基本知识, 同时对逻辑扇区和物理扇区的概念做出说明 盘片上涉及的基本概念 整个硬盘上一般有很多的盘片组成,每个盘片如同切西瓜一样被"切"成一块一块的扇面,同时沿着半径的方向被划分成了很多同心圆,就是传说中的磁道,每条磁道被扇面切成很多的扇形区域叫做扇区(扇区是从磁盘读出和写入信息的最小单位,通常大小为512字节),不同盘片上的同半径磁道组成了柱面,这些都是磁盘物理上的概念

E2PROM芯片24C02的读写程序

一.实验目的: 给24C02的内部RAM写入一组数据0xb0,数据从24C02内部RAM的0x01开始存放.然后再把这组数据读出来,来点亮LED灯,检验写入和读出是否正确. 二.理论知识准备: 下面我们先介绍一下I2C总线的相关理论知识. (一).I2C总线概念 I2C总线是一种双向二线制总线,它的结构简单,可靠性和抗干扰性能好.目前很多公司都推出了基于I2C总线的外围器件,例如我们学习板上的24C02芯片,就是一个带有I2C总线接口的E2PROM存储器,具有掉电记忆的功能,方便进行数据的长期保

电脑中的文件是在硬盘扇区中存储的形式

在数据恢复的过程中,主要就是和数打交道的过程,所以有必要普及下数据进制的基础知识.由于计算机底层用二进制语言通信的,而二进制转换成16进制相对方便,所以我们在用磁盘编辑软件打开硬盘是大多数看到的都是十六进制格式的. 10进制 : 逢十进位有  0 1 2 3 4 5 6 7 8 9 2进制:逢二进位  只有0和1 两个数字 8进制:逢八进位 有0 1 2 3 4 5 6 7 八个数字 16进制:逢16进位  除了0-9 十个数字外.还有A B C D E F 六个字母 数的存储格式 数的存储格式

Mac-移动硬盘,优盘读写(NTFS for Mac)

最近一直在学习mac,真是让人头大,首先是不能从优盘或者硬盘拷贝进来,也不能拷贝出去.很多人推荐使用 NTFS for Mac.Tuxera NTFS for Mac.或者其他收费的,本博主囊中羞涩,只能使用免费的. 一.下载一款免费的挂载工具,mounty,官方网站:https://mounty.app/ 这是一个很神奇的网站,让我有了很好的体验,看官网肯定能让你完全学会怎么处理,感谢各位大佬的支持: 二.优盘.硬盘,以后一定要记住一点,尽量不要在windows操作系统或者其他操作系统直接拔出

Linux i2c 读写程序

/* This software uses a BSD license. Copyright (c) 2010, Sean Cross / chumby industriesAll rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: