- 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/
总的来说,我对 Linux 内核和操作系统非常感兴趣。我想知道的是,内核的文件类型或扩展名是什么?它显然没有 .exe 或 .out 扩展名,因为它们用于安装在操作系统上的应用程序。 内核只是一个二进
我需要为 Raspbian Linux 内核添加一个自己的系统调用。现在我在搜索了大约 2 天以找到解决方案后陷入困境。 要加一个系统调用,我基本上是按照大纲来的( http://elinux.org
对于一个学术项目,我希望将源文件 (myfile.c) 添加到 kernel/目录,与exit.c相同的目录和 fork.c .构建系统似乎不会自动获取新文件,因为我在 myfile.c 中定义的函数
浏览器排行榜 浏览器市占率排行榜全球榜 。 浏览器市占率排行榜中国榜 -快科技 。 如果按照浏览器内核来看, Chromium 内核的市场占有率无疑是最大的,一家独大
给定一个进程或线程的任务结构,迭代属于同一进程的所有其他线程的习惯用法是什么? 最佳答案 Linux 不区分进程(任务)和线程。库调用 fork() 和 pthread_create() 使用相同的系
我正在用c(不是linux。完全从头开始)从头开始制作一个内核,但我遇到了一些问题。我有这个代码: #include "timer.h" int ms = 0; void timer_handler(
我正在从头开始制作一个 C 内核,我实际上只是从网站上复制了这段代码,因为我的代码无法工作,所以我很困惑。 void kmain(void) { const char *str = "my f
我不确定,如果我完全理解上述差异,所以我想自己解释一下,你可以打断我,只要我有错:“内核是创建内核线程的初始代码段。内核线程是由内核管理的进程。用户线程是进程的一部分。如果你有一个单线程进程,那么整个
看一下struct file 定义from this code Linux 内核版本 2.6.18。 我正在尝试比较代码中的两个 struct file 变量,并确定它们是否指的是同一个文件。该结构中
我试图在 Linux 启动时使嵌入式设备中的 LED 闪烁。基本上,LED 闪烁表明 Linux 正在启动。为了使 LED 闪烁,我正在做以下事情 在 init/main.c 中创建了一个全局定时器(
我有一些在 FreeBSD 和 Linux 上运行的特定硬件。 我必须做一个用户空间应用程序,它将使用内核/用户空间应用程序之间的共享内存与驱动程序一起工作。我的应用程序对来自用户空间的共享内存进行忙
我在哪里可以找到 linux 内核中相应函数的解释,特别是对于 ICMPv4? 例如:icmp_reply、icmp_send等 感谢您的帮助。 最好的,阿里木 最佳答案 探索 Linux 内核中的
我在 Linux Kernel 3.4 上工作,我有以下代码: /* Proximity sensor calibration values */ unsigned int als_kadc;
我正在阅读“罗伯特·洛夫 (Robert Love) 撰写的 Linux 内核开发第 3 版”,以大致了解 Linux 内核的工作原理..(2.6.2.3) 我对等待队列的工作方式感到困惑,例如这段代
我之前也问过同样的问题,但是我的帖子不知为何被删除了。 无论如何,我正在尝试使用 C++ 并编写一个允许我直接访问内存并向其中写入内容的程序。我听说我需要对内核做一些事情,因为它是连接操作系统和应用程
在尝试了解 Ruby 执行方法时,我找到了这篇关于在 Ruby 中运行命令的五种方法的博文 http://mentalized.net/journal/2010/03/08/5_ways_to_run
是否有 Linux 发行版(Minix 除外)包含良好的源代码文档?或者,是否有一些好的文档来描述一般的 Linux 源代码? 我已经下载了内核源代码,但是(不出所料)我有点不知所措,我想知道是否有一
有谁知道 linux 中的哪个函数或文件包含查找用于 bind() 系统调用的随机端口的算法?我到处寻找,在 Linux 源代码中找不到包含此算法的方法。 谢谢! 最佳答案 这是一段又长又复杂的代码,
前言 首先,对于有科班背景的读者,可以跳过本系列文章。这些文章的主要目的是通过简单易懂的汇总,帮助非科班出身的读者理解底层知识,进一步了解为什么在面试中会涉及这些底层问题。否则,某些概念将始终
CentOS7.2与CentOS6区别及特点 Linux 操作系统的启动首先从 BIOS 开始,接下来进入 boot loader,由 bootloader 载入内核,进行内核初始化。内核初始化的
我是一名优秀的程序员,十分优秀!