成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入理解Linux內(nèi)核之臟頁跟蹤

系統(tǒng) Linux
Linux內(nèi)核由于存在page cache, 一般修改的文件數(shù)據(jù)并不會馬上同步到磁盤,會緩存在內(nèi)存的page cache中,我們把這種和磁盤數(shù)據(jù)不一致的頁稱為臟頁,臟頁會在合適的時機同步到磁盤。為了回寫page cache中的臟頁,需要標記頁為臟。

[[439448]]

本文轉(zhuǎn)載自微信公眾號「Linux內(nèi)核遠航者」,作者Linux內(nèi)核遠航者 。轉(zhuǎn)載本文請聯(lián)系Linux內(nèi)核遠航者公眾號。

1.開場白

環(huán)境:

處理器架構(gòu):arm64

內(nèi)核源碼:linux-5.10.50

ubuntu版本:20.04.1

代碼閱讀工具:vim+ctags+cscope

Linux內(nèi)核由于存在page cache, 一般修改的文件數(shù)據(jù)并不會馬上同步到磁盤,會緩存在內(nèi)存的page cache中,我們把這種和磁盤數(shù)據(jù)不一致的頁稱為臟頁,臟頁會在合適的時機同步到磁盤。為了回寫page cache中的臟頁,需要標記頁為臟。

臟頁跟蹤是指內(nèi)核如何在合適的時機記錄文件頁為臟,以便內(nèi)核在進行臟頁回寫時,知道將哪些頁面回寫到磁盤。匿名頁不需要跟蹤臟頁,因為不需要同步到磁盤;私有文件頁也不需要跟蹤臟頁,因為映射的時候,可寫頁會映射為只讀,寫訪問會發(fā)生寫時復制,轉(zhuǎn)變?yōu)槟涿?所以只有共享的文件頁需要跟蹤臟頁。跟蹤有兩個層面:一個是頁表項記錄,一個是頁描述符記錄。

訪問文件頁有兩種方式:一種是通過mmap映射文件,一種是通過文件系統(tǒng)的write接口操作文件,本文將對這兩種方式進行講解。在Linux內(nèi)核中,因為跟蹤臟頁會涉及到文件回寫、缺頁異常、反向映射等技術(shù),所以本文也重點講解在Linux內(nèi)核中如何跟蹤臟頁。

2.mmap映射的文件頁

基本過程如下:

1)通過mmap映射共享文件。

2)第一次訪問文件頁時,發(fā)生缺頁后讀文件頁到page cache, 如果是寫訪問則設(shè)置相應(yīng)進程的頁表項為臟、可寫。

3)臟頁回寫時,會通過反向映射機制,查找映射這個頁的每一個vma, 設(shè)置相應(yīng)進程的頁表項為只讀,清臟標記。

4)假如第二次寫訪問這個文件頁時,臟頁的處理有兩種情況:

  • page cache中的文件頁還未回寫到磁盤(3步驟之前), 此刻,這個文件頁依然是臟頁。因為相應(yīng)進程的頁表項為臟、可寫,所以可以直接寫這個頁。
  • page cache中的文件頁已經(jīng)回寫到磁盤(3步驟之后), 此刻,這個文件頁不再是臟頁。因為頁表項為只讀,所以寫訪問會發(fā)生寫時復制缺頁異常,異常處理中將處理共享文件頁映射,重新將相應(yīng)進程的頁表項為設(shè)置為臟、可寫。

分析如下:

2.1 第一次寫訪問文件頁時

如果是mmap映射文件頁,在沒有填充頁表情況下,寫訪問會發(fā)生轉(zhuǎn)換表錯誤類型的缺頁異常。

  1. //mm/memory.c  
  2. handle_pte_fault 
  3.     ->do_fault  
  4.         ->do_shared_fault  
  5.             ->__do_fault  //讀文件頁到page cache 
  6.                 ->do_page_mkwrite  
  7.                     ->vmf->vma->vm_ops->page_mkwrite()  
  8.                         ->filemap_page_mkwrite, //對于ext2 
  9.                                 ->set_page_dirty(page)  
  10.                                     ->__set_page_dirty_buffers 
  11.                                         ->__set_page_dirty//page cache中標記頁為臟  
  12.                                             ->TestSetPageDirty(page) //設(shè)置頁描述符臟標記 
  13.                 ->finish_fault  //設(shè)置頁表項 
  14.                     ->alloc_set_pte 
  15.                         ->if (write)  
  16.                             entry = maybe_mkwrite(pte_mkdirty(entry), vma) //設(shè)置頁表項臟、可寫 

