如何在Linux内核中使用生物请求阅读一个部门

前端之家收集整理的这篇文章主要介绍了如何在Linux内核中使用生物请求阅读一个部门前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想只读一个扇区从硬盘到内存中的一个特定的页面,这个页面是保留的,没有映射到任何地址映射.我发现 this solution,但我不知道如何将文件翻译成块设备和扇区.例如,在文件mm / filemap.c中的函数do_generic_file_read中有这样一行:
  1. error = mapping->a_ops->readpage(filp,page);

由于目标页面不是任何映射,所以我无法使用相同的功能,但是我需要将filp转换为设备和扇区,以便生成自己的生物请求.我该怎么办?

编辑1

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

  1. struct page *myPage;
  2. int myRet;
  3. struct buffer_head bh;
  4. struct bio *bio = bio_alloc(GFP_NOIO,1);
  5. myPage = pfn_to_page(Some_Location);
  6. bio_init(bio);
  7. bio->bi_sector = (sector_t)page_offset << (PAGE_CACHE_SHIFT - mapping->host->i_blkbits);
  8. myRet = ext2_get_block(mapping->host,bio->bi_sector,&bh,0);
  9. bio->bi_bdev = bh.b_bdev;
  10. bio->bi_next = NULL;
  11. bio->bi_size = PAGE_SIZE;
  12. bio_add_page(bio,myPage,PAGE_SIZE,0);
  13. submit_bio(READ,bio);

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

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

后来导致这个:

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

和这个:

  1. [ 48.957807] hda: lost interrupt

添加函数__do_page_cache_readahead在mm / readahead.c,但它可以添加类似于mm / filemap.c或类似的功能.也许有人可以解决这个问题!

解决方法

你计算行业的方式似乎很好,虽然我不认为你会得到你想要的精确部门.话虽如此,您正在抓取块设备是错误的.不要调用ext2_get_block,因为它不仅具有文件系统特定的功能,而且似乎并没有真正了解它的功能,而且比获取块设备的标准方法更为混乱.相反,只是使用
  1. bio.bi_bdev = I_BDEV(mapping->host);

另外,如果你想测试一下,看看它在行动,那么只需将它编译成一个模块并设置一个钩子,这样当你打开一个特定的块设备(你已经创建)它将触发该功能.您目前的方法将其添加到现有功能中可能会干扰内核当前正在执行的任何操作,并且会使您的测试失败.

猜你在找的Linux相关文章