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

简介: <p style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; line-height: 21px; color: rgb(50, 62, 50);

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

相关文章
|
3月前
|
安全 Linux Shell
Linux上执行内存中的脚本和程序
【9月更文挑战第3天】在 Linux 系统中,可以通过多种方式执行内存中的脚本和程序:一是使用 `eval` 命令直接执行内存中的脚本内容;二是利用管道将脚本内容传递给 `bash` 解释器执行;三是将编译好的程序复制到 `/dev/shm` 并执行。这些方法虽便捷,但也需谨慎操作以避免安全风险。
228 6
|
4月前
|
网络协议 Linux
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
727 2
|
4月前
|
Linux Python
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
75 2
|
2月前
|
运维 Java Linux
【运维基础知识】Linux服务器下手写启停Java程序脚本start.sh stop.sh及详细说明
### 启动Java程序脚本 `start.sh` 此脚本用于启动一个Java程序,设置JVM字符集为GBK,最大堆内存为3000M,并将程序的日志输出到`output.log`文件中,同时在后台运行。 ### 停止Java程序脚本 `stop.sh` 此脚本用于停止指定名称的服务(如`QuoteServer`),通过查找并终止该服务的Java进程,输出操作结果以确认是否成功。
81 1
|
3月前
|
消息中间件 分布式计算 Java
Linux环境下 java程序提交spark任务到Yarn报错
Linux环境下 java程序提交spark任务到Yarn报错
51 5
|
4月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
159 3
|
4月前
|
网络协议 Linux Shell
在Linux中,如何通过一个端口找到程序?
在Linux中,如何通过一个端口找到程序?
|
4月前
|
Linux API
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
|
3月前
|
Linux
linux内核 —— 读写信号量实验
linux内核 —— 读写信号量实验
|
4月前
|
Linux Windows Python
最新 Windows\Linux 后台运行程序注解
本文介绍了在Windows和Linux系统后台运行程序的方法,包括Linux系统中使用nohup命令和ps命令查看进程,以及Windows系统中通过编写bat文件和使用PowerShell启动隐藏窗口的程序,确保即使退出命令行界面程序也继续在后台运行。