2.2 臟頁回寫時

  1. //mm/page-writeback.c  
  2. write_cache_pages 
  3. ->clear_page_dirty_for_io(page) //對于回寫的每一個頁 
  4.     ->page_mkclean(page) //清臟標記  mm/rmap.c  
  5.         ->page_mkclean_one //反向映射查找這個頁的每個vma,調(diào)用清臟標記和寫保護處理 
  6.                 ->entry = pte_wrprotect(entry);     //寫保護處理,設(shè)置只讀 
  7.                     entry = pte_mkclean(entry); //清臟標記 set_pte_at(vma->vm_mm, address, pte, entry) //設(shè)置到頁表項中 
  8.     ->TestClearPageDirty(page) //清頁描述符臟標記 

2.3 第二次寫訪問文件頁時

1)臟頁還沒有回寫時(確切的說是調(diào)用clear_page_dirty_for_io之前),頁描述符已經(jīng)設(shè)置了臟標記,頁表項已經(jīng)設(shè)置了臟標記、可寫。

這時可以直接寫訪問文件頁,不會發(fā)生缺頁。

2)臟頁已經(jīng)回寫時(確切的說是調(diào)用clear_page_dirty_for_io之后),頁描述符已經(jīng)清除了臟標記,頁表項已經(jīng)清除了臟標記,且只讀。

這時寫訪問文件頁會發(fā)生寫時復制缺頁異常(訪問權(quán)限錯誤缺頁)。

調(diào)用鏈如下:

  1. //mm/memory.c  
  2. handle_pte_fault  
  3. ->if (vmf->flags & FAULT_FLAG_WRITE) { //vma可寫 
  4.             if (!pte_write(entry)) //頁表項沒有可寫屬性 return do_wp_page(vmf) //寫時復制缺頁異常處理 
  5.                     do_wp_page  
  6.                             ->} else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))) { //是共享可寫的文件映射vma  
  7.                                         return   wp_page_shared(vmf); 
  8.                                         ->do_page_mkwrite  
  9.                                             ->vmf->vma->vm_ops->page_mkwrite() 
  10.                                                 ->filemap_page_mkwrite, //對于ext2                                                              ->set_page_dirty(page) 
  11.                                                                ->__set_page_dirty_buffers  //page cache中標記頁為臟  
  12.                                                                      ->TestSetPageDirty(page) //設(shè)置頁描述符臟標記 
  13.                                                   ->finish_mkwrite_fault 
  14.                                                         ->wp_page_reuse 
  15.                                                                     ->entry = maybe_mkwrite(pte_mkdirty(entry), vma) //重新設(shè)置頁表項臟、可寫 

2.4 再次寫訪問

重復上面步驟。

3.write接口操作的文件頁

由于通過write接口訪問文件頁時,會讀取文件頁到page cache,不會映射到任何進程地址空間,所有這種方式跟蹤臟頁是通過設(shè)置/清除頁描述符臟標記來實現(xiàn)。

3.1 第一次寫訪問文件頁時

會首先讀文件頁到page cache,然后將用戶空間寫緩沖區(qū)數(shù)據(jù)寫到page cache,調(diào)用鏈如下:

  1. ext2_file_write_iter //fs/ext2/file.c  
  2. ->generic_file_write_iter //mm/filemap.c  
  3.     ->__generic_file_write_iter  
  4.         ->generic_perform_write  
  5.             ->a_ops->write_begin() //寫之前處理 分配page cache頁                                               ->iov_iter_copy_from_user_atomic //戶空間寫緩沖區(qū)數(shù)據(jù)寫到page cache頁       -> a_ops->write_end() //寫之后處理 
  6.                     ->block_write_end  
  7.                             ->__block_commit_write 
  8.                                     ->mark_buffer_dirty 
  9.                                             if (!TestSetPageDirty(page)) {  //設(shè)置頁描述符臟標記                                                        ->__set_page_dirty  //設(shè)置頁為臟(設(shè)置頁描述符臟標記) 

3.2 臟頁回寫時

  1. write_cache_pages  //mm/page-writeback.c  
  2. ->clear_page_dirty_for_io  
  3.         ->TestClearPageDirty(page) //清除頁描述符臟標記 

3.3 第二次寫訪問文件頁時

臟頁回寫之前,頁描述符臟標志位依然被置位,等待回寫, 不需要設(shè)置頁描述符臟標志位。

臟頁回寫之后,頁描述符臟標志位是清零的,文件寫頁調(diào)用鏈會設(shè)置頁描述符臟標志位。

4.總結(jié)

1)對于mmap映射的共享文件頁,因為這個文件頁可能會被多個進程共享到多個vma中,所以通過頁表項的臟標志位來跟蹤臟頁:第一次寫訪問發(fā)生缺頁異常會讀文件頁到page cache中并設(shè)置進程的頁表項的臟標志,回寫之前(clear_page_dirty_for_io完成之前),頁表項的臟標志是置位的,回寫的時候(clear_page_dirty_for_io的調(diào)用)會通過反向映射機制將所有映射這個頁的頁表項的臟標志位清零并設(shè)置只讀權(quán)限,回寫之后(clear_page_dirty_for_io完成之后),再次的寫訪問會發(fā)生寫時復制缺頁異常,再次設(shè)置頁表項的臟標志位,如此重復,從而跟蹤了臟頁。

2)對于直接通過write接口訪問的文件頁,因為這個文件頁只會被讀取到page cache中,并沒有映射到任何進程地址空間,進程寫訪問是通過copy_from_user的方式,所以通過頁描述符記錄臟頁?;貙懼?clear_page_dirty_for_io完成之前),寫文件的時候通過文件系統(tǒng)的寫文件的調(diào)用鏈會設(shè)置頁描述符臟標志位,回寫的時候(clear_page_dirty_for_io的調(diào)用)會清除頁描述符臟標志位,回寫之后(clear_page_dirty_for_io完成之后),再次通過write接口寫訪問時,再次通過文件系統(tǒng)的寫文件的調(diào)用鏈會再次設(shè)置頁描述符臟標志位,如此重復,從而跟蹤了臟頁。

 

