《電子技術應用》
您所在的位置:首頁 > 可編程邏輯 > 其他 > Linux教學——mmap實現詳解

Linux教學——mmap實現詳解

2022-09-29
作者:songsong001
來源:一口Linux
關鍵詞: Linux mmap 中斷處理

  故事的開始是這樣的,某天在脈脈上看到有人發了下面的帖子:

微信截圖_20220929173630.png

  想不到 mmap 都成了黑科技了,為了讓大家都能了解這個黑科技,所以還是寫篇文章來詳細介紹一下 mmap 的實現吧。

  其實,源碼分析是比較難寫的,主要有兩個原因:

  一方面是源碼實現一般會涉及多個知識點,所以在分析源碼時需要穿插多個知識點,從而增加分析的難度。另一方面是源碼實現會處理很多細節問題,這些細節問題雖然不是設計的主要框架,但忽略了有時會讓人摸不著頭腦。

  所以,為了降低分析的難度和讓讀者能夠更容易看懂,在分析源碼時更注重知識點的實現,而在不影響理解的情況下,我會忽略一些細節問題。而對于穿插其他知識點的時候,會先跳過其實現,并且在后續的文章對其進行分析。

  mmap 原理

  在之前的文章中,我們也介紹過 mmap 的原理,比如這篇:《原來 mmap 這么簡單》。當然這篇文章只是簡單介紹了 mmap 的原理,但是 mmap 的實現遠不止那么簡單,這是因為 mmap 涉及多個子系統,如:內存管理、文件系統、中斷處理等。

  好消息是,這幾個子系統我們都有對應的文章介紹過:

  內存管理:Linux虛擬內存空間管理》
       文件系統:《 什么是頁緩存》
       中斷處理:《Linux中斷處理》

  在閱讀本文前,最好復習一下上面的文章。

  雖然在《原來 mmap 這么簡單》一文中,我們簡單介紹過 mmap 的原理。但為了方便分析源碼,下面還是簡單回顧一下 mmap 的原理吧。

  mmap 的全稱是 memory map,中文意思是 內存映射。其用途是將文件映射到內存中,然后可以通過對映射區的內存進行讀寫操作,其效果等同于對文件進行讀寫操作。

  下面我們通過一幅圖來對 mmap 的原理進行闡述:

微信截圖_20220929173816.png

  從上圖可以看出,mmap 的原理就是將虛擬內存空間映射到文件的頁緩存,在《什么是頁緩存》一文中可知,對文件進行讀寫時需要經過頁緩存進行中轉的。所以當虛擬內存地址映射到文件的頁緩存后,就可以直接通過讀寫映射區內存來對文件進行讀寫操作。

  mmap 實現

  在分析 mmap 的實現前,最好先了解其使用方式,mmap 的使用可以參考《原來 mmap 這么簡單》這篇文章。

  1. 文件映射

  當我們使用 mmap() 系統調用對文件進行映射時,將會觸發調用 do_mmap_pgoff() 內核函數來完成工作,我們來看看 do_mmap_pgoff() 函數的實現(經過精簡后):

  unsigned long

  do_mmap_pgoff(struct file *file, unsigned long addr,

  unsigned long len, unsigned long prot,

  unsigned long flags, unsigned long pgoff)

  {

  ...

  // 1. 獲取一個未被使用的虛擬內存區

  addr = get_unmapped_area(file, addr, len, pgoff, flags);

  if (addr & ~PAGE_MASK)

  return addr;

  ...

  // 2. 調用 mmap_region() 函數繼續進行映射操作

  return mmap_region(file, addr, len, flags, vm_flags, pgoff, accountable);

  }

  經過精簡后的 do_mmap_pgoff() 函數主要完成 2 個工作:

  首先,調用 get_unmapped_area() 函數來獲取進程沒被使用的虛擬內存區,并且返回此內存區的首地址。然后,調用 mmap_region() 函數繼續進行映射操作。

  在 32 位的操作系統中,每個進程都有 4GB 的虛擬內存空間,應用程序在使用內存前,需要先向操作系統發起申請內存的操作。操作系統會從進程的虛擬內存空間中查找未被使用的內存地址,并且返回給應用程序。

  操作系統會記錄進程正在使用中的虛擬內存地址,如果內存地址沒被登記,說明此內存地址是空閑的(未被使用)。

  我們繼續來看看 mmap_region() 函數的實現,代碼如下(經過精簡后):

  unsigned long

  mmap_region(struct file *file, unsigned long addr,

  unsigned long len, unsigned long flags,

  unsigned int vm_flags, unsigned long pgoff,

  int accountable)

  {

  struct mm_struct *mm = current->mm;

  struct vm_area_struct *vma, *prev;

  int correct_wcount = 0;

  int error;

  ...

  // 1. 申請一個虛擬內存區管理結構(vma)

  vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);

  ...

  // 2. 設置vma結構各個字段的值

  vma->vm_mm = mm;

  vma->vm_start = addr;

  vma->vm_end = addr + len;

  vma->vm_flags = vm_flags;

  vma->vm_page_prot = protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];

  vma->vm_pgoff = pgoff;

  if (file) {

  ...

  vma->vm_file = file;

  /* 3. 此處是內存映射的關鍵點,調用文件對象的 mmap() 回調函數來設置vma結構的 fault() 回調函數。

  *    vma對象的 fault() 回調函數的作用是:

  *        - 當訪問的虛擬內存沒有映射到物理內存時,

  *        - 將會調用 fault() 回調函數對虛擬內存地址映射到物理內存地址。

  */

  error = file->f_op->mmap(file, vma);

  ...

  }

  ...

  // 4. 把 vma 結構連接到進程虛擬內存區的鏈表和紅黑樹中。

  vma_link(mm, vma, prev, rb_link, rb_parent);

  ...

  return addr;

  }

  mmap_region() 函數主要完成以下 4 件事情:

  申請一個 vm_area_struct 結構(vma),內核使用 vma 來管理進程的虛擬內存地址,關于 vma 的詳細介紹可以參考:《Linux虛擬內存空間管理》。設置 vma 結構各個字段的值。通過調用文件對象的 mmap() 回調函數來設置vma結構的 fault() 回調函數,一般文件對象的 mmap() 回調函數為:generic_file_mmap()。把新創建的 vma 結構連接到進程的虛擬內存區鏈表和紅黑樹中。

  內核使用 vm_area_struct 結構來管理進程的虛擬內存地址。當進程需要使用內存時,首先要向操作系統進行申請,操作系統會使用 vm_area_struct 結構來記錄被分配出去的內存區的大小、起始地址和權限等。

  我們來看看 vm_area_struct 結構的定義:

  struct vm_area_struct {

  struct mm_struct *vm_mm;

  unsigned long vm_start;              // 內存區的開始地址

  unsigned long vm_end;                // 內存區的結束地址

  struct vm_area_struct *vm_next;      // 把進程所有已分配的內存區鏈接起來

  pgprot_t vm_page_prot;               // 內存區的權限

  ...

  struct rb_node vm_rb;                // 為了加快查找內存區而建立的紅黑樹

  ...

  struct vm_operations_struct *vm_ops; // 內存區的操作回調函數集

  unsigned long vm_pgoff;

  struct file *vm_file;                // 如果映射到文件,將指向映射的文件對象

  ...

  };

  struct vm_operations_struct {

  // 當虛擬內存區沒有映射到物理內存地址時,將會觸發缺頁異常,

  // 而在缺頁異常處理函數中,將會調用此回調函數來對虛擬內存映射到物理內存。

  int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);

  ...

  };

  當把文件映射到虛擬內存空間時,需要把 vma 結構的 vm_file 字段設置為要映射的文件對象,然后調用文件對象的 mmap() 回調函數來設置 vma 結構的 fault() 回調函數。

  vma 結構的 fault() 回調函數的作用是:當虛擬內存區沒有映射到物理內存地址時,將會觸發缺頁異常。而在缺頁異常處理中,將會調用此回調函數來對虛擬內存映射到物理內存。

  我們來看看 generic_file_mmap() 函數是怎么設置 vma 結構的 fault() 回調函數的:

  struct vm_operations_struct generic_file_vm_ops = {

  .fault = filemap_fault, // 將 fault() 回調函數設置為:filemap_fault()

  };

  int generic_file_mmap(struct file *file, struct vm_area_struct *vma)

  {

  ...

  vma->vm_ops = &generic_file_vm_ops;

  ...

  return 0;

  }

  至此,文件映射的過程已經分析完畢。我們來看看其調用鏈:

  sys_mmap()

  └→ do_mmap_pgoff()

  └→ mmap_region()

  └→ generic_file_mmap()

  2. 缺頁異常

  前面介紹了 mmap() 系統調用的處理過程,可以發現 mmap() 只是將 vma 的 vm_file 字段設置為被映射的文件對象,并且將 vma 的 fault() 回調函數設置為 filemap_fault()。也就是說,mmap() 系統調用并沒有對虛擬內存進行任何的映射操作。

  我們在《漫畫解說 “內存映射”》一文中介紹過,虛擬內存必須映射到物理內存才能使用。如果訪問沒有映射到物理內存的虛擬內存地址,CPU 將會觸發缺頁異常。也就是說,虛擬內存并不能直接映射到磁盤中的文件。

  那么 mmap() 是怎么將文件映射到虛擬內存中呢?我們在《 什么是頁緩存》一文中介紹過,讀寫文件時并不是直接對磁盤上的文件進行操作的,而是通過 頁緩存 作為中轉的,而頁緩存就是物理內存中的內存頁。所以,mmap() 可以通過將文件的頁緩存映射到虛擬內存空間來實現對文件的映射。

  但我們在 mmap() 系統調用的實現中,也沒看到將文件頁緩存映射到虛擬內存空間。那么映射過程是在什么時候發生的呢?

  答案就是:缺頁異常。

  由于 mmap() 系統調用并沒有直接將文件的頁緩存映射到虛擬內存中,所以當訪問到沒有映射的虛擬內存地址時,將會觸發 缺頁異常。當 CPU 觸發缺頁異常時,將會調用 do_page_fault() 函數來修復觸發異常的虛擬內存地址。

  我們主要來看看 do_page_fault() 函數對文件映射的實現部分,其調用鏈如下:

  do_page_fault()

  └→ handle_mm_fault()

  └→ handle_pte_fault()

  └→ do_linear_fault()

  └→ __do_fault()

  所以我們直接來看看 __do_fault() 函數的實現:

  static int

  __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,

  unsigned long address, pmd_t *pmd, pgoff_t pgoff,

  unsigned int flags, pte_t orig_pte)

  {

  ...

  vmf.virtual_address = address & PAGE_MASK; // 要映射的虛擬內存地址

  vmf.pgoff = pgoff;                         // 映射到文件的偏移量

  vmf.flags = flags;                         // 標志位

  vmf.page = NULL;                           // 映射到虛擬內存中的物理內存頁

  // 1. 如果虛擬內存管理區提供了 falut() 回調函數,那么將調用此函數來獲取要映射的物理內存頁,

  //    我們在 mmap() 系統調用的實現中看到,已經將其設置為 filemap_fault() 函數了。

  if (likely(vma->vm_ops->fault)) {

  ret = vma->vm_ops->fault(vma, &vmf);

  ...

  }

  ...

  if (likely(pte_same(*page_table, orig_pte))) {

  ...

  // 2. 通過物理內存頁生成一個頁表項值(可以參考內存映射一文)

  entry = mk_pte(page, vma->vm_page_prot);

  if (flags & FAULT_FLAG_WRITE)

  entry = maybe_mkwrite(pte_mkdirty(entry), vma);

  // 3. 將虛擬內存地址映射到物理內存(也就是將進程的頁表項設置為剛生成的頁表項的值)

  set_pte_at(mm, address, page_table, entry);

  ...

  }

  ...

  return ret;

  }

  __do_fault() 函數對處理文件映射部分主要分為 3 個步驟:

  調用虛擬內存管理區結構(vma)的 fault() 回調函數(也就是 filemap_fault() 函數)來獲取到文件的頁緩存。通過頁緩存的物理內存頁來生成一個頁表項值,可以參考《漫畫解說 “內存映射”》一文。將虛擬內存地址映射到頁緩存的物理內存頁(也就是將進程的頁表項設置為上面生成的頁表項的值)。

  對于 filemap_fault() 函數是怎樣讀取文件頁緩存的,本文不作解釋,有興趣的可以自行閱讀源碼。

  最后,我們以一幅圖來描述一下虛擬內存是如何與文件進行映射的:

