gpt4 book ai didi

c - 如何在 Linux 内核中使用 bio 请求读取一个扇区

转载 作者:IT王子 更新时间:2023-10-28 23:55:40 29 4
gpt4 key购买 nike

我只想从硬盘读取一个扇区到内存中的特定页面,这个页面是保留的,没有映射到任何地址映射。我找到了 this solution但我不知道如何将文件转换为 block 设备和扇区。例如,在文件 mm/filemap.c 的函数 do_generic_file_read 中有这一行:

error = mapping->a_ops->readpage(filp, page);

由于目标页面没有任何映射,我不能使用相同的函数,但我需要将 filp 转换为设备和扇区才能生成我自己的 bio 请求。我该怎么做?

编辑 1

我试过这个作为一个可能的解决方案,通过添加这个,它首先计算扇区,然后直接调用 ext2_get_block 来获取设备,然后添加所需的页面位置并提交 bio 请求:

struct page *myPage;
int myRet;
struct buffer_head bh;
struct bio *bio = bio_alloc(GFP_NOIO,1);
myPage = pfn_to_page(Some_Location);
bio_init(bio);
bio->bi_sector = (sector_t)page_offset << (PAGE_CACHE_SHIFT - mapping->host->i_blkbits);
myRet = ext2_get_block(mapping->host, bio->bi_sector, &bh, 0);
bio->bi_bdev = bh.b_bdev;
bio->bi_next = NULL;
bio->bi_size = PAGE_SIZE;
bio_add_page(bio, myPage, PAGE_SIZE, 0);
submit_bio(READ, bio);

这使用函数中现有的地址映射来创建 bio 请求,因为所需的页面没有地址映射。它只有一个问题,submit_bio 行导致了这一点:

[    4.792142] ------------[ cut here ]------------
[ 4.792892] WARNING: at arch/x86/kernel/pci-nommu.c:63 nommu_map_sg+0xd9/0x100()
[ 4.793674] Hardware name: Standard PC (i440FX + PIIX, 1996)
[ 4.794149] Modules linked in:
[ 4.794607] Pid: 153, comm: kblockd/0 Not tainted 2.6.32.65 #308
[ 4.795077] Call Trace:
[ 4.795545] [<ffffffff81056875>] ? warn_slowpath_common+0x65/0xa0
[ 4.796024] [<ffffffff810380a9>] ? nommu_map_sg+0xd9/0x100
[ 4.796446] [<ffffffff8121ef4a>] ? ide_dma_prepare+0xda/0x180
[ 4.796900] [<ffffffff81219923>] ? do_rw_taskfile+0x253/0x330
[ 4.797532] [<ffffffff8122311c>] ? ide_do_rw_disk+0x22c/0x320
[ 4.797983] [<ffffffff81215c3a>] ? do_ide_request+0x11a/0x600
[ 4.798416] [<ffffffff81051450>] ? __dequeue_entity+0x30/0x40
[ 4.798854] [<ffffffff810519a1>] ? finish_task_switch.constprop.110+0x31/0xc0
[ 4.799391] [<ffffffff8141fdd6>] ? thread_return+0x2a/0x1d4
[ 4.799816] [<ffffffff81052116>] ? check_preempt_wakeup+0x76/0xe0
[ 4.800279] [<ffffffff811a3be0>] ? blk_unplug_work+0x0/0x20
[ 4.800754] [<ffffffff811a5b2a>] ? generic_unplug_device+0x1a/0x30
[ 4.801218] [<ffffffff810661dc>] ? worker_thread+0x13c/0x210
[ 4.802710] [<ffffffff81069cb0>] ? autoremove_wake_function+0x0/0x30
[ 4.804130] [<ffffffff810660a0>] ? worker_thread+0x0/0x210
[ 4.805357] [<ffffffff810660a0>] ? worker_thread+0x0/0x210
[ 4.806356] [<ffffffff81069907>] ? kthread+0x77/0x80
[ 4.807302] [<ffffffff81033eaa>] ? child_rip+0xa/0x20
[ 4.808500] [<ffffffff81069890>] ? kthread+0x0/0x80
[ 4.809060] [<ffffffff81033ea0>] ? child_rip+0x0/0x20
[ 4.809620] ---[ end trace 61d7e1478dbb58eb ]---

后来导致了这个:

[    4.871857] hda: task_pio_intr: status=0x58 { DriveReady SeekComplete DataRequest }
[ 4.872553] hda: possibly failed opcode: 0x29
[ 4.873346] hda: DMA disabled
[ 4.885478] Clocksource tsc unstable (delta = 115822911 ns)
[ 4.886364] Switching to clocksource jiffies
[ 4.919051] ide0: reset: success

还有这个:

[   48.957807] hda: lost interrupt

我将此添加到 mm/readahead.c 中的函数 __do_page_cache_readahead 但它可以像 mm/filemap.c 或类似的方式添加功能。也许有人可以解决这个问题!

最佳答案

您计算扇区的方式似乎不错,但我认为您最终不会得到您想要的精确扇区。话虽如此,您完全错误地获取了 block 设备。不要调用 ext2_get_block,因为它不仅是特定于文件系统的,而且您似乎并不真正理解它的作用,而且它比获取 block 设备的标准方法更令人困惑。相反,只需使用

bio.bi_bdev = I_BDEV(mapping->host);

另外,如果你想测试它并查看它的实际效果,那么只需将它编译成一个模块并设置一个 Hook ,这样当你打开某个 block 设备(你创建的)时它就会触发功能。您当前将其添加到现有函数中的方法可能会干扰内核当前正在做的任何事情,并且会弄乱您的测试。

关于c - 如何在 Linux 内核中使用 bio 请求读取一个扇区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29762313/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com