歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux RAMDisk 源碼分析

Linux RAMDisk 源碼分析

日期:2017/2/28 15:59:56   编辑:Linux教程

在產品中使用了ramdisk, 看了一部分的源碼,分析和共享一下。內核源碼 2.6.18

安裝ramdisk

ramdisk 在linux裡面被認為是個內存的塊設備,通常以rm0,rm1... 掛在dev下,首先需要格式化塊設備成linux的文件系統,然後在將想使用的目錄mount 到dev/rm0...下,這樣操作目錄,在目錄裡操作文件就在內存裡。

ramdisk是一個塊設備,需要格式化成linux能認識的文件系統(ext2,ext3),那麼對ramdisk的 IO的操作 ,就繞不過page cache,也就是無意中多了一次內存復制。

通常在linux中,由於塊設備的隨機讀寫是急劇降低性能的,linux 系統中會有一些合並算法,我們將每次設備的請求認為是一個操作,那麼在內核中不會將每一次的請求都提交給塊設備,而是在一定的時間內把請求合並成一個隊列,然後 調整隊列裡請求的順序,盡量讓請求(比如塊設備中地址相近的)排序在相鄰的位置,這樣可以提高磁頭訪問的效率。

最後將隊列提交給塊設備,相見常用的四種電梯調度算法,就不描述了。

ramdisk是以內存作為訪問的塊設備,隨機訪問的速度非常塊,調度算法不能提高IO的效率,反而因為合並請求而導致訪問性能下降,所以ramdisk沒有使用調度算法,在初始化ramdisk的時候,重新設置了queue的調度算法。

drivers/block/rd.c

  1. static int __init rd_init(void)
  2. {
  3. ...
  4. blk_queue_make_request(rd_queue[i], &rd_make_request);
  5. ....
  6. }

在函數裡rd_make_request,核心就是rd_blkdev_pagecache_IO
  1. static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector,
  2. struct address_space *mapping)
  3. {
  4. pgoff_t index = sector >> (PAGE_CACHE_SHIFT - 9);
  5. unsigned int vec_offset = vec->bv_offset;
  6. int offset = (sector << 9) & ~PAGE_CACHE_MASK;
  7. int size = vec->bv_len;
  8. int err = 0;
  9. do {
  10. int count;
  11. struct page *page;
  12. char *src;
  13. char *dst;
  14. count = PAGE_CACHE_SIZE - offset;
  15. if (count > size)
  16. count = size;
  17. size -= count;
  18. page = grab_cache_page(mapping, index);
  19. if (!page) {
  20. err = -ENOMEM;
  21. goto out;
  22. }
  23. if (!PageUptodate(page))
  24. make_page_uptodate(page);
  25. index++;
  26. if (rw == READ) {
  27. src = kmap_atomic(page, KM_USER0) + offset;
  28. dst = kmap_atomic(vec->bv_page, KM_USER1) + vec_offset;
  29. } else {
  30. src = kmap_atomic(vec->bv_page, KM_USER0) + vec_offset;
  31. dst = kmap_atomic(page, KM_USER1) + offset;
  32. }
  33. offset = 0;
  34. vec_offset += count;
  35. memcpy(dst, src, count);
  36. kunmap_atomic(src, KM_USER0);
  37. kunmap_atomic(dst, KM_USER1);
  38. if (rw == READ)
  39. flush_dcache_page(vec->bv_page);
  40. else
  41. set_page_dirty(page);
  42. unlock_page(page);
  43. put_page(page);
  44. } while (size);
  45. out:
  46. return err;
  47. }

a. Grab_Cache_Page

grab_cache_page -> find_or_create_page

address_space *mapping,這是Ramdisk block 的塊結構,通過index,可以很塊的找到在ramdisk裡面的內容(也可以說在默認的ramdisk裡塊和linux 的頁的大小是一致的),而不是�� ext 文件系統中所表示的inode的address_space。

find_or_create_page, 是查找ramdisk裡的頁的位置,在ramdisk中內容是以頁的形式來保存的,如果頁面不存在,會生成新的頁面,如果頁面存在會鎖住該頁,同時加到lru cache的列表中去。該函數是允許睡眠的,在鎖住頁面的時候,會等待直到頁面的狀態位設置成set_bit(PG_locked, &(page)->flags),具體的函數__lock_page實現

Copyright © Linux教程網 All Rights Reserved