微信截圖_20220929174107.png

  從上圖可以看出,mmap() 是通過將虛擬內存地址映射到文件的頁緩存來實現的。當對映射后的虛擬內存進行讀寫操作時,其效果等價于直接對文件的頁緩存進行讀寫操作。對文件的頁緩存進行讀寫操作,也等價于對文件進行讀寫操作。

  

更多信息可以來這里獲取==>>電子技術應用-AET<<

微信圖片_20210517164139.jpg

本站內容除特別聲明的原創文章之外,轉載內容只為傳遞更多信息,并不代表本網站贊同其觀點。轉載的所有的文章、圖片、音/視頻文件等資料的版權歸版權所有權人所有。本站采用的非本站原創文章及圖片等內容無法一一聯系確認版權者。如涉及作品內容、版權和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當措施,避免給雙方造成不必要的經濟損失。聯系電話:010-82306118;郵箱:aet@chinaaet.com。
热re99久久精品国产66热_欧美小视频在线观看_日韩成人激情影院_庆余年2免费日韩剧观看大牛_91久久久久久国产精品_国产原创欧美精品_美女999久久久精品视频_欧美大成色www永久网站婷_国产色婷婷国产综合在线理论片a_国产精品电影在线观看_日韩精品视频在线观看网址_97在线观看免费_性欧美亚洲xxxx乳在线观看_久久精品美女视频网站_777国产偷窥盗摄精品视频_在线日韩第一页
  • <strike id="ygamy"></strike>
  • 
    
      • <del id="ygamy"></del>
        <tfoot id="ygamy"></tfoot>
          <strike id="ygamy"></strike>
          午夜天堂精品久久久久| 亚洲在线网站| 国产在线不卡精品| 亚洲二区免费| 欧美日韩大陆在线| 欧美影院一区| 欧美日韩爆操| 午夜在线视频观看日韩17c| 欧美日本在线播放| 亚洲欧美激情精品一区二区| 国产精品狼人久久影院观看方式| 亚洲二区在线观看| 国产精品女人毛片| 樱花yy私人影院亚洲| 欧美日韩另类综合| 亚洲福利在线视频| 精品成人久久| 欧美一区成人| 国产精品日韩专区| 国产精品www色诱视频| 久久久久久高潮国产精品视| 欧美精品国产一区| 欧美日韩午夜剧场| 国产精品网站在线观看| 亚洲伦理在线免费看| 亚洲午夜在线观看| 欧美视频成人| 欧美日韩国产精品一区| 国产日韩精品在线播放| 激情欧美一区二区三区在线观看| 久久久久久电影| 亚洲素人一区二区| 欧美高清视频一区二区| 一区二区三区你懂的| 国产欧美日韩亚洲精品| 欧美v亚洲v综合ⅴ国产v| 久久免费视频在线| 欧美一级专区免费大片| 欧美三级黄美女| 国产乱码精品一区二区三区五月婷| 激情综合电影网| 亚洲精品在线电影| 一本一本久久a久久精品综合妖精| 在线视频免费在线观看一区二区| 蘑菇福利视频一区播放| 亚洲欧美国产高清va在线播| 久久精品国产77777蜜臀| 狠狠色狠狠色综合| 激情欧美丁香| 国产欧美日本一区二区三区| 午夜在线不卡| 亚洲欧美日韩第一区| 午夜精品久久99蜜桃的功能介绍| 国产亚洲成精品久久| 精品福利免费观看| 在线免费观看日本一区| 国产美女诱惑一区二区| 性欧美大战久久久久久久久| 一片黄亚洲嫩模| 久久综合九色综合欧美就去吻| 欧美特黄一级大片| 久久人人爽爽爽人久久久| 欧美日韩国产精品专区| 一区二区三区波多野结衣在线观看| 欧美日韩亚洲一区二区三区在线| 在线日韩成人| 亚洲国产精品激情在线观看| 久久噜噜噜精品国产亚洲综合| 欧美日韩理论| 欧美日韩精品在线播放| 香蕉成人啪国产精品视频综合网| 欧美在线视频网站| 狠狠色狠狠色综合日日91app| 黄色精品在线看| 国产视频一区在线| 国产日产精品一区二区三区四区的观看方式| 亚洲制服欧美中文字幕中文字幕| 欧美一级艳片视频免费观看| 亚洲精品永久免费精品| 久久精品99无色码中文字幕| 久久精品久久99精品久久| 国产伦精品一区二区三区免费| 99精品黄色片免费大全| 午夜久久久久久| 亚洲深夜福利| 欧美日本一道本在线视频| 米奇777超碰欧美日韩亚洲| 亚洲欧美久久久| 欧美日韩国产综合在线| 你懂的视频一区二区| 国模精品一区二区三区| 精品99视频| 欧美在线短视频| 免费91麻豆精品国产自产在线观看| 亚洲福利在线看| 欧美日韩国产首页在线观看| 久久综合久久综合久久综合| 亚洲第一精品福利| 欧美性jizz18性欧美| 国产精品一区久久久| 欧美日本在线视频| 久久精品成人| 美女被久久久| 久久视频国产精品免费视频在线| 原创国产精品91| 亚洲精品综合在线| 欧美二区视频| 欧美性久久久| 国产精品爱啪在线线免费观看| 国模 一区 二区 三区| 亚洲免费电影在线| 国产日韩一区二区三区在线| 亚洲国产婷婷综合在线精品| 影音先锋亚洲电影| 欧美日韩1区2区3区| 欧美二区在线| 欧美日韩在线观看一区二区| 久久免费视频在线| 欧美视频精品在线观看| 一本一本久久a久久精品综合妖精| 国产在线拍揄自揄视频不卡99| 久久久精品一品道一区| 欧美视频中文一区二区三区在线观看| 亚洲国内欧美| 亚洲国产人成综合网站| 欧美日韩国产综合视频在线观看| 日韩天堂在线视频| 99re66热这里只有精品3直播| 国产日韩亚洲欧美综合| 亚洲精品日韩久久| 中文在线不卡视频| 亚洲动漫精品| 国产三级欧美三级日产三级99| 这里只有视频精品| 欧美午夜性色大片在线观看| 国产有码一区二区| 夜夜嗨av一区二区三区网页| 91久久精品www人人做人人爽| 午夜精品久久久久久久白皮肤| 亚洲国产精品成人综合| 伊人久久亚洲影院| 欧美三级第一页| 久久精品国产免费看久久精品| 久久久久久久波多野高潮日日| 夜夜嗨av一区二区三区| 欧美色大人视频| 国产主播一区二区三区| 欧美三级在线视频| 国产女主播一区二区三区| 久久成人免费日本黄色| 国产一区二区三区黄| ●精品国产综合乱码久久久久| 亚洲天堂免费观看| 你懂的视频一区二区| 亚洲国产精品日韩| 影音国产精品| 欧美日韩国产精品一区二区亚洲| 欧美激情第六页| 亚洲一区在线直播| 欧美体内谢she精2性欧美| 亚洲电影欧美电影有声小说| 一区二区在线视频播放| 亚洲日本一区二区| 亚洲欧美国产日韩中文字幕| 久久av红桃一区二区小说| 亚洲欧美在线视频观看| 亚洲欧美日本日韩| 欧美成人一区二区在线| 一区电影在线观看| 在线免费观看日本欧美| 日韩亚洲欧美精品| 欧美日韩精品一区| 亚洲精品人人| 亚洲一区免费网站| 欧美精品久久99久久在免费线| 亚洲欧美日韩国产一区二区三区| 亚洲人成在线播放| 国内成+人亚洲+欧美+综合在线| 亚洲黄一区二区三区| 午夜精品www| 欧美日韩国产a| 欧美电影免费观看高清| 伊人久久亚洲影院| 国产精品综合不卡av| 亚洲视频一区在线| 亚洲一区免费| 樱桃成人精品视频在线播放| 午夜精品999| 国产噜噜噜噜噜久久久久久久久| 欧美激情性爽国产精品17p| 国产精品乱子久久久久| 亚洲一区三区视频在线观看| 欧美一区91| 伊人久久大香线蕉综合热线| 午夜精品国产更新| 亚洲色图制服丝袜| 久久免费视频这里只有精品| 亚洲国产欧美另类丝袜| 久久久久久久久久久久久久一区| 久久久久欧美精品| 最新国产乱人伦偷精品免费网站| 欧美日韩午夜在线视频| 久久久综合网站| 亚洲一区黄色| 亚洲人成绝费网站色www| 欧美一区亚洲| 亚洲一区二区日本| 欧美性色aⅴ视频一区日韩精品| aⅴ色国产欧美| 久久久www成人免费精品| 欧美精品一区在线播放| 国产精品电影观看| 欧美成人国产一区二区| 黄色日韩在线| 欧美伦理在线观看| 欧美视频在线不卡| 久久激情综合| 久久一区二区三区av| 国产精品青草综合久久久久99| 亚洲人成网在线播放| 久久国产精品久久久久久电车| 欧美日韩国产在线| 国产欧美在线观看一区| 久久久久网站| 国产美女高潮久久白浆| 亚洲视频网站在线观看| 欧美另类在线观看| 亚洲欧美日本国产专区一区| 亚洲性感美女99在线| 久久青草欧美一区二区三区| 国内精品99| 欧美日本三级| 国产精品网站视频| 欧美电影免费观看网站| 精品电影一区| 国产欧美一区二区精品仙草咪| 亚洲一区二区三区四区视频| 欧美吻胸吃奶大尺度电影| 影音先锋中文字幕一区二区| 亚洲字幕在线观看| 你懂的网址国产 欧美| 国产精品久久久久久久久借妻| 久久久久国产一区二区三区四区| 欧美视频网站| 欧美一区二区三区免费视| 鲁鲁狠狠狠7777一区二区| 在线看片成人| 久久精品男女| 亚洲高清视频一区二区| 欧美日韩免费在线| 极品少妇一区二区| 欧美好骚综合网| 鲁大师影院一区二区三区| 国产精品专区h在线观看| 日韩亚洲欧美成人一区| 亚洲欧美中文在线视频| 欧美精品免费看| 久久久噜噜噜久久中文字幕色伊伊| 欧美午夜性色大片在线观看| 国内揄拍国内精品久久| 激情综合色丁香一区二区| 精品动漫一区二区| 久久久av网站| 国产欧美日韩激情| 亚洲国产91精品在线观看| 一本久久青青| 久久夜色精品国产欧美乱极品| 一本久久综合亚洲鲁鲁| 欧美xx视频| 亚洲欧美综合精品久久成人| 亚洲区一区二| 久久精品国产精品亚洲综合| 欧美日韩一区二区三区| 国产亚洲网站| 欧美韩日一区| 国产精品久久777777毛茸茸| 亚洲欧美国产精品va在线观看| 亚洲免费成人av电影| 久久亚洲春色中文字幕久久久| 一区免费在线| 亚洲系列中文字幕| 欧美日韩成人在线播放| 国产精品久久久久久久7电影| 国产精品国产三级国产aⅴ无密码| 亚洲另类自拍| 欧美日韩一区二区免费视频| 亚洲高清不卡一区| 欧美激情在线播放| 久久av一区二区| 久久激情视频免费观看| 欧美日韩精品一本二本三本| 欧美精品色网| 国产精品美女一区二区在线观看| 欧美日韩三级| 亚洲午夜精品17c| 好看的亚洲午夜视频在线| 国产日韩欧美高清| 日韩视频在线免费观看| 欧美日韩国产精品一卡| 欧美日韩成人网| 久久伊人免费视频| 国产精品三区www17con| 亚洲香蕉成视频在线观看| av成人毛片| 国产欧美视频一区二区| 99综合精品| 亚洲高清不卡在线观看| 欧美国产在线视频| 免费久久99精品国产自在现线| 国产欧美另类| 国产精品v日韩精品| 国产精品高潮在线| 久久亚洲综合色一区二区三区| 亚洲尤物在线| 亚洲四色影视在线观看| 欧美性生交xxxxx久久久| 国产九九视频一区二区三区| 篠田优中文在线播放第一区| 久久久久国产精品一区二区| 久久综合免费视频影院| 欧美亚洲综合网| 99re8这里有精品热视频免费| 久久人人看视频| 9i看片成人免费高清| 一色屋精品亚洲香蕉网站| 国产精品亚洲一区二区三区在线| 在线观看视频免费一区二区三区| 国产视频综合在线|