我正在研究内核模块,我需要比较两个缓冲区以确定它们是否相同。我正在使用Linux内核中定义的memcmp函数来执行此操作。我的第一个缓冲区是这样的:
cache_buffer = (unsigned char *)vmalloc(4097);
cache_buffer[4096] = '/0';
第二个缓冲区来自使用page_address()函数的页面。
page = bio_page(bio);
kmap(page);
write_buffer = (char *)page_address(page);
kunmap(page);
我已经预先打印了两个缓冲区的内容,不仅打印正确,而且它们也有相同的内容。接下来,我这样做:
result = memcmp(write_buffer, cache_buffer, 2048); // only comparing up to 2048 positions
这导致内核冻结,我无法弄清楚原因。我检查了memcmp的实现,没有看到任何会导致冻结的东西。任何人都可以建议一个原因吗?
这是memcmp实现:
int memcmp(const void *cs, const void *ct, size_t count)
{
const unsigned char *su1, *su2;
int res = 0;
for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
if ((res = *su1 - *su2) != 0)
break;
return res;
}
编辑:导致冻结的功能是memcmp。当我评论它时,一切都有效。另外,当我做了memcmp时,如下
memcmp(write_buffer, write_buffer, 2048); //comparing two write_buffers
一切都运作良好。只有当我将cache_buffer抛入混合时才会出现错误。此外,上面是我的实际代码的简化。这是整个功能:
static int compare_data(sector_t location, struct bio * bio, struct cache_c * dmc)
{
struct dm_io_region where;
unsigned long bits;
int segno;
struct bio_vec * bvec;
struct page * page;
unsigned char * cache_data;
char * temp_data;
char * write_data;
int result, length, i;
cache_data = (unsigned char *)vmalloc((dmc->block_size * 512) + 1);
where.bdev = dmc->cache_dev->bdev;
where.count = dmc->block_size;
where.sector = location << dmc->block_shift;
printk(KERN_DEBUG "place: %llu\n", where.sector);
dm_io_sync_vm(1, &where, READ, cache_data, &bits, dmc);
length = 0;
bio_for_each_segment(bvec, bio, segno)
{
if(segno == 0)
{
page = bio_page(bio);
kmap(page);
write_data = (char *)page_address(page);
//kunmap(page);
length += bvec->bv_len;
}
else
{
page = bio_page(bio);
kmap(page);
temp_data = strcat(write_data, (char *)page_address(page));
//kunmap(page);
write_data = temp_data;
length += bvec->bv_len;
}
}
printk(KERN_INFO "length: %u\n", length);
cache_data[dmc->block_size * 512] = '\0';
for(i = 0; i < 2048; i++)
{
printk("%c", write_data[i]);
}
printk("\n");
for(i = 0; i < 2048; i++)
{
printk("%c", cache_data[i]);
}
printk("\n");
result = memcmp(write_data, cache_data, length);
return result;
}
编辑#2:对不起伙计们。问题不在于memcmp。这是memcmp的结果。当它返回正数或负数时,调用我的函数的函数将使用一些指针,其中一个未初始化。我不知道为什么我之前没有意识到这一点。感谢您尽力提供帮助!
答案 0 :(得分:7)
我不是内核专家,但我认为你需要在进行比较时保留这个内存映射?换句话说,在kunmap
完成之前,请勿致电memcmp
。我认为之前调用它会导致write_buffer
指向不再映射的页面。
在另一个问题中使用您的代码,这是对增量的粗略尝试。仍然需要一些清理,我敢肯定:
static int compare_data(sector_t location, struct bio * bio, struct cache_c * dmc)
{
struct dm_io_region where;
unsigned long bits;
int segno;
struct bio_vec * bvec;
struct page * page;
unsigned char * cache_data;
char * temp_data;
char * write_data;
int length, i;
int result = 0;
size_t position = 0;
size_t max_size = (dmc->block_size * 512) + 1;
cache_data = (unsigned char *)vmalloc(max_size);
where.bdev = dmc->cache_dev->bdev;
where.count = dmc->block_size;
where.sector = location << dmc->block_shift;
printk(KERN_DEBUG "place: %llu\n", where.sector);
dm_io_sync_vm(1, &where, READ, cache_data, &bits, dmc);
bio_for_each_segment(bvec, bio, segno)
{
// Map the page into memory
page = bio_page(bio);
write_data = (char *)kmap(page);
length = bvec->bv_len;
// Make sure we don't go past the end
if(position >= max_size)
break;
if(position + length > max_size)
length = max_size - position;
// Compare the data
result = memcmp(write_data, cache_data + position, length);
position += length;
kunmap(page);
// If the memory is not equal, bail out now and return the result
if(result != 0)
break;
}
cache_data[dmc->block_size * 512] = '\0';
return result;
}