3

私はカーネル モジュールに取り組んでおり、2 つのバッファーを比較して、それらが同等かどうかを確認する必要があります。そのために、Linux カーネルで定義されている memcmp 関数を使用しています。私の最初のバッファは次のようなものです:

cache_buffer = (unsigned char *)vmalloc(4097);
cache_buffer[4096] = '/0';

2 番目のバッファーは、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の結果でした。正または負の数値が返されるたびに、私の関数を呼び出した関数がいくつかのポインターを操作し、そのうちの 1 つが初期化されていませんでした。なんで今まで気づかなかったのかわからない。でも助けてくれてありがとう!

4

1 に答える 1

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;    
}
于 2013-06-10T19:22:10.780 に答える