- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
你好 stackoverflow。
想知道我在尝试直接从内核模块访问 block 设备时犯了什么错误。 (amd64 上的内核 3.7)
我使用 get_gendisk() 获取设备的 (struct gendisk*)。接下来,使用 bio_map_kern() 创建一个 bio,使用 bdget_disk() 将 block_device 添加到它,并使用 submit_bio() 发送它。 (见下面的代码)
在“sdb”上执行此操作时,它工作正常。在“loop0”或 ramdisk 设备上执行此操作时,它会因段错误而失败。故障归结为 generic_make_request_checks() 调用内联函数 bdev_get_queue(),它试图访问 block_device 结构中的“bd_disk”字段。
RIP: 0010:[] [] generic_make_request_checks+0x3e/0x2b1
当从“sdb”获取 block_device 时,bd_disk 被链接回设备的 gendisk 结构(在它的任何分区上)。在“loop0”设备上尝试相同操作时,此指针为零。但是 loop0 已正确设置,因为我可以使用它进行 mkfs、mount 或 dd。
关于如何设置简单数据读取的任何提示?干净和正确的方法?将 gendisk 指针添加到 block_device 不是一个好的解决方案,因为我不“拥有”这些结构。
也许这种方法都是错误的,我错过了一些简单的 read() 函数......:-)
调用堆栈(内核 3.7,amd64):
[<ffffffff812796f5>] generic_make_request_checks+0x3e/0x2b1
[<ffffffff8103c2b8>] ? console_trylock+0xf/0x47
[<ffffffff8103dad0>] ? vprintk_emit+0x3aa/0x3d0
[<ffffffff81279976>] ? generic_make_request+0xe/0xd5
[<ffffffff8127a75c>] ? submit_bio+0x10a/0x13b
[<ffffffffa02ad191>] ? init_tryKM2+0x16e/0x221 [tryKM2]
[<ffffffffa02ad023>] ? endFunc_tryKM2+0x23/0x23 [tryKM2]
[<ffffffff810020b6>] ? do_one_initcall+0x75/0x12b
[<ffffffff8107c9a3>] ? sys_init_module+0x105/0x251
[<ffffffff8145f1e9>] ? system_call_fastpath+0x16/0x1b
我尝试这个的测试代码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
#include <linux/bio.h>
#include <linux/completion.h>
typedef struct _drvDat
{
dev_t di;
struct gendisk *gd;
} drvDat;
#define printf(...) printk(KERN_ALERT "tryKM2: " __VA_ARGS__)
#define DEVNAME "loop0"
#define PARTITIONNO 0
static int init_tryKM2(void)
{
int dummy;
// init self
memset(&self,0,sizeof(self));
self.di = blk_lookup_devt(DEVNAME,0); // use partition zero here. gendisk handle is same anyway.
if(self.di==0)
return -1;
self.gd = get_gendisk(self.di,&dummy); // get_gendisk always gets the 'disk', even if dev_t points to a partition.
if(self.gd==0)
return -1;
// check if have partitions (this array always has at least one entry. That is same as &(self.gd->part0)
if(self.gd->part_tbl->len<1+PARTITIONNO)
{put_disk(self.gd);self.gd=0;return -1;}
readbytes_tryKM2(&self);
return 0;
}
static void endFunc_tryKM2(struct bio *bb, int err)
{
if(bb->bi_private)
complete( (struct completion*)(bb->bi_private) );
}
static void readbytes_tryKM2(drvDat *self)
{
struct bio *bb;
DECLARE_COMPLETION_ONSTACK(waithandle);
unsigned char *buf;
unsigned int i,j;
printf("readbytes_tryKM2\n");
buf = (unsigned char*)vmalloc(0x800);
memset( buf , 0xFE , 0x800 );
bb = bio_map_kern( self->gd->queue , buf , 0x400 , GFP_KERNEL );
if( IS_ERR(bb) )
{vfree(buf);return;}
bb->bi_sector = 0;
bb->bi_bdev = bdget_disk(self->gd,PARTITIONNO);
printf(" bi_bdev = %016lX\n",(unsigned long)(bb->bi_bdev));
printf(" bi_bdev->bd_disk = %016lX\n",(unsigned long)(bb->bi_bdev->bd_disk));
bb->bi_end_io = endFunc_tryKM2;
bb->bi_private = &waithandle;
printf(" send...\n");
submit_bio( 0 , bb );
printf(" wait...\n");
wait_for_completion(&waithandle);
printf(" done. flags=0x%X\n",(unsigned int)(bb->bi_flags));
if(!( bb->bi_flags & (1<<BIO_UPTODATE) ))
{bio_put(bb);vfree(buf);return;}
// just dump data... (misusing upper half of buffer)
for(i=0;i<0x400;i+=0x20)
{
for(j=0;j<0x20;j++)
snprintf( (char*)(buf+0x400+3*j) , 8 , "%02X " , (unsigned int)buf[i+j] );
buf[3*0x20-1]=0;
printf(" %s\n",buf+0x400);
}
bio_put(bb);
vfree(buf);
}
module_init(init_tryKM2);
module_exit(cleanup_tryKM2);
最佳答案
我发现我会先通过路径查找 bdev:
struct block_device *bdev;
bdev = lookup_bdev("/dev/loop0");
然后打开它:
bb->bi_bdev = blkdev_get_by_dev(bdev->bd_dev, FMODE_READ|FMODE_WRITE, NULL);
或
bb->bi_bdev = blkdev_get_by_path("/dev/loop0", FMODE_READ|FMODE_WRITE, NULL);
没有 FMODE_EXCL。但是当你完成后,你需要关闭设备:
blkdev_put(bb->bi_bdev, FMODE_READ|FMODE_WRITE);
关于module - 从内核 (3.7) 模块读取 block_device : segfault in submit_bio, bd_disk 丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14628275/
你好 stackoverflow。 想知道我在尝试直接从内核模块访问 block 设备时犯了什么错误。 (amd64 上的内核 3.7) 我使用 get_gendisk() 获取设备的 (struct
我是一名优秀的程序员,十分优秀!