出于某些特定原因,我需要编辑2.6.32.65 Linux内核,以便在将内容分配到内存之前,将扇区从硬盘读取到特定位置。例如,在do_generic_file_read
中的函数mm/filemap.c
中,我执行以下操作:
myRet = mapping->a_ops->readpage(filp,myPage); //Added
Function_Operates_On_MyPage(); //Added
page = page_cache_alloc_cold(mapping);
if (!page) {
desc->error = -ENOMEM;
goto out;
}
然后函数实际上再次将扇区读取到分配的页面,如下所示:
error = mapping->a_ops->readpage(filp, page);
当然这不是最佳选择,但我只需将其用于测试目的,因此无关紧要。现在这很好用,做我想做的事。它在多个其他位置也可以正常工作,__do_page_cache_readahead
中的mm/readahead.c
除外。它看起来如下:
for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
pgoff_t page_offset = offset + page_idx;
if (page_offset > end_index)
break;
rcu_read_lock();
page = radix_tree_lookup(&mapping->page_tree, page_offset);
rcu_read_unlock();
if (page)
continue;
myRet = mapping->a_ops->readpage(filp,myPage); //Added
Function_Operates_On_Mypage(); //Added
page = page_cache_alloc_cold(mapping);
if (!page)
break;
page->index = page_offset;
list_add(&page->lru, &page_pool);
if (page_idx == nr_to_read - lookahead_size)
SetPageReadahead(page);
ret++;
}
if (ret)
read_pages(mapping, filp, &page_pool, ret);
它调用read_pages
实际上再次将扇区读取到其分配的页面。现在read_pages
据我所知,和我一样:
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_to_page(pages);
list_del(&page->lru);
if (!add_to_page_cache_lru(page, mapping,
page->index, GFP_KERNEL)) {
mapping->a_ops->readpage(filp, page);
}
page_cache_release(page);
}
ret = 0;
然而readpage
在read_pages
中正常工作,但当我在__do_page_cache_readahead
中添加时,会导致错误BUG: unable to handle kernel paging request at ffffea0df0668018
。两行之间的唯一区别是获取数据的页面。在其他情况下,我和我一起工作得很好。为什么会这样?如何解决?
修改1
readpage
是指向文件mpage_readpage
中函数fs/mpage.c
的指针,该函数在同一文件中调用do_mpage_readpage
。使用printk
我能够发现故障实际发生在do_mpage_readpage
的第一行,如下所示:
struct inode *inode = page->mapping->host;
问题是我用来从硬盘读取的页面在启动时被标记为保留(我不希望将此位置分配给任何进程!)。所以我不确定page->mapping
会是什么。我猜这是造成错误的原因,但我不知道如何解决这个问题!我也不确定它在其他位置是如何工作的,可能因为readpage
指向mpage_readpage
以外的函数。
答案 0 :(得分:2)
从您的代码中,我猜到了/**
* Create rounded corner bitmap from given bitmap. The given bitmap will be
* recycle after createing round image.
*
* @param bitmap
* in {@link Bitmap} to parse
* @param corner
* in {@link Integer} the corner of round rect image
* @return rounded corner bitmap in {@link Bitmap}
*/
public static Bitmap parseBitmapToRoundedBitmap(Bitmap bitmap) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
int size = Math.min(width, height);
Bitmap output = Bitmap.createBitmap(size, size, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
// Rect of bitmap
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
// This is how we draw round rect image or circle image
// Round rect image
// canvas.drawRoundRect(new RectF(rect), roundPx, roundPx, paint);
// Circle image
final float radius = size / 2;
canvas.drawCircle(size / 2, size / 2, radius, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
Rect srcRect = new Rect(width / 2 - size / 2, height / 2 - size / 2,
size, size);
canvas.drawBitmap(bitmap, srcRect, new Rect(0, 0, size, size), paint);
// Recycle bitmap if need.
if (hasHoneycomb()) {
bitmap = null;
} else {
bitmap.recycle();
bitmap = null;
}
return output;
}
中发生的错误。我用Google搜索了它:page = page_cache_alloc_cold(mapping);
用于在缓存中找不到想要的页面时分配新页面。但是如果你经常调用函数,内核会因为为内核提供的内存太小而oops!我遇到的问题,我的解决方案是在你的module_init()函数中预先分配页面(预分配)。它会避免经常调用page_cache_alloc_cold
。我希望这会对你有所帮助。
答案 1 :(得分:-1)
经过多次努力,我发现我的错误真的很愚蠢和直截了当。我只是使用了一个无效的页面地址(实际上忘了在某个步骤之间在pfn和页面之间进行转换)。一旦我解决了它,它工作正常。