責任編輯:武曉燕 來源: Linux內(nèi)核遠航者
相關(guān)推薦

2021-07-26 07:47:36

數(shù)據(jù)庫

2021-05-19 07:56:26

Linux內(nèi)核搶占

2021-07-20 08:02:41

Linux進程睡眠

2021-02-17 11:25:33

前端JavaScriptthis

2021-07-05 06:51:45

Linux內(nèi)核調(diào)度器

2021-07-02 06:54:44

Linux內(nèi)核主調(diào)度器

2020-09-28 08:44:17

Linux內(nèi)核

2025-06-16 05:10:00

2023-02-10 08:11:43

Linux系統(tǒng)調(diào)用

2022-11-09 08:12:07

2024-07-08 09:29:07

2018-12-27 12:34:42

HadoopHDFS分布式系統(tǒng)

2014-12-04 14:01:54

openstacknetworkneutron

2019-03-18 09:50:44

Nginx架構(gòu)服務(wù)器

2022-09-05 22:22:00

Stream操作對象

2021-08-31 10:32:11

LinuxPage Cache命令

2013-06-20 10:25:56

2010-06-01 15:25:27

JavaCLASSPATH

2016-12-08 15:36:59

HashMap數(shù)據(jù)結(jié)構(gòu)hash函數(shù)

2020-07-21 08:26:08

SpringSecurity過濾器
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 神马久久久久久久久久 | 91高清视频在线观看 | www.亚洲 | 免费看片在线播放 | 亚洲 欧美 综合 | 国产精品jizz在线观看老狼 | 日韩精品一区二 | 亚洲香蕉在线视频 | 欧美一区二区三区免费在线观看 | 免费看91 | 久久精品中文字幕 | 一区二区在线 | 国色天香综合网 | 精品欧美一区二区中文字幕视频 | 91成人在线视频 | 久久久亚洲精品视频 | 欧美一区二区三区,视频 | 爱草视频| 黄色毛片在线播放 | 国产精品美女久久久久久免费 | 久久综合狠狠综合久久综合88 | 成人影院在线视频 | 99热精品6 | 国产天天操 | 久久精品国产久精国产 | 成人久久网 | 欧美日一区 | 午夜视频在线观看一区二区 | 亚洲日本视频 | 永久av| 久久久网 | 国产最新精品视频 | 91久久夜色精品国产网站 | 国产一区二区在线免费 | 亚洲成人网在线 | 欧美成人精品 | 中文精品久久 | 国产99热在线| 青青草av | 久久精品一区二区三区四区 | 欧美不卡一区二区三区 |