久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

转一个solaris虚拟内存管理的wiki

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转一个solaris虚拟内存管理的wiki 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Virtual Meory management Wikipedia,自由的百科全書

1. 內存管理 1.1. 虛擬地址空間 1.1.1. 概述 Solaris的進程地址空間分配分為兩個階段:內核地址空間的分配和用戶地址空間的分配。內核地址空間的分配只在系統啟動時進行一次,當創建第一個內核進程,該進程的地址空間就是剛剛分配好的內核地址空間,而且之后所有的內核進程都共享該內核地址空間。在Solaris中,只有內核地址空間是經過分配得到的,之后利用fork進行進程創建時,都是直接復制父進程的地址空間。第一個用戶進程創建時,它會復制父進程的地址空間,也就是內核地址空間。 1.1.2. 數據結構 1.1.2.1. 重要數據結構間關系 圖1 數據結構關系圖 每個用戶進程都擁有自己獨立的地址空間,而所有的內核進程則共享唯一的內核地址空間。每個地址空間將若干segment driver封裝起來,這些segment driver以AVL樹的形式組織起來。每個地址空間都要有hat結構,在Solaris中,硬件地址轉換(Hardware Address Translation)實現利用hat數據結構來存放一個地址空間的頂級地址轉換信息。當segment driver試圖操作硬件MMU時,HAT層會被調用。如果一個segment driver試圖創建或者撤銷某個地址空間映射,它就會調用相應的HAT函數。而htable結構則用來描述硬件頁表。 1.1.2.2.as as結構是進程地址空間結構,每一個進程都對應一個as結構的變量。as結構在uts/common/vm/as.h中定義,它的定義如下: struct as { /*as結構的一些屬性*/ kmutex_t a_contents; /* 保護as結構中的一些域 */ uchar_t a_flags; /* 描述as的屬性*/ uchar_t a_vbits; /* 用來收集統計信息 */ kcondvar_t a_cv; /* 被as_rangelock使用*/ struct hrmstat *a_hrm; /* 維護引用信息和修改信息 */ caddr_t a_userlimit; /* 該地址空間的最高允許地址 */ size_t a_size; /* 地址空間的大小 */ /* 與hat結構相關的字段 */ struct hat *a_hat; /* hat數據結構*/ /*與segment相關*/ struct seg *a_seglast; /* 該地址空間中上次命中的segment */ krwlock_t a_lock; /* 保護與segment相關的一些域 */ struct seg *a_lastgap; /* 由as_gap()發現的最近一次的segment */ struct seg *a_lastgaphl; /* last seg saved in as_gap() either for */ /* AS_HI or AS_LO used in as_addseg() */ avl_tree_t a_segtree; /* 地址空間中的segment,以AVL樹的形式組織 */ avl_tree_t a_wpage; /* 守護頁 (procfs) */ uchar_t a_updatedir; /* 映射改變時,重建a_objectdir */ timespec_t a_updatetime; /* 映射上一次改變的時間 */ vnode_t **a_objectdir; /* 對象目錄 (procfs) */ size_t a_sizedir; /* 對象目錄的大小*/ struct as_callback *a_callbacks; /* callback列表*/ void *a_xhat; /* xhat提供者列表 */ }; as中的字段分成三個部分。第一個部分是用于描述as的一般性字段,包括用于保護as中域的互斥變量a_contents,描述as屬性的a_flags域,用來收集統計信息的a_vbits域,用來保護as_rangelock的條件變量,以及描述該地址空間大小的size域。 第二部分是與hat結構相關的字段。每個地址空間都需要有相應的hat結構,hat結構中主要存放地址轉換信息,幫助MMU完成虛擬地址到物理地址的轉換。第三部分是與segment相關的字段。 a_seglast表示該地址空間中最近一次命中的segment。每次對地址空間的訪問都需要更新該字段。 a_lock保護與segment相關的域,當對as中某個segment相關的域操作時,都需要用該讀寫鎖對這些域進行保護。 a_lastgaphl表示在as_gap()中存放的最近一次訪問的segment。在向地址空間增加一個segment時,為了提高效率,并沒有采用avl_find()方法來尋找插入點,而是簡單地以a_lastgaphl為起點尋找插入點(如果a_lastgaphl不空)。 a_segtree表示地址空間中所有segment組成的AVL樹。在Solaris中,地址空間中的所有segment都以AVL樹的形式組織起來。這樣,對segment進行增刪查改操作效率比較高。 a_wpage表示該地址空間的守護頁。這些守護頁也就是procfs。利用守護頁可以對內存中的一些段進行監控。 a_updatedir標示地址空間的映射發生變化,通知進程需要重建a_objectdir。例如,當向進程地址空間中,新增一個segment時,需要將該地址空間的a_updatedir域置為1。 a_updatetime表示最近一次地址映射發生變化的時間。 a_objectdir表示對象目錄。 a_callbacks是callback列表。該列表中主要是掛在segment driver上的回調函數列表。 1.1.2.3.seg seg結構是描述進程中segment的結構,每一個進程地址空間都由若干segment組成,這些segment組成一個AVL樹。seg結構在uts/common/vm/seg.h中,它的定義如下: struct seg { caddr_t s_base; /* 虛擬基地址 */ size_t s_size; /* 以byte計算的segment大小 */ uint_t s_szc; /* 該段所支持的最大的頁大小 */ uint_t s_flags; /* segment的標記*/ struct as *s_as; /* 該segment從屬的地址空間 */ avl_node_t s_tree; /* 在該地址空間中,針對該segment的AVL樹鏈接 */ struct seg_ops *s_ops; /* 對該segment的操作向量*/ void *s_data; /* 針對具體實例的私有數據*/ }; 每個地址空間都包含了若干segment,這些segment由不同的segment driver管理。Seg結構包含該segment的虛擬基地址,segment的大小,指向其所屬地址空間的指針,用來維護AVL樹的指針,以及掛在該segment driver上的回調函數和數據。可以看出,在seg結構中既包含描述segment的屬性信息,也包含對該segment進行操作、訪問的函數信息。 1.1.2.4.hat hat結構是進程地址空間結構,每一個進程都對應一個as結構的變量。as結構在uts/common/vm/as.h中,它的定義如下: struct hat { /* hat結構的一些屬性 */ kmutex_t hat_mutex; /* 整個hat結構的互斥量 */ kmutex_t hat_switch_mutex; /* hat切換時的互斥量 */ struct as *hat_as; /* 指向hat所屬的地址空間 */ uint_t hat_stats; /* hat結構的統計信息 */ pgcnt_t hat_pages_mapped[MAX_PAGE_LEVEL + 1]; cpuset_t hat_cpus; uint16_t hat_flags; /* hat的標記 */ /* 維護hat鏈表的字段 */ struct hat *hat_next; /* 指向下一個hat結構 */ struct hat *hat_prev; /* 指向上一個hat結構 */ /* 與htable相關的字段 */ htable_t *hat_htable; /* 指向頂級硬件頁表的指針 */ uint_t hat_num_hash; /* htable哈希數目 */ htable_t **hat_ht_hash; htable_t *hat_ht_cached; /* 空閑的htables緩存 */ x86pte_t hat_vlp_ptes[VLP_NUM_PTES]; }; hat中的字段分成三個部分。第一部分主要描述hat結構的屬性,包括一些互斥變量,hat所屬的地址空間指針,hat結構的統計信息,及hat的標記等。第二部分則包含了如何組織hat雙向鏈表的字段。 第三部分是一些與htable相關的字段。 hat_htable是指向頂級硬件頁表的指針。當進行地址轉換,調用HAT層時,通過hat結構就可以找到頂級硬件頁表,從而進行地址轉換。 1.1.3. 情景 1.1.3.1. 內核地址空間的分配 這個情景描述如何在系統啟動時分配整個系統中的第一個地址空間---內核地址空間,其中涉及到的主要函數包括:表1 內核地址空間分配中的主要函數函數名 文件名 功能描述 kvm_init uts/i86pc/os/Startup.c 內核虛擬地址空間的初始化工作 as_avlinit uts/common/vm/Vm_as.c 為地址空間分配所需的avl樹 as_addseg uts/common/vm/Vm_seg.c 將segment添加到指定的地址空間上 as_setprot uts/common/vm/Vm_as.c 為指定區域設置映射分配內核地址空間的工作主要在kvm_init()函數中完成。這個函數的流程如圖2所示。 圖2 kvm_init()的函數流程圖 kvm_init()首先為kas(內核地址空間的as結構)創建segment AVL樹和守護頁AVL樹,該過程是由as_avlinit()函數完成的。然后kvm_init()會調用seg_attach()及segkmem_create()函數來為內核地址空間添加必要的段,如內核代碼段,kvalloc段,內核debugger段。seg_attach()函數的主要實現工作是由as_addseg()函數完成的。as_addseg()函數的流程如圖2所示。 圖3 as_addseg()的流程圖 在as_addseg()函數中,為newseg尋找插入點時,為了提高效率,并沒有直接利用avl_find()來尋找插入點,而是先利用as的a_lastgaphl,該域存放的是as_gap()函數最近使用的segment。如果a_lastgaphl不為空,那么則以它作為初始點,為newseg尋找合適的插入點,如果找到符合條件的插入點,則調用avl_insert_here()函數將newseg插入到AVL樹中;如果a_lastgaphl為空,則利用avl_find()等函數來尋找符合條件的插入點。最后還需要判斷所找到的插入點表示的段與newseg段是否有重合,如果有重合,在sparc處理器下就需要調用seg_unmap()函數取消插入點所表示的段的映射,之后調用avl_insert()函數將newseg插入到AVL樹中。 利用seg_attach()及segkmem_create()函數來為內核地址空間添加好內核代碼段,kvalloc段及內核debugger段之后,kvm_init()調用as_setprot()來對Red Zone、內核代碼段及內核數據段設置相應的訪問權限。在這里,為了確保Red Zone域不為訪問,將其權限置為0;將內核代碼段的權限置為可讀/可寫/可執行;將內核數據段的權限置為可讀/可寫/可執行。圖4將給出as_setprot()函數的流程: 1.1.3.2.虛擬地址空間的釋放 這個情景描述如何釋放一個虛擬地址空間,其中涉及到的主要函數包括:表2 虛擬地址空間釋放中的主要函數函數名 文件名 功能描述 as_free uts/common/vm/Vm_as.c 釋放虛擬地址空間 hat_free_end uts/i86pc/vm/Hat_i86.c 進程地址空間正被銷毀,該函數將銷毀相應的hat xhat_free_end_all uts/common/vm/Xhat.c 銷毀相應的xhat 釋放虛擬地址空間的工作主要在as_free ()函數中完成。這個函數的流程如圖4所示: 圖4 as_free()的流程圖 as_free()函數將釋放一個地址空間,它的具體過程: 1. 它會調用as_do_callback()函數將所有的回調函數執行完畢,將回調函數列表清空 2. 進行hat結構釋放的開始工作 a) 首先將as的flag置為AS_BUSY,以阻止新的XHAT被附到as上 b) 調用hat_free_start來設置hat_flag為HAT_FREEING(在銷毀HAT時,需要設置該標志),為釋放hat做好準備 c) 調用xhat_free_start_all,主要的工作就是將xhat鏈表中的holder都設為curthread,為釋放xhat列表做好準備 3. 釋放as中的segment a) 利用SEGOP_UNMAP來取消對as中各段的映射,并會判斷其返回值err。若err=0表明正常執行;否則err==EAGAIN(表明當前段資源不可用),出現該err有兩種情況:callback未處理完,內存被加鎖,要進行等待。并回到步驟1重新進行。 4. 進行hat結構釋放的結尾工作 a) 調用hat_free_end來真正清除相應的hat結構? 確保hat當前沒有被page table stealing,然后從hat鏈表中刪除hat結構,并重置kas的hat鏈表? 將所有htables都釋放? 利用kmem_cache_free來釋放hat結構所占用的cache b) 調用xhat_free_end_all來釋放XHAT 5. 釋放as結構本身所占的空間 a) 釋放object directory(procfs)中的vnode b) 利用kmem_cache_fee釋放as結構 1.1.3.3.虛擬地址空間的復制 這個情景描述如何復制一個虛擬地址空間,其中涉及到的主要函數包括:表2 虛擬地址空間復制中的主要函數 函數名 文件名 功能描述 as_dup uts/common/vm/Vm_as.c 復制虛擬地址空間 seg_alloc uts/common/vm/Vm_seg.c 分配一個段,并將它附到相應的地址空間上 hat_dup uts/sfmmu/vm/hat_sfmmu.c 復制地址空間的地址轉換 xhat_dup_all uts/sfmmu/vm/Xhat.c 復制地址空間的xhat列表復制虛擬地址空間的工作主要在as_dup ()函數中完成。這個函數的流程如圖2所示: 圖5 as_dup流程圖 as_dup將復制一個地址空間,具體過程如下: 6. 調用as_alloc()為新的地址空間分配一個與之對應的as數據結構 7. 將原來地址空間所有的段都拷貝到新的地址空間中(利用一個循環) a) 調用seg_alloc()來分配一個段,并將這個新分配的段映射到新的地址空間中 b) 如果上面的seg_alloc()工作失敗,則會調用as_free()將新的地址空間釋放 c) 調用SEGOP_DUP()將原來段的操作復制到剛剛分配好的段中 d) 若復制段操作時發生錯誤,需調用seg_free()將剛剛分配的段釋放,然后調用as_fee()將新的地址空間釋放 8. 調用hat_dup()進行hat的復制工作 9. 調用xhat_dup_all()進行xhat的復制工作這里需要指出,hat_dup()和xhat_dup_all()只進行了一些字段取值的驗證,并沒有去進行實際的復制工作,這里hat和xhat都采用copy-on-write的策略完成復制。也就是說,只有真正去使用hat或xhat時,才會去進行復制工作。 1.2. 匿名內存 1.2.1. 概述 Solaris匿名內存是由segvn管理的,但并不直接與文件相關聯,匿名內存用于進程的棧,堆以及寫入時拷貝頁。匿名頁是通過anon層接口被創建的。當一個段第一次收到一個頁錯誤,它分配一個anon映像結構(該結構說明anon頭部在哪里)并在匿名映射的amp域里置入指向該anon頭部的指針。然后分配插槽數組,需要足夠大以至于能放下段內潛在的其他頁。插槽數組采用一次間接尋址和兩次間接尋址(一維數組和二維數組),這取決于需要插槽的數目。 32位系統由于要支持大于16MB的段,需要兩次間接尋址;64位系統,因為指針的長度更長,當支持大于8MB時需要兩次間接尋址。當只用一次間接尋址時,anon頭部的 anon_chunk直接引用了anon的插槽數組。當我們使用兩次間接尋址時,anon_chunk被分成兩大塊:針對32位系統,由2048個插槽組成的插槽塊和針對64位系統,由1024個插槽組成的插槽塊。這一分配過程由anon層接口anon_create實現。每一個anon插槽指向一個anon結構,anon結構描述了與地址空間內一頁大小的區域內容一致的虛擬內存頁。 使用匿名內存會有很多的優點。例如,當創建一個進程時,被創建的進程的所有地址都映射到物理內存的相同位(相同的頁)。但是如果子進程在此時要對內存做些不同的操作(例如子進程管理內存中的一個數組),vm子系統會將這些頁復制,并在子進程中改變映射指向新的頁。這些新頁即為匿名內存,子進程可以正常的修改數組,而不必知道這個數組已經有了一個新的物理內存了。這保證了存儲部分對子進程的透明。 1.2.2. 數據結構 1.2.2.1.重要數據結構之間的關系 1.2.2.2.anon結構 struct anon { struct vnode *an_vp; /* vnode of anon page */ struct vnode *an_pvp; /* vnode of physical backing store */ anoff_t an_off; /* offset of anon page */ anoff_t an_poff; /* offset in vnode */ struct anon *an_hash; /* hash table of anon slots */ int an_refcnt; /* # of people sharing slot */ }; 每個匿名頁,不論其在內存還是在對換區,都有一個anon結構。這個結構(也稱為插槽)提供了匿名頁和其后備存儲器之間的一個間接級的映射。(an_vp,an_off)為這個插槽指向匿名頁的vnode,(an_pvp,an_poff)指向這個插槽代表的頁的物理存儲器的位置。An_hash是anon插槽的一個散列表。這個列表由相關的匿名頁的(an_vp,an_off)進行散列,并且提供一個方法用于從一個匿名頁轉到相關的匿名anon插槽。An_refcnt用于一個引用計數,記錄了在寫入時拷貝的情況下,需要建立的各個分散的拷貝的數目。一個大于零的refcnt保護了插槽的存在。在anon_alloc被調用時,refcnt初始化為1 。 1.2.2.3.anon_hdr結構 struct anon_hdr { kmutex_t serial_lock; /* serialize array chunk allocation */ pgcnt_t size; /* number of pointers to (anon) pages */ void **array_chunk; /* pointers to anon pointers or chunks of */ /* anon pointers */ int flags; /* ANON_ALLOC_FORCE force preallocation of */ /* whole anon array */ }; anon數組指針在塊中分配。每個塊都有anon指針的pagesize/sizeof(u_long*),anon_hdr結構指向匿名數組,控制著匿名插槽的分配。 anon數組是二維指針數組比一個塊要大。第一級指針指向anon數組的塊,第二級包含anon指針的塊。如果anon數組比一個塊要小則建立整個的anon數組。如果anon數組比一個塊要大則僅僅第一維數組被分配。則另一維數組只在它們被anon指針初始化時分配。serial_lock,分配一個連續的數組塊。Size,記錄指向匿名頁的指針的數目。array_chunk,指向anon指針的指針。 1.2.2.4.anon_map結構 struct anon_map { krwlock_t a_rwlock; /* 保護anon_map結構和anon數組*/ size_t size; /* anon數組大小*/ struct anon_hdr *ahp; /*anon數組的頭指針, 包含anon指針數組*/ size_t swresv; /* 為anon_map結構而保存的交換空間 */ uint_t refcnt; /* 這個結構的引用計數 */ ushort_t a_szc; /*在共享的進程中最大的 szc */ void *locality; /* lgroup locality info */ }; 這是匿名內存中最核心的數據結構。 Anon_map結構用于各種各樣的anon從客戶端來進行匿名內存的管理。當匿名內存被共享時,不同的共享客戶端將會指向同一個anon_map結構。同樣的如果一個段在anon_map結構存在中間沒有被安排,則新創建的段將仍會共享anon_map結構,盡管這兩個段用到的是anon數組的不同范圍。 1.2.3.情景 1.2.3.1.匿名內存的分配 所用的函數: anonmap_alloc()為給定交換區的相關段分配并初始化一個anon_map結構. anon_create()創建指針列表. anon_get_slot()從列表中返回指定的匿名索引的指針。 anon_alloc()分配一個anon插槽,上鎖后返回該插槽. Anon_zero()分配一個私有的用零填充的anon頁 Anon_set_ptr()用一給定的指針設置列表項,該指針為一指定偏移量的指針. 流程圖如下: 詳細的說明: 1. 進入anonmap_alloc()函數,為給定交換區的相關段分配并初始化一個anon_map結構 2. 進入anon_create()函數,來創建指針列表,指向匿名數組(一維或二維) 3. 創建工作結束,進入匿名數組的操作,首先通過page_get_pagecnt()函數來得到可用匿名插槽的數目,如果可用插槽數目為0則將其標記為忙碌,若大于0則調用anon_array_lock()來鎖定插槽區域,獲取第一個插槽,并將此插槽置位忙碌,之后用anon_get_slot()來獲取一個匿名插槽。 4. 調用Anon_zero()來分配一個私有的用零填充的anon頁,在此函數中,用anon_alloc()來分配匿名插槽和它的鎖。通過[vp,offset]來尋找頁(page_lookup()),沒有找到,所以要調用page_lookup_create()來建立一個頁,并將其置位vp,offset。 5. 從頁空閑列表中根據所給的vp和offset選擇一個最合適的頁(page_get_freelist()),并將此頁上鎖(page_trylock()),并將此頁從空閑列表中移出(page_sub()),插入到散列表中(page_hashin())。請求此頁的i/o鎖(page_io_lock()),并將此頁插入到引用列表中(page_add)。 6. 調用Anon_zero()來分配一個私有的用零填充的anon頁,在此函數中,用anon_alloc()來分配匿名插槽和它的鎖。通過[vp,offset]來尋找頁(page_lookup()),沒有找到,所以要調用page_lookup_create()來建立一個頁,并將其置位vp,offset。 7. 從頁空閑列表中根據所給的vp和offset選擇一個最合適的頁(page_get_freelist()),并將此頁上鎖(page_trylock()),并將此頁從空閑列表中移出(page_sub()),插入到散列表中(page_hashin())。請求此頁的i/o鎖(page_io_lock()),并將此頁插入到引用列表中(page_add)。 8. 將此頁添0(pagezero()),將此頁鎖的等級從獨占鎖降為共享鎖(page_downgrade()). 9. 若有匿名頁,也將此匿名頁添0(anon_zero()),并用給定的指針設置列表項(anon_set_ptr()),通過hat層從實際的內存空間中分配此頁(在對換區域中)。退出匿名內存數組的操作(anon_array_exit())。 10. 至此,所有的操作完成。一個問題要注意:為什么anon結構要設置成一個數組?答案:每個anon結構代表了一個內存頁。而每一個段可能比一頁的大小要大,所以需要不止一個的anon結構去描述它,所以我們需要一個數組。 1.2.3.2.匿名內存的釋放 涉及到的函數: anonmap_free() 釋放anon結構 anon_release() 釋放匿名數組的指針 lgrp_shm_policy_fini()為anon_map結構釋放共享內存的決策樹和為零的本地空間。此函數在Lgrp.c文件中。流程圖: 詳細解釋: 1. 判斷anon_map結構中的ahp指針是否為空,若為空,則說明此anon頁已經被釋放,錯誤。若不為空則進入下一步。 2. 判斷匿名頁是否還有進程在引用,若refcnt=0則說明沒有進程在引用,則可以釋放。若refcnt!=0則錯誤。 3. 釋放在物理內存中的頁面 4. 釋放匿名數組,要分為兩種情況,即一維數組和二維數組的情況。 5. 清空對象緩存。 1.2.3.3. 分配一個anon插槽 函數anon_alloc() 流程圖: 詳細說明:anon_alloc參數為vnode和其偏移。首先聲明一個anon結構類型變量ap,ap是一個anon插槽。為ap在緩存中分配空間,若失敗則調用swap_alloc進行分配,若成功則將ap的兩個分量an_vp和an_off置為參數的值,并將ap的其他分量都初始化。根據an_vp和an_off進行散列,并插入散列表中并上鎖,最后返回指針ap。 1.2.3.4.匿名數組的拷貝 函數:anon_copy_ptr():拷貝anon數組sahp到另一個anon數組dahp. 流程圖: 詳細過程:拷貝anon數組sahp到另一個anon數組dahp。幾個參數的意義,s_idx指sahp數組塊的大小,d_idx指dahp數組塊的大小,npages指復制需要的頁面數。函數的執行過程:如果兩個數組都是一維的,要對sahp和dahp所指向的空間進行測試,(1)如果其小于ANON_CHUNK_SIZE的值才是合法值,然后調用bcopy函數對數組進行復制。(2)如果兩個數組都是二維的則相對要麻煩一些。同一維數組一樣,首先要測試sahp和dahp所指向的空間的大小是否合法,然后不斷測試npage的值,當其值大于零的時候則進入循環,相當于調用若干次的bcopy對若干個一維數組進行復制,最終得到二維數組的復制。(3)如果至少有一個數組是二維的,則在npage大于零的情況下,要求anon索引的指針不能為空,用anon_get_ptr函數得到索引指針并且放在ap中,并通過anon_set_ptr函數直接復制給dahp。 1.2.3.5.設置指針數組結構 函數:anon_create() 流程圖: 詳細說明:這個函數可以分配和回收指針,返回和設置給定的偏移的指針數組的入口。首先在內核內存中分配數組指針的空間,對數組指針的互斥鎖進行初始化。若數組是一維的,整個指針數組占npages個頁,則在內核內存中分配這npages個頁的anon指針的空間(用函數kmem_zalloc),若沒有分配成功則調用kmem_free尋找內核中的空閑區。若是二維數組,則只是在計算指針數組大小的時候麻煩一下,其余均一樣。最后返回這個數組的指針(anon_hdr*類型)。這里要說一下kmem_free函數的算法,將內核內存中空閑的塊建立為一個堆,從根部開始在其中查找與給定塊最相近的空閑塊,如果找到,則將給定的塊寫入到空閑塊中。 1.2.3.6.匿名頁引用計數的操作 函數:Anon_decref():對anon頁的引用減1,如果引用計數為零,則將其和其相關頁釋放。流程圖: 詳細過程:在散列表中找到ap指向的匿名頁,并通過臨界區訪問此頁,以保證互斥。(1)若引用此頁的計數不為零,則對其進行減1操作,如果減1以后對此匿名頁的引用變為零,則調用函數swap_xlate(),將一個匿名插槽轉換為其相關的vnode和vnode中的偏移,并查找此匿名插槽的頁,如果找到,則調用VN_DISPOSE函數將與之相關的匿名頁歸還到空閑列表中,以表示此頁真正成為空閑頁了。(2)若引用計數為零,則直接從散列表中將ap所指的匿名頁移除,如果ap_pvp所指的物理頁不為null則也要調用函數swap_phys_free將物理頁釋放。 1.2.3.7.匿名內存中數據的復制函數:anon_dup():復制anon頁size字節長度的內容。流程圖: 詳細過程:首先,調用btopr函數將要復制的長度size轉換為以頁為單位的度量即npages個頁。每復制一頁就將npages減1,找到index處開始第一個合法的anon指針賦給ap。然后,調用anon_set_ptr函數將old的內容復制到new處,并對每一個匿名頁的引用數都加1。函數中用off來記錄每頁中的偏移,進行復制。須注意,對頁的引用計數進行修改時要保證互斥進行,代碼如下: mutex_enter(ahm); ap->an_refcnt++; mutex_exit(ahm); 1.2.3.8.釋放一組anon頁 函數:anon_free():釋放一組anon頁,長度為size字節,并清空指向這些anon表項的指針。流程圖: 詳細過程:首先將size字節的長度轉換為以頁為單位,npages個頁。即轉換為釋放這npages個頁的函數。找出index后的第一個合法的anon指針ap,ap指向的是要釋放的第一頁。將此頁的列表項設置為null,調用anon_decref函數減少一個此頁的引用計數。當該引用的計數為0時,釋放該頁和與之關聯的頁(如果有的話)。將npages減1再進入循環,直至npages等于零,表明所有的匿名頁已被釋放。 1.3.Swap文件系統 1.3.1.概述現代操作系統都實現了“虛擬內存”這一技術,在功能上突破了物理內存的限制,使程序可以操縱大于實際物理內存的空間。有兩個基本的虛擬內存管理模型:交換(swapping)和按需換頁(demand pages)。交換模型的內存管理粒度是進程,當物理內存不足時,最不活躍的進程被換出內存。按需換頁的內存管理粒度是頁面,在內存匱乏時,只有最不經常使用的頁面被換出。Solaris中使用了這兩種虛擬內存管理方法。通常情況下使用按需換頁方式,在內存嚴重不足的時候采用交換的方式。在進行虛擬內存管理的時候,在系統的磁盤空間中,必須專門劃分出一個部分作為系統的Swap空間。Swap空間的作用可簡單描述為:當系統的物理內存不夠用的時候,就需要將物理內存中的一部分空間釋放出來,以供當前運行的程序使用。那些被釋放的空間可能來自一些很長時間沒有什么操作的程序,這些被釋放的空間被臨時保存到Swap空間中,等到那些程序要運行時,再從Swap中恢復保存的數據到內存中。這樣,系統總是在物理內存不夠時,才進行Swap交換。需要聲明的是,并不是所有從物理內存中交換出來的數據都會被放到Swap空間中,有相當一部分的數據直接交換到操作系統的文件系統中了。例如,有的程序會打開一些文件,對文件進行讀寫(其實每個程序都至少打開一個文件,那就是運行程序本身),當這些程序的內存空間需要交換出去時,文件部分的數據就沒有必要放到Swap空間中了,如果是讀文件操作,那么內存數據直接就釋放了,不需要交換出來,因為下次需要時,直接從文件系統就能恢復;如果是寫文件,只需要將變化的數據保存到文件中,以便恢復。但是那些用malloc( )和new等函數生成的對象的數據則不同,需要Swap空間,因為它們在文件系統中沒有相應的“儲備”文件,因此被稱為“匿名”(Anonymous)的內存數據,這類數據還包括堆棧中的一些狀態和變量數據等,所以說,Swap空間是“匿名”數據的交換空間。內存的每個物理頁面都由它的vnode和offset指定。當所要尋找的頁面不在內存中時,則vnode和offset指出該頁在后備存儲器中的位置。對于一個文件來說,物理頁緩存了文件的vnode和offset.交換空間就像一個后備存儲器,存儲內存的匿名頁,因此,當內存不足時,可以把內存的某頁交換到磁盤中,以增加內存空閑空間。因為交換空間是作為匿名內存的后備存儲器,所以我們必須首先確定是否有足夠的交換空間,以便可以把頁面交換出去。因此,在創建一個可寫入的映象前,我們要先申請交換空間。當有足夠的內存空間可裝入進程的內容時,Solaris內核允許匿名內存可不申請交換空間。這意味著在某些情況下,一個系統可以在很少或沒有交換空間下運行。通常情況下,Swap空間應大于或等于物理內存的大小,最小不應小于64M,通常Swap空間的大小應是物理內存的2-2.5倍。對于傳統的UNIX,在可寫入的虛擬內存中,其每個頁大小的單元都需要一個同等大小的交換空間。比如,在傳統的UNIX系統里,一個malloc要求分配8 Mbytes空間,那同時,它也要申請8 Mbytes的交換磁盤空間,盡管這些交換空間它可能從未用到。一般地,粗略估計進程所要的空間的大小是其所使用的物理頁的兩倍,這就導致了交換空間要等于兩倍大小的內存空間。而swapfs層允許Solaris在分配時更加謹慎,我們只需要讓交換空間等于虛擬內存的大小即可,該虛擬內存比機器中可用的可分頁物理內存大。 Solaris的交換使用swapfs來實現交換區域分配,以提高空間的使用效率。swapfs文件系統位于anon層和物理交換設備之間,是一個虛擬的文件系統。即使沒有分配物理交換空間,swapfs文件系統也使每個頁面如同有真實的后備交換空間。 swapfs文件系統使用一個全局變量:availrmen來跟蹤系統中可用且可分頁的物理內存,并把添加到可使用的交換空間中。當我們申請虛擬交換時,我們只是簡單地減少了可用的虛擬內存的總量。只要有充足的內存和物理交換空間可用,則該交換分配就是成功的。物理交換空間直到需要使用時才會分配。當我們創建一個私有段時,我們申請交換分區和分配anon結構。在這狀態中,直到一個真正的內存頁作為ZFOD或copy-on-write的結果被創建時,anon結構的分配等才會真正發生。當一個物理頁默認加入時,用vnode/offset對它進行標記。在Solaris中,當段驅動調用anon_alloc()去獲取一個新的匿名頁時,該匿名頁被分配swapfs vnode和offset。anon_alloc()函數通過swafs_getvp()進入swapfs,然后調用swapfs_getpage()創建一個帶有vnode/offset的新頁面。an_vp和an_off被初始化成swapfs虛擬交換設備的vnode和offset,這兩個an_vp和an_off是在anon結構中用來標明該頁的后備存儲的地址的。 在沒有page-out請求之前,并不需要任何物理交換空間。當段請求虛擬交換空間時,可用的虛擬交換空間的總量減少,但是,因為我們還不需要把頁置換到物理交換區,所以,物理交換空間并沒有被分配。當發生第一個page-out請求時,真正的交換分區才被分配。這時,頁掃描器為該頁檢查vnode,然后調用putpage()方法。因為該頁的vnode是swapfs vnode,因而調用swapfs_putpage()把該頁置換到交換設備。swapfs_putpage()分配物理交換分區的一個頁大小的塊給該頁面,然后把anon槽中的vnode an_pvp和an_poff設置為指向物理交換設備,接著該頁就被置換到交換設備中了。 另外,系統中有可能包含多個Swap分區,分區的數量對性能也有很大的影響。因為Swap交換的操作是磁盤I/O的操作,如果有多個Swap交換區,Swap空間的分配會以輪流的方式操作于所有的Swap,這樣會大大均衡I/O的負載,加快Swap交換的速度。 1.3.2.數據結構 1.3.2.1.重要數據結構關系 1.3.2.2.swapinfo 每個交換空間都有一個swapinfo結構來記錄該區域的相關信息。這些結構連成一個線性表,決定交換空間在邏輯交換設備中的順序。每個結構包含一個指針,指向相應的位圖,同時也說明該交換空間的大小,和它相應的vnode。Swapinfo結構在/uts/common/sys/swap.h中,它的定義如下: struct swapinfo { ulong_t si_soff; /*指明文件開始的偏移量*/ ulong_t si_eoff; /* 指明文件結束的偏移量*/ struct vnode *si_vp; /*指向一個結點*/ struct swapinfo *si_next; /*指向下一個交換空間 */ int si_allocs; /*該交換空間的分配結果*/ short si_flags; /* 標記*/ pgcnt_t si_npgs; /* 交換空間的頁面數 */ pgcnt_t si_nfpgs; /* 交換空間的空閑頁面數*/ int si_pnamelen; /*交換文件的名字長度加一 */ char *si_pname; /* 交換文件的名字*/ ssize_t si_mapsize; /*為位圖分配的字節 */ uint_t *si_swapslots; /*插槽的位圖,未置位標明該插槽為空*/ pgcnt_t si_hint; /*空閑頁的第一頁 first page to check if free */ ssize_t si_checkcnt; /*尋找空的插槽 # of checks to find freeslot */ ssize_t si_alloccnt; /* 用來獲取ave結果used to find ave checks */ }; ulong_t si_soff和ulong_t si_eoff分別指明文件在vnode中的開始地址和結束地址。 vnode *si_vp指向某設備的vnode。 swapinfo *si_next指向下一個交換空間,從而把所有的交換空間串連起來。 si_allocs指出交換空間的分配結果,si_flags是一個標記,以后會有詳細的定義。 pgcnt_t si_npgs和pgcnt_t si_nfpgs分別指出交換空間的頁面數和空閑頁面數 si_pnamelen的值為交換文件的名字長度加一 si_pname指出交換文件的名字 si_mapsize指出交換空間對應的位圖的比特數,系統中,每個物理交換空間都有一個相對應的位圖,該位圖用來表示它的物理容量。位圖記錄了哪個交換槽已經被使用或尚未使用。分配時是通過遍歷位圖來找到第一個空閑槽。因而,在交換設備中的偏移量和插槽所支持的頁面地址之間不存在線性關系。相反,這是一個一對一的映像。 si_swapslots插槽的位圖,未置位則標明該插槽可用。 si_hint指出空閑頁的第一頁; si_checkcnt尋找空的插槽 si_alloccnt用來獲取ave結果,ave為一個宏,表明空間分配了多長時間。 1.3.2.3. swapre swapre結構指出將要進入或移出交換空間的資源的路徑。Swapre結構在/uts/common/sys/swap.h中,其定義如下: typedef struct swapres { char *sr_name; /* 特定資源的路徑名*/ off_t sr_start; /*被交換資源的起始偏移地址g*/ off_t sr_length; /*交換空間的長度 */ } swapres_t; sr_name指出將要移入或移出交換空間的資源的路徑名稱 sr_start 指出被交換資源的起始偏移地址 sr_length指出交換空間的長度 1.3.2.4.swapent swapent結構保存交換文件(相當于交換設備,暫存換出頁面)的名字,將要進行交換的頁數等,它在/uts/common/sys/swap.h中,其結構定義如下: typedef struct swapent { char *ste_path; /* 獲取交換文件的名字 */ off_t ste_start; /* 交換的起始塊*/ off_t ste_length; /*交換空間的長度 */ long ste_pages; /* 可交換的頁數*/ long ste_free; /*空閑的交換頁數 */ int ste_flags } swapent_t; ste_path獲取交換文件的名字 ste_start指出交換的起始塊 ste_length交換空間的長度 ste_pages可以進行交換的頁數 ste_free 空閑的交換頁數 1.3.2.5.swaptable swaptable結構是一個數組,存儲swapent,指出有多少個交換文件。它在/uts/common/sys/swap.h中,其結構定義如下: typedef struct swaptable { int swt_n; /*指出有多少個交換文件*/ struct swapent swt_ent[1]; /* array of swt_n swapents */ } swaptbl_t; 1.3.3.情景 1.3.3.1.從設備中分配交換頁 表6 添加交換文件時用到的主要函數函數名 文件名 功能描述 swap_phys_alloc uts/common/vm/Vm_swap.c 分配指定大小的連續頁 swap_getoff uts/common/vm/Vm_swap.c 獲取設備中空閑頁的開始偏移量從物理設備中分配交換頁是通過函數swap_phys_alloc來完成的, 這個函數的流程如圖所示: 圖11 swap_phys_alloc函數流程圖 分配指定大小的,連續的物理交換頁。分配成功返回1,若一個頁面都分配不了,則返回0。首先對swapinfo表加鎖。然后在列表中逐個搜索,搜索有空閑頁的設備。如果調用者表明交換頁不從某個設備中分配,則交換頁應從其他設備中分配,于是應尋找不相同的設備,如果找到,轉到found;如果調用者沒有這種需求,則直接轉到found。sip指向所找到設備的swapinfo。調用swap_getoff,找到設備空閑頁的偏移地址soff。設備的空閑頁數減掉1。如果soff為-1,出錯。開始從設備中分配所需的頁面數。若分配過程中,設備的頁已分配完或剩下的比特數不夠一頁大小,則完成分配過程,盡管可能還未分配夠要求的頁數。把設備的vnode,偏移量soff,剛才分配的比特數len等返回給調用者。如果設備分配的交換頁數超過swap_maxconfig(一個宏,在anon_init中定義其大小),為了把負載平衡分配到各個設備,把該設備的si_allocs設為0,并且如果該設備排在鏈表的最后,把silast的值改為swapinfo鏈表的開頭結點。保存分配的信息,完成程序。 1.3.3.2.釋放物理交換頁 表7 釋放物理頁時用到的主要函數 函數名 文件名 功能描述 swap_phys_free uts/common/vm/Vm_swap.c 釋放指定設備的物理頁從指定設備中釋放頁是通過函數swap_phys_free來完成的, 這個函數的流程如圖所示: 圖12 swap_phys_free函數流程圖釋放一個物理頁。調用者給出欲釋放頁所在設備的vnode,頁的偏移量和頁大小。調用者給出的欲刪頁大小,并不符合設備中頁的規格,即調用者眼里的一頁和設備中的一頁大小是不一樣的。 首先,在swapinfo鏈表中開始查找。如果某個結點的vnode和指定vnode相同,且給出的偏移量超出結點范圍,則計算在指定偏移量之前的頁數pagenumber, 而npage是pangnumber和釋放頁數之和。 釋放每一頁。如果某頁對應的位圖表示該頁未曾使用,則打印:“釋放空閑頁。”把該頁對應的位圖清0,設備的空閑頁數加一。 1.3.3.3.釋放一個正在使用的交換頁 表8 釋放一個正在使用的交換頁用到的主要函數函數名 文件名 功能描述 swapslot_free uts/common/vm/Vm_swap.c 釋放指定設備的正在使用的物理頁 VOP_GETPAGE /on/usr/src/uts/common/sys/vnode.h 找到指定頁,并設置該頁屬性 swap_anon uts/common/vm/Vm_swap.c 找尋和指定vnode,off相關的anon swap_phys_free uts/common/vm/Vm_swap.c 釋放指定的交換頁頁 hat_setmod /on/usr/src/uts/common/vm/hat.h 為指定頁設置指定的屬性從設備中釋放正在使用的交換頁是通過函數swapslot_free來完成的, 這個函數的流程如圖所示: 圖13 swapslot_free函數流程圖釋放某個設備正被使用的交換頁,調用者需提供該設備的vnode,欲釋放頁在設備中的偏移量,和設備的swapinfo結點。使用VOP_GETPAGE獲取欲釋放的頁,如果VOP_GETPAGE返回錯誤信息,轉出錯處理。對找到的頁加鎖,添加互斥量。找到欲釋放頁所在的anon結構,把anon結構返回給ap;如果找不到相應的anon,出錯處理;如果ap的后備存儲的vnode和指定設備的vnode相同,且ap在設備中的偏移量沒超出設備的范圍,則調用swap_phys_free釋放該頁。把ap的an_pvp和an_poff置為空,調用hat_setmod對該頁屬性進行設置。 1.3.3.4.添加交換文件 表4 添加交換文件時用到的主要函數 函數名 文件名 功能描述 swapadd uts/common/vm/Vm_swap.c 增加新的交換設備到列表中,并在更新anoninfo計數器前轉移分配給它 common_specvp uts/common/fs/specfs/specsubr.c 對給定設備的vnode,函數返回和該設備vnode相關聯的通用vnode格式 mutex_enter /on/usr/src/lib/libzpool/common/kernel.c 對文件上鎖 mutex_exit /on/usr/src/lib/libzpool/common/kernel.c 對文件開鎖 kmem_zalloc /on/usr/src/uts/common/os/kmem.c 該函數在這里為swapinfo 結構分配指定大小的內存空間添加交換文件是通過函數swapadd來完成的,這個函數的流程如圖 7所示: 圖 8 swapadd函數流程圖 交換文件是用于交換的有固定長度的、規則的文件,交換設備相當于磁盤分區,交換設備和交換文件的作用一樣,設備掛靠到系統上時,系統就把設備當作一個文件來操作,添加交換文件可看作添加設備,以下的交換文件和交換設備都可統一看作交換文件。系統中所說的塊和頁其實是一樣的,都是頁的意思。 在函數的開始,先把交換設備的vnode轉化成文件系統通用的的vnode格式,這通過函數common_specvp實現。common_specvp把返回的vnode賦給cvp,cvp就表示了欲添加設備的vnode。 改變設備vnode的 標志位。先對設備加鎖,然后計算wasswap和vnode的v_flag,其中,wasswap表明設備是否是交換設備,計算完后開鎖。對互斥量swap_lock加鎖,調用VOP_OPEN打開欲添加的設備,如果成功,VOP_OPEN會為設備返回一個新的vnode;如果打開不成功,則恢復剛才改變的wasswap值。開鎖。獲取交換設備的屬性,如果設備的大小為零,或無法確定大小,則進行出錯處理。如果設備大小超過系統所能接受的范圍,則把它的大小限定為MAXOFF32_T(0x7fffffff),因為32位的操作系統不支持超過32位尋址的交換設備。判斷該交換設備是否可寫入。這通過VOP_SETATTR設置設備屬性來決定,如果成功設置,則設備可寫,否則進入出錯處理。判斷設備是否可進行頁I/O,如果不支持文件系統操作,則轉出錯處理。一般地,如果在根文件系統上進行交換,不要把和miniroot文件系統相應的交換塊放在空閑的交換列表中。因此,如果加入的設備作為根文件,則可用塊的起始地址要進行計算,具體前面多少塊不能用由klustsize(外部定義)決定。如果設備不是根文件,則起始地址由調用者指定,如果未指定,則從第二張頁面開始,因為第一張頁面存儲設備的標志。計算開始的偏移地址soff,如果大于設備的大小,則轉出錯處理。計算尾端的偏移地址eoff,如果大于設備大小,轉出錯處理。開始的偏移量soff和尾端的偏移量eoff進行頁面對齊,如果soff>=eoff,轉出錯處理。調用kmem_zalloc函數分配給swapinfo結構相應大小的內存。分配的空間的指針返回給nsip,則nsip指出交換設備的相關交換信息。對nsip的部分變量進行賦值:它的vnode,起始偏移量,尾端偏移量,對應的設備名稱。。。計算設備插槽(插槽相當于頁)相應位圖需要的字節數,給位圖分配相應的內存,并對每一位進行置位,然后檢查是否可以把交換設備添加到系統中。首先對swapinfo進行加鎖,由mutex_enter(&swapinfo_lock)完成。接著檢查全局變量swapinfo中是否已有該設備的vnode,如果找到的vnode和欲添加的vnode的偏移量一樣,只是先前被刪去的,把它恢復即可,然后解鎖,跳出程序;如果找到的vnode的偏移量的范圍被設備的偏移量完全覆蓋,則出錯。把設備加到列表中。判斷k_anoninfo中申請的頁數是否大于加上鎖的頁數,如小于,出錯;再判斷k_anoninfo中頁數的總量是否大于申請的數目,如果小于,出錯處理。把設備的頁數加到k_anoninfo的總數上,然后把cpu中相關線程的ani_count加上設備的頁數。如果在k_anoninfo中申請的頁面數大于已加鎖的,說明有一些申請為滿足,現在加入了一個設備,可把這個設備的頁面分配給請求者。如果系統中尚未有備份裝置,把剛添加的設備初始化為備份裝置。 1.3.3.5.刪除交換文件 表5 刪除交換文件時用到的主要函數 函數名 文件名 功能描述 swapdel uts/common/vm/Vm_swap.c 刪除某個設備刪除交換文件是通過函數swapdel這個函數的流程如圖 9所示: 圖 10swapdel函數流程圖 刪除交換文件是通過swapdel函數來完成的,調用者必須傳給swapdel欲刪除文件的vnode和刪除區域的起始塊地址。首先,函數把設備文件的vnode轉換成文件系統通用的vnode格式,這通過函數common_specvp實現。common_specvp把返回的vnode賦給cvp,cvp就表示了欲刪除設備的vnode。進行頁面對齊,獲取設備的開始偏移量soff。對全局變量swapinfo上鎖,在swapinfo中尋找設備的vnode。如果未找到,轉出錯處理。設備的信息賦給osip變量。對匿名內存k_anoninfo結構的信息進行判斷。如果申請的內存頁數小于被鎖的內存交換頁數,跳出程序;如果可申請的磁盤交換頁數小于已申請的磁盤交換頁數,跳出程序。如果系統中的所有的空閑頁數目小于欲刪除設備的頁數目,說明設備正在被使用,或系統無法騰出空間裝載在刪除設備中的內容,轉出錯處理。如果刪除設備后,請求的磁盤交換空間不足,可申請內存交換空間補足。先計算差額,然后從availrmem中分配內存。如果全局變量k_anoninfo中申請的內存交換空間小于被鎖住的,跳出程序;如果可分配的磁盤交換空間小于申請的數目,跳出程序;從系統中減去所刪除設備的頁數。對設備信息Osip的的標志位進行置位,防止再從該設備分配交換空間。準備釋放該設備的物理交換頁。在系統中,每個匿名頁都有一個anon結構。這個anon結構(slot)提供了匿名頁和其對應后備存儲的關系。對整個anon哈希表進行遍歷,找出有交換頁在欲刪除設備的anon slot,更新anon slot。在每個頁釋放后,都要返回anon slot相應的桶的開始,因為在釋放頁的時候,并沒有對整個哈希表加鎖,所以在釋放時哈希表可能會被別的進程改變。對哈希表一個個桶逐個遍歷。首先,獲取全局變量anon_hash的初始地址,然后對第一個桶進行分析,先對其加鎖。然后找這個桶中的每一個anon結構,如果某個anon的后備存儲為欲刪設備的頁,測試該頁對應的位圖情況,如果該頁已被使用,則把該頁對應vnode的v_count加1,把該頁從slot中釋放,然后把該頁對應的v_count減1。如果釋放成功,返回當前桶,繼續查找。如果釋放失敗,要把該頁恢復,全局變量k_anoninfo和availrmem等的相關值要重新加上該頁,然后轉出錯處理程序。遍歷完哈希表后,判斷是否完全完成釋放,這時應有空閑頁數和設備的頁數相等,否則終止程序。把設備從swapinfo列表中刪除。如果設備處于列表中的最后一個,則修改指針silast;釋放設備對應位圖的內存,釋放設備swapinfo對應的內存。如果設備屬于后備裝置,釋放。釋放設備的vnode,程序完成。 1.4.物理頁面管理 1.5.Vmem分配器 1.6.內核內存的初始化與布局 1.7.內核內存分配 1.7.1.概述 Solaris的內核內存分配器分成兩個層次。下層是后備分配器,它負責從內核地址空間分配整塊的內存供上層分配器使用,它分配的內存塊大小一般是一個頁或者是頁的整數倍。上層是slab分配器,它從后備分配器那里獲得整塊內存,然后把整塊內存分成小的內存塊,分配給內核程序。一整塊內存被稱為一個slab,這也是slab分配器名字的由來。后備分配器是一個vmem分配器,這是一個通用的資源分配器。后面的章節會對vmem分配器進行分析,這一節主要是分析slab分配器。 slab分配器吸收了面向對象的思想,它可以直接給用戶分配已經初始化好的對象,而且在釋放對象的時候,它也會調用相應的析構函數來銷毀對象。Slab分配器還采用了緩存的技術,每種類型的對象有一個單獨的緩存,以前分配的對象在釋放時并不是馬上銷毀,而是放回這個緩存中。以后再分配時,如果緩存中有空閑對象,就直接從緩存中分配,沒有的話再去創建一個新對象。采用緩存的辦法避免了每次分配對象都要進行一次初始化,從而加快了分配的速度。用戶在創建對象緩存的時候需要指定對象的規格,包括對象的尺寸、對齊邊界、構造函數和析構函數。除了可以分配初始化好的對象,slab分配器還實現了傳統的內存分配接口,可以分配任意大小的未初始化內存。在多CPU平臺中,不同的CPU在同時向內存分配器請求分配內存的時候會發生沖突。為了防止沖突破壞內存分配器的一致性,一個CPU在分配內存的時候必須對分配器加鎖,防止其他CPU同時分配內存。這樣的后果是不同CPU的內存分配操作必須順序進行,后一個CPU必須在前一個CPU分配完后才能開始分配,這就會造成效率的降低。CPU數量越多,這個問題越嚴重。為了解決這個問題,Solaris為每一個CPU配置了一個自己的局部緩存。CPU在分配內存的時候,首先從自己的緩存中分配,如果自己的緩存已空再從全局緩存中分配,這樣就降低了CPU沖突的概率。 CPU的局部緩存借用了自動步槍的原理,一個CPU是一支步槍,緩存中的對象是步槍的子彈,每分配一個對象就相當于打出一發子彈。子彈被放到彈夾(magazine)中,一個CPU的局部緩存中有兩個彈夾。分配對象時如果所有彈夾都被打空,就從全局分配器中換上一個滿彈夾。CPU釋放一個對象的時候相當于又獲得了一發子彈,它把這發子彈壓入彈夾中,供以后使用。釋放對象時如果CPU局部緩存中所有彈夾都是滿的,則用從全局分配器中換上一個空彈夾。為了存放全局的彈夾,slab分配器又引入了一個depot層,這個層相當于一個彈藥庫。depot層中有兩個鏈表,一個是空彈夾鏈表,一個是滿彈夾鏈表,每個CPU從彈藥庫中換彈夾時就是對這兩個鏈表進行操作。因此slab分配器可以看作是由三個層組成。最下層是slab層,它與頁分配器進行交互,申請或釋放整塊的內存,并把整塊內存劃分成小塊,供上層使用。中間是depot層,它是一個全局的彈夾管理器。最上面是CPU層,主要處理CPU的局部緩存。 Solaris中的slab分配器還考慮到了對CPU高速cache的影響。如果所有的對象都是從相同的對齊邊界開始(例如512字節對齊邊界),那么不同對象映射到同一個CPU緩存線(cache line)的概率就會增加,相應地也會增加cache的沖突和失效率,從而造成系統性能的下降。Solaris中引入了一個簡單的染色機制來解決這個問題。在對象緩存中,一個slab中對象的起始地址由一個染色值(color)決定,染色值不同,對象的起始地址也不同,所以映射到同一個緩存線的概率就會降低。一個對象緩存有一組可用的染色值,在創建slab的時候,這組染色值被循環使用,使得具有相同染色值的slab數量盡可能少。這樣就減少了cache沖突的次數,提高了系統的整體性能。 1.7.2.數據結構 1.7.2.1.重要數據結構間關系 圖14 數據結構關系圖 slab分配器中主要的實體是對象緩存。對象緩存的控制結構是kmem_cache,從kmem_cache出發可以訪問到緩存相關的數據結構,如kmem_slab、kmem_magazine等。系統中所有的對象緩存被串成一個雙向鏈表,通過全局變量kmem_null_cache可以訪問這個鏈表。一個對象緩存中可以包括多個slab,所有的slab鏈成一個雙向循環鏈表,通過kmem_cache中的cache_freelist字段可以引用這個鏈表。slab的控制結構是kmem_slab。一個slab被分成多個對象,每一個對象用一個kmem_bufctl結構來控制。slab中空閑的對象鏈成一個單向鏈表,kmem_slab中的slab_head字段指向這個鏈表的表頭。對象緩存中有兩個彈夾的鏈表,一個是空彈夾鏈表,一個是滿彈夾鏈表。彈夾的鏈表用kmem_maglist結構表示,鏈表中每一個彈夾用kmem_magazine結構表示。一個彈夾中可以裝載多個對象,對每一個裝載的對象,kmem_magazine中保存一個指向該對象起始地址的指針。每一個CPU有自己的局部緩存,這個局部緩存由kmem_cpu_cache結構控制。kmem_cache結構中有一個kmem_cpu_cache結構的數組,其中每一個元素表示一個CPU的局部緩存。每個CPU的局部緩存中包含兩個彈夾,一個是當前裝載的彈夾,一個是前一個裝載的彈夾。 1.7.2.2.kmem_cache kmem_cache結構是對象緩存的控制結構,每一個對象緩存都對應一個kmem_cache結構的變量。kmem_cache結構在uts/common/sys/kmem_impl.h中定義,它的定義如下: struct kmem_cache { /* 以下變量用于統計 */ uint64_t cache_slab_create; /* slab創建的次數 */ uint64_t cache_slab_destroy; /* slab銷毀的次數 */ uint64_t cache_slab_alloc; /* slab層分配的次數 */ uint64_t cache_slab_free; /* slab層釋放的次數 */ uint64_t cache_alloc_fail; /* 分配失敗的總次數 */ uint64_t cache_buftotal; /* 總的對象個數 */ uint64_t cache_bufmax; /* 出現過的最大對象個數 */ uint64_t cache_rescale; /* 重新調整hash表的次數 */ uint64_t cache_lookup_depth; /* hash查找的深度 */ uint64_t cache_depot_contention; /* depot層互斥沖突的次數 */ uint64_t cache_depot_contention_prev; /* depot層互斥沖突次數的前一個快照 */ /* 對象緩存的屬性 */ char cache_name[KMEM_CACHE_NAMELEN + 1]; /* 緩存名稱 */ size_t cache_bufsize; /* 對象大小 */ size_t cache_align; /* 對象的對齊邊界 */ int (*cache_constructor)(void *, void *, int); /* 構造函數 */ void (*cache_destructor)(void *, void *); /* 析構函數 */ void (*cache_reclaim)(void *); /* 回收函數 */ void *cache_private; /* 構造函數、析構函數和回收函數的參數 */ vmem_t *cache_arena; /* slab的后備分配器 */ int cache_cflags; /* 緩存的創建標識 */ int cache_flags; /* 緩存的狀態信息 */ uint32_t cache_mtbf; /* induced alloc failure rate */ uint32_t cache_pad1; /* to align cache_lock */ kstat_t *cache_kstat; /* exported statistics */ kmem_cache_t *cache_next; /* 系統中后一個緩存 */ kmem_cache_t *cache_prev; /* 系統中前一個緩存 */ /* Slab層 */ kmutex_t cache_lock; /* 保護slab層的互斥鎖 */ size_t cache_chunksize; /* 對象在slab中的實際大小 */ size_t cache_slabsize; /* 一個slab的大小 */ size_t cache_bufctl; /* buf起始地址到kmem_bufctl的偏移 */ size_t cache_buftag; /* buf起始地址到kmem_buftag的偏移 */ size_t cache_verify; /* 需要驗證的字節數 */ size_t cache_contents; /* bytes of saved content */ size_t cache_color; /* 創建下一個slab時用的染色值 */ size_t cache_mincolor; /* 可用的最小染色值 */ size_t cache_maxcolor; /* 可用的最大染色值 */ size_t cache_hash_shift; /* hash運算時地址移位的位數 */ size_t cache_hash_mask; /* hash表的掩碼 */ kmem_slab_t *cache_freelist; /* 空閑slab鏈表 */ kmem_slab_t cache_nullslab; /* 空閑鏈表尾部的標記 */ kmem_cache_t *cache_bufctl_cache; /* 分配kmem_bufctls結構的緩存 */ kmem_bufctl_t **cache_hash_table; /* hash表的基地址 */ void *cache_pad2; /* to align depot_lock */ /* Depot層 */ kmutex_t cache_depot_lock; /* 保護depot層的互斥鎖 */ kmem_magtype_t *cache_magtype; /* 彈夾類型 */ void *cache_pad3; /* to align cache_cpu */ kmem_maglist_t cache_full; /* 滿彈夾列表 */ kmem_maglist_t cache_empty; /* 空彈夾列表 */ /* CPU層 */ kmem_cpu_cache_t cache_cpu[1]; /* CPU局部緩存控制結構數組 */ }; kmem_cache中的字段分成五個部分。第一個部分是用于統計的字段,系統每次執行與該緩存相關的操作時會更新這些字段,它們的值用于做系統負載、性能等方面的統計。第二個部分是表示緩存屬性的字段。 cache_bufsize和cache_align保存了緩存中對象的大小和對齊邊界。 cache_constructor、cache_destructor和cache_reclaim是回調函數,它們分別是構造函數、析構函數和回收函數,這些函數由用戶在創建緩存的時候指定。cache_private是調用這三個回調函數時用到的參數。 cache_arena是比緩存低一級的分配器,緩存從這里獲取整塊內存(一般是頁的整數倍)來創建slab,然后再劃分成對象,釋放slab時slab對應的內存也歸還到這里。系統中所有的緩存通過cache_next和cache_prev字段鏈成一個雙向循環鏈表,這個鏈表的表頭是kmem_null_cache,這是一個kmem_cache類型的全局變量,定義在uts/common/os/kmem.c中。第三個部分是與slab層相關的字段。 cache_chunksize表示一個對象在slab中的實際大小。一個對象在slab中除了它本身要占用空間外,為了對齊還要占用一些空間,另外可能還會有一些調試信息,所有這些空間合稱為一個chunk,而cache_chunksize就是它的大小。 cache_slabsize是緩存中一個slab的大小,這個大小與cache_chunksize有關。一般小對象(chunksize小于512字節)對應的slab大小都是一個整頁(4K字節)。在slab中,如果一個小對象是空閑的,而且這個對象的大小可以放下kmem_bufctl和kmem_buftag結構,那么這個對象對應的內存塊會被用來存放這兩個控制結構。kmem_bufctl和kmem_buftag結構位于內存塊的末尾,cache_bufctl和cache_buftag字段分別表示對象的起始地址到這兩個結構的起始地址之間的距離。如果對象太大,使得一個slab可能跨越多個頁,或者對象太小,不能放下kmem_bufctl結構,那么即便對象是空閑的,kmem_bufctl也不能放在對象所占的內存塊中,而是要另外為kmem_bufctl分配一塊內存。在為kmem_bufctl分配內存的時候,把kmem_bufctl也看作是小對象,用的是與其它對象相同的分配方法。cache_bufctl_cache字段就是指向用于分配kmem_bufctl結構的對象緩存。 cache_hash_table是一個kmem_bufctl結構的hash表。當kmem_bufctl結構不位于對象所占的內存塊中時,就不能通過對象的起始地址計算出kmem_bufctl的地址。為了能快速找到對象的kmem_bufctl,Solaris為kmem_bufctl建了一個hash表,表的索引值就是對象的起始地址,這樣就可以通過起始地址快速在表中它的kmem_bufctl。 kmem_hash_shift和kmem_hash_mask字段與hash函數有關。slab中hash函數的過程是先把kmem_bufctl的地址右移kmem_hash_shift位,然后再與kmem_hash_mask做與操作,得到的值就是kmem_bufctl結構在hash表中的索引。 cache_color、cache_mincolor和cache_maxcolor這三個字段用于對slab進行染色。cache_color是創建下一個slab時用到的染色值,cache_mincolor是可用的最小染色值,cache_maxcolor是可用的最大染色值。一個對象緩存中所有的slab串成一個雙向循環鏈表,kmem_nullslab標識這個鏈表的結尾。這個鏈表分成三個部分,所有對象都已被分配的slab位于最前面的部分,部分被分配的slab位于中間,而完全空閑的slab位于尾部。部分被分配的部分和完全空閑的部分合稱為空閑列表,cache_freelist指向這個鏈表的表頭。kmem_nullslab是整個鏈表的尾部,因此它也是空閑鏈表的尾部。第四個部分是depot層相關的字段。 cache_magtype表示彈夾的類型。彈夾分成不同的類型,不同類型的彈夾中可以存放的對象數各不相同,可裝載對象的尺寸范圍也不同。這個部分中還有兩個鏈表字段,一個是滿彈夾鏈表cache_full,一個是空彈夾鏈表cache_empty,這兩個鏈表中存放的是全局的彈夾。第五個部分是與CPU層相關的字段。這個部分中只有一個字段cache_cpu,這是一個kmem_cpu_cache結構的數組,數組中有多少個元素由CPU的個數決定。每一個元素對應一個CPU,表示該CPU的局部緩存。在kmem_cache結構的聲明中,這個數組只有一個元素,但是在創建緩存的時候,系統會根據CPU的數目給kmem_cache結構多分配一些內存,保證數組中可以放下所有CPU局部緩存的控制結構。 1.7.2.3.kmem_slab kmem_slab結構是slab的控制結構,它在uts/common/sys/kmem_impl.h中定義,定義如下: typedef struct kmem_slab { struct kmem_cache *slab_cache; /* 所屬對象緩存的控制結構指針 */ void *slab_base; /* 第一個對象的起始地址 */ struct kmem_slab *slab_next; /* 空閑鏈表中的下一個slab */ struct kmem_slab *slab_prev; /* 空閑鏈表中的上一個slab */ struct kmem_bufctl *slab_head; /* 空閑對象鏈表的表頭 */ long slab_refcnt; /* 已經分配的對象數 */ long slab_chunks; /* 共有多少個對象 */ } kmem_slab_t; slab_cache字段是一個指向這個slab所屬對象緩存控制結構的指針。 slab_base字段表示這個slab中第一個對象的起始地址。前面提到,slab的第一個對象不一定位于slab的起始位置,它的地址與創建slab時分配的染色值有關。slab_base保存了第一個對象的地址,在實現中它就等于slab的起始地址加上染色值。 slab_next和slab_prev用來構建空閑slab鏈表。一個slab中所有空閑對象的控制結構組成一個單向鏈表,slab_head就指向這個鏈表的表頭。 slab_refcnt是引用數,實際上就表示這個slab中已經有多少個對象已經被分配出去。 slab_chunks表示slab中包括多少個chunk。一個chunk對應一個對象,因此這個字段實際上也指出了slab中有多少個對象。 1.7.2.4.kmem_bufctl kmem_bufctl是對象所占內存塊的控制結構,它在uts/common/sys/kmem_impl.h中定義,定義如下: typedef struct kmem_bufctl { struct kmem_bufctl *bc_next; /* 空閑列表中下一個內存塊 */ void *bc_addr; /* 內存塊的起始地址 */ struct kmem_slab *bc_slab; /* 所屬slab的控制結構指針 */ } kmem_bufctl_t; 這個結構中只有三個字段。bc_next表示空閑列表中的下一個內存塊;bc_addr表示這個內存塊的起始地址,實際上也是對象的地址;bc_slab表示這個內存塊所屬slab的控制結構的指針。 1.7.2.5.kmem_magazine、kmem_maglist和kmem_magtype 這三個數據結構是在管理彈夾的時候用到的主要數據結構,它們都是在uts/common/sys/kmem_impl.h中定義,定義如下: typedef struct kmem_magazine { void *mag_next; /* 彈夾鏈表中的下一個彈夾 */ void *mag_round[1]; /* 一發或多發子彈 */ } kmem_magazine_t; /* 每個CPU進行分配時所用的彈夾類型 */ typedef struct kmem_magtype { int mt_magsize; /* 彈夾尺寸(有多少發子彈) */ int mt_align; /* 彈夾對齊邊界 */ size_t mt_minbuf; /* 適用的最小內存塊尺寸 */ size_t mt_maxbuf; /* 允許調整的最大內存塊尺寸 */ kmem_cache_t *mt_cache; /* 用于分配彈夾數據結構的對象緩存 */ } kmem_magtype_t; /* 用于depot層的彈夾列表 */ typedef struct kmem_maglist { kmem_magazine_t *ml_list; /* 彈夾鏈表 */ long ml_total; /* 總彈夾數 */ long ml_min; /* 上次更新后彈夾數的最小值 */ long ml_reaplimit; /* 最多可以釋放的彈夾數 */ uint64_t ml_alloc; /* 從這個鏈表中分配了多少個彈夾 */ } kmem_maglist_t; kmem_magazine是彈夾的控制結構,它有兩個字段。mag_next字段指向彈夾鏈表中的下一個彈夾。mag_round是一個數組,其中每一個位置可以裝一發子彈。如果一個位置裝了一發子彈,那么這個位置的指針就指向一個空閑對象。在聲明中這個數組只有一個元素,但在實際分配內存的時候,系統會根據彈夾中能裝的子彈數分配出足夠的內存。 kmem_magtype表示彈夾的類型。 mt_magsize表示彈夾中可以裝多少發子彈,kmem_magazine中mag_round數組的大小就是由這個字段來決定。 mt_align表示彈夾的對齊邊界。 mt_minbuf和mt_maxbuf限定了這個彈夾類型的適用范圍。一種類型的彈夾并不是可以用于所有的對象,它所能裝對象的尺寸是有一定限制的,這兩個字段就給出了尺寸范圍。這兩個字段表示的尺寸不是對象本身的大小,而是前面所說的chunksize,也就是對象加上對齊和調試信息之后實際所占的內存塊大小。一個彈夾中裝載的對象的chunksize必須大于mt_minbuf。mt_maxbuf的用法與mt_minbuf的用法有所不同,它用于調整彈夾的類型。一個CPU在運行的時候可以調整它所用的彈夾類型,如果它發現當前類型中的彈夾裝載的子彈數太少,就會選擇子彈數更多的彈夾類型。在調整彈夾的時候,需要判斷對象的chunksize是否比當前彈夾類型的mt_maxbuf小。如果chunksize小于mt_maxbuf,則允許調整,CPU可以選擇下一級別的彈夾類型,否則的話就不能進行彈夾的調整。 mt_cache表示分配這種類型的彈夾使用哪一個對象緩存,分配不同類型的彈夾用到的對象緩存可能是不同的,但是分配同一類型的彈夾用的都是同一個對象緩存。系統中共定義了九種彈夾類型,每個彈夾必定屬于其中一種類型。這九種類型在uts/common/os/kmem.c中定義,定義如下: static kmem_magtype_t kmem_magtype[] = { { 1, 8, 3200, 65536}, { 3, 16, 256, 32768}, { 7, 32, 64, 16384}, { 15, 64, 0, 8192 }, { 31, 64, 0, 4096 }, { 47, 64, 0, 2048 }, { 63, 64, 0, 1024 }, { 95, 64, 0, 512 }, { 143, 64, 0, 0 }, }; 在這個定義中,只給出了每種類型前四個字段的值,最后一個字段,也就是mt_cache字段的值沒有給出。mt_cache字段指向分配彈夾所用的對象緩存,這些對象緩存是在uts/common/os/kmem.c中的kmem_cache_init函數中創建的,所以mt_cache字段也是在kmem_cache_init函數中賦的值。 kmem_maglist表示一個彈夾鏈表。 ml_list是鏈表的表頭,ml_total是鏈表中的總彈夾數。 ml_min表示從上次更新到當前時間彈夾鏈表中出現的彈夾數最小值。Solaris會定期更新對象緩存,也就是做對象緩存維護,包括更新對象緩存的統計信息、更新depot層的工作集和調整彈夾大小。每次在更新depot層工作集的時候,它會把depot層的空彈夾鏈表和滿彈夾鏈表中的ml_min設成鏈表的當前總彈夾數。隨著對象的分配和回收,彈夾鏈表中的彈夾數也在不斷變化,而ml_min保存了自上次更新以后出現過的最小彈夾數。 ml_reaplimit用于回收depot層的彈夾。這里有一個彈夾工作集的概念。在系統穩定工作的時候,所需的內存會保持在一個穩定的值,因此depot層中所需的彈夾數也會在一個穩定的范圍內,這時,所需的彈夾就構成一個彈夾工作集。例如在一段時間內,一個彈夾鏈表的彈夾數在30到40之間浮動,那么彈夾工作集就是10個彈夾(40 - 30),其余的彈夾一直閑置在彈夾鏈表中,在回收的時候就要回收這些閑置的彈夾。實際上ml_min就是閑置的彈夾數,因為它表示了一段時間內不同彈夾的最小值,在更新depot工作集的時候,Solaris會把ml_min的值賦給ml_reaplimit。在下次更新depot工作集之前,ml_reaplimit的值就不會再改變了,但是彈夾鏈表中的彈夾數是會發生變化的,所以在實際回收的時候,回收的彈夾數會取ml_reaplimit和當前彈夾總數中的最小值。 1.7.2.6.kmem_cpu_cache kmem_cpu_cache結構是CPU局部緩存的控制結構,它在uts/common/sys/kmem_impl.h中定義,定義如下: typedef struct kmem_cpu_cache { kmutex_t cc_lock; /* 保護CPU局部緩存的互斥鎖 */ uint64_t cc_alloc; /* 這個局部緩存中已分配的對象數 */ uint64_t cc_free; /* 這個局部緩存中的空閑對象數 */ kmem_magazine_t *cc_loaded; /* 當前裝載的彈夾 */ kmem_magazine_t *cc_ploaded; /* 前一個裝載的彈夾 */ int cc_rounds; /* 當前裝載的彈夾中還有多少發子彈 */ int cc_prounds; /* 前一個裝載的彈夾中還有多少發子彈 */ int cc_magsize; /* 滿彈夾中有多少發子彈 */ int cc_flags; /* 全局對象緩存cache_flags字段的拷貝 */ char cc_pad[KMEM_CPU_PAD]; /* 用于邊界對齊 */ } kmem_cpu_cache_t; cc_alloc表示當前CPU的局部緩存中已經分配了多少個對象,cc_free表示還有多少個空閑對象。 cc_loaded和cc_ploaded表示CPU裝載的兩個彈夾。當從depot層裝載一個新彈夾的時候,cc_loaded指向新裝載的彈夾,cc_ploaded指向cc_loaded原來所指的彈夾,而cc_ploaded原來所指的彈夾被歸還到depot層。保存兩個彈夾的目的是為了防止抖動。如果只有一個彈夾,現在考慮彈夾中只有一個對象的情況,如果CPU要連續分配兩個對象,那么第一個對象可以直接從彈夾中分配,而分配第二個對象時就需要局部緩存從depot層裝載一個滿彈夾,并把當前的空彈夾還給depot層,再從滿彈夾中分配;下一步CPU要連續釋放兩個對象,由于彈夾中還有一個空位,所以第一個對象可以直接存到彈夾中,但是釋放第二個對象時就需要從depot層裝載一個空彈夾,并把滿彈夾還給depot層,然后把空閑對象放到空彈夾中。這時,CPU的局部緩存中的彈夾又變成只有一個對象的情況。如果這種操作反復進行,那么局部緩存就需要反復地與depot層交互,從而出現抖動。如果有兩個彈夾的話,只要其中有一個彈夾中有空閑對象,就可以分配對象,而只要其中一個彈夾有空位,就可以釋放對象,這就避免了抖動的情況。 cc_rounds和cc_prounds分別表示當前裝載的彈夾和前一個裝載的彈夾中的空閑對象數,而cc_magsize表示彈夾中最多可以裝載多少個對象。 cc_flags是局部緩存所在的對象緩存中cache_flags字段的拷貝,在這里放一份拷貝是為了操作方便。 1.7.3.情景 1.7.3.1.創建對象緩存 表9 創建對象緩存時用到的主要函數函數名 文件名 功能描述 kmem_cache_create uts/common/os/kmem.c 在內核空間分配一個已初始化的對象創建對象緩存是通過kmem_cache_create函數完成的,這個函數的流程如圖2所示: 圖15 kmem_cache_create函數流程圖創建對象緩存的時候需要給對象緩存起一個名字,這個名字要符合C語言的命名規范,kmem_cache_create函數首先會調用strident_valid函數來驗證緩存的名字。然后要為對象緩存的控制結構分配空間,這通過調用vmem_xalloc函數來完成。vmem_xalloc函數從kmem_cache_arena區域分配一塊內存,內存的大小通過KMEM_CACHE_SIZE宏來計算。這個宏根據系統中CPU的個數調整內存塊的大小,保證位于控制結構末尾的局部緩存數組可以容下所有CPU的局部緩存。新分配的內存塊中所有的字節都被初始化為0。接下來就要設置控制結構的各個字段了,這大致分成設置對象緩存屬性、設置slab層、設置depot層和設置CPU層幾個部分,下面就部分字段進行說明。 cache_align字段根據align參數來設置。首先要檢查align的值,如果它的值為0,就把它設成默認的對齊邊界(8字節,在KMEM_ALIGN宏中定義)。另外align的值必須是2的冪,而且它不能大于下層分配器的基本分配單位,否則會報錯。接下來kmem_cache_create函數會對cflags進行檢驗和設置,保證里面的各個標識位都是合理的,然后把cflags的值賦給cache_cflags字段。 cache_constructor、cache_destructor等字段由調用者通過參數來設置。 cache_chunksize字段的值需要根據cache_bufsize字段的值來計算。首先把cache_bufsize按對齊邊界對齊;如果cache_flags中的KMF_BUFTAG位被置位,就再加上kmem_buftag結構的大小;最后再按對齊邊界對齊一次,得到的值就是chunk的大小。有了chunk的大小,就可以算出cache_bufctl、cache_buftag、cache_contents等字段的值。然后要找一個合適的slab大小。如果cache_chunksize小于下層分配器基本分配單位的1/KMEM_VOID_FRACTION(KMEM_VOID_FRACTION的值為8),而且cache_cflags的 KMF_NOHASH位被置位,則slab的大小就等于基本分配單位的大小。否則的話就分別考慮slab中分別包括1個到8個chunk的情況,從中找出內存浪費最少的一個情況,slab的大小就等于這種情況下的chunk數乘以chunk大小,再按基本分配單位對齊。 depot層的設置主要就是考慮選擇一個合適的彈夾類型,選擇的原則就是從彈夾類型鏈表中找第一個適用的彈夾類型(mt_minbuf字段小于chunk大小的類型),找到后就把這個類型賦給cache_magtype字段。設置完各個字段的值后,kmem_cache_create函數會把新建的對象緩存添加到全局對象緩存鏈表中,把它插在kmem_null_cache之前。最后,如果kmem_ready的值非0,也就是內核內存的初始化已經完成,說明用于分配彈夾的對象緩存已經創建完畢,這時就開啟對象緩存的彈夾機制。 1.7.3.2.分配對象 這個情景描述在內核空間分配一個已經初始化好的對象,其中涉及到的主要函數包括:表10 內核對象分配中的主要函數函數名 文件名 功能描述 kmem_cache_alloc uts/common/os/kmem.c 在內核空間分配一個已初始化的對象 kmem_depot_alloc uts/common/os/kmem.c 從depot層申請一個滿彈夾 kmem_depot_free uts/common/os/kmem.c 把CPU換下的空彈夾加入到depot層的空彈夾鏈表中 kmem_slab_alloc uts/common/os/kmem.c 在slab層創建一個對象,并把它分配給調用者 kmem_slab_create uts/common/os/kmem.c 為一個對象緩存創建一個新的slab 內核程序要分配一個對象的時候,需要調用kmem_cache_alloc函數。這個函數的流程如圖2所示: 圖16 kmem_cache_alloc函數流程圖 kmem_cache_alloc首先從CPU自己的緩存中分配。如果CPU的兩個彈夾中都沒有可分配的對象,則調用kmem_depot_alloc函數從depot層的滿彈夾鏈表中裝載一個滿彈夾,然后把滿彈夾設為當前彈夾,重新執行分配過程。裝載滿彈夾時會替換下CPU前一個裝載的彈夾,被換下的彈夾一定是一個空彈夾,所以要調用kmem_depot_free函數把這個彈夾放入depot層的空彈夾鏈表中。如果獲取滿彈夾失敗,則說明滿彈夾列表為空,depot層也沒有可以分配的對象,這時就調用kmem_slab_alloc函數直接從slab層分配一個對象。kmem_slab_alloc分配的對象是未初始化的對象,最后還要用構造函數對這個對象進行初始化。從slab層分配對象時調用的是kmem_slab_alloc函數,這個函數的流程如圖3所示: 圖17 kmem_slab_alloc函數流程圖 這個函數中需要說明的是如何獲取slab中一個空閑內存塊的地址。獲取地址的代碼如下: if (cp->cache_flags & KMF_HASH) { /* * Add buffer to allocated-address hash table. */ buf = bcp->bc_addr; hash_bucket = KMEM_HASH(cp, buf); bcp->bc_next = *hash_bucket; *hash_bucket = bcp; if ((cp->cache_flags & (KMF_AUDIT | KMF_BUFTAG)) == KMF_AUDIT) { KMEM_AUDIT(kmem_transaction_log, cp, bcp); } } else { buf = KMEM_BUF(cp, bcp); } 從kmem_slab結構中只能獲取空閑內存塊的控制結構,也就是一個kmem_bufctl變量,然后需要從kmem_bufctl得出空閑塊的地址。在kmem_cache結構的介紹中提到內存塊的控制結構可能放在內存塊中,也可能另外為它分一塊內存,如果另外分配內存的話,就需要一個存放控制結構的hash表。kmem_cache結構的cache_flag字段中有一位會標出是否要用到hash表。在從kmem_bufctl結構獲得內存塊地址的時候,要對這一位進行判斷。如果用到hash表,則kmem_bufctl的bc_addr字段就指向內存塊的地址;如果kmem_bufctl就在內存塊中,就可以從控制結構直接計算出內存塊的地址。這個計算是通過KMEM_BUF宏完成的,這個宏在uts/common/sys/kmem_impl.h中定義。在沒有空閑slab時需要調用kmem_slab_create函數創建一個新的slab,它的流程如圖4所示: 圖18 kmem_slab_create函數流程 這個函數在為kmem_slab控制結構分配內存的時候,會根據對象緩存是否使用hash表來決定是為控制結構另外分配一塊內存還是利用slab末尾的內存。同樣,在為每個小內存塊的控制結構分配內存的時候,也要根據是否使用hash表來決定是為控制結構另外分配內存還是直接利用小內存塊本身的內存。如果不使用hash表,則不需要另外分配內存。為了節省空間,在流程圖中為小內存塊設置控制結構這一塊簡略表示了。為slab控制結構分配內存的代碼如下: if (cache_flags & KMF_HASH) { if ((sp = kmem_cache_alloc(kmem_slab_cache, kmflag)) == NULL) goto slab_alloc_failure; chunks = (slabsize - color) / chunksize; } else { sp = KMEM_SLAB(cp, slab); chunks = (slabsize - sizeof (kmem_slab_t) - color) / chunksize; } 代碼中為控制結構另外分配內存時調用的也是kmem_cache_alloc函數,它從kmem_slab對應的對象緩存中分配。kmem_slab的對象緩存是不使用hash表的,否則在分配kmem_slab對象的時候有可能引起對kmem_slab對象緩存的遞歸分配,最后導致內存分配失敗。 KMEM_SLAB宏用來根據slab的地址計算slab控制結構的地址。相應地,在分配小內存塊控制結構的時候,KMEM_BUFCTL宏用來根據小內存塊的地址計算小內存塊控制結構的地址。 1.7.3.3.釋放對象 表11 釋放對象時用到的主要函數函數名 文件名 功能描述 kmem_cache_free uts/common/os/kmem.c 釋放一個已初始化的對象 kmem_slab_free uts/common/os/kmem.c 在slab層釋放一個內存塊 kmem_slab_destroy uts/common/os/kmem.c 銷毀一個slab 釋放對象是與分配對象相反的過程。釋放對象時調用的是kmem_cache_free,這個函數在uts/common/os/kmem.c中定義,它的流程如圖5所示: 圖19 kmem_alloc_free函數流程圖如果CPU當前裝載的彈夾中有空位,那么就把被釋放的對象放到空位中,也就是讓對象數組中的一個空閑指針指向被釋放的對象。如果當前裝載的彈夾是滿的,那么就看前一個裝載的彈夾是否還有空位。如果有空位的話就把當前裝載的彈夾和前一個裝載的彈夾交換一下位置,再重新做釋放操作。如果局部緩存中的兩個彈夾都是滿的,那么就需要調用kmem_depot_alloc函數從depot層獲取一個空彈夾,并通過調用kmem_depot_free函數把一個滿彈夾還給depot層,然后再重新做釋放操作。如果depot層的空彈夾鏈表中已經沒有空彈夾,就調用kmem_cache_alloc函數從彈夾的對象緩存中分配一個新彈夾(空彈夾),然后重新做釋放操作。這也就是說一個對象緩存在剛創建的時候,depot層中的滿彈夾鏈表和空彈夾鏈表都是空的,以后用到的彈夾都是在釋放對象時創建的。彈夾在被創建后,除非出現內存緊張或者需要調整彈夾尺寸的情況,它們不會被銷毀,而是隨著申請對象和釋放對象操作的交替進行,慢慢分布到depot層的空彈夾鏈表或滿彈夾鏈表中。如果創建新彈夾失敗,就無法把被釋放的對象緩存到depot層,這時就調用析構函數銷毀對象,再調用kmem_slab_free函數把對象所占的內存塊還給slab層。 kmem_slab_free函數的功能是釋放一個已分配的未初始化內存塊,它在uts/common/os/kmem.c中定義,它的流程如圖6所示: 圖20 kmem_slab_free函數流程圖 kmem_slab_free首先要得到內存塊的控制結構和slab的控制結構。如果這個slab使用hash表存儲控制結構,則查詢hash表,否則直接從內存塊的地址算出控制結構的地址。由于這個slab釋放了一個內存塊,也就是說這個slab現在肯定包含有空閑內存塊,所以如果這個slab以前不在對象緩存的空閑slab鏈表中,現在就把它加進去。然后把被釋放的內存塊插入到這個slab的空閑內存塊鏈表的頭部。如果釋放完這個內存塊后slab中所有的內存塊都是空閑的,就可以回收這個slab所占的內存空間。回收slab時首先要把這個slab從空閑slab鏈表中移除,如果這個slab恰好是空閑鏈表的表頭,那么還要修改表頭,讓表頭指向下一個空閑slab。然后就可以調用kmem_slab_destroy函數銷毀slab了。 kmem_slab_destroy函數比較簡單,它完成的工作包括兩步:第一步,如果slab的控制結構占用了另外的空間,就釋放這些空間;第二步,調用底層分配器的釋放函數(vmem_free),釋放slab所占的內存。 1.7.3.4.分配與釋放未初始化內存塊 表12分配與釋放未初始化內存塊時用到的主要函數函數名 文件名 功能描述 kmem_alloc uts/common/os/kmem.c 分配一塊任意大小的未初始化內存 kmem_zalloc uts/common/os/kmem.c 分配一塊任意大小的內存塊,內存塊全部初始化為0 kmem_free uts/common/os/kmem.c 釋放一個未初始化內存塊 Solaris的slab內存分配器除了可以分配已初始化的對象,它還可以像普通的分配器一樣分配和釋放任意大小的未初始化的內存,完成這兩個操作的函數分別是kmem_alloc和kmem_free。 kmem_alloc函數在uts/common/os/kmem.c中定義。在調用kmem_alloc函數的時候需要給出所需內存塊的尺寸,kmem_alloc會根據尺寸進行不同的分配操作。對于小于16k(在常量KMEM_MAXBUF中定義)的內存塊,slab分配器采用了與分配對象相同的方法,它把未初始化的內存看作構造函數和析構函數都為空的對象。系統在初始化的時候創建了32個用于分配未初始化內存的對象緩存,它們對應的內存塊尺寸在kmem_alloc_sizes數組中給出。 static const int kmem_alloc_sizes[] = { 1 * 8, 2 * 8, 3 * 8, 4 * 8, 5 * 8, 6 * 8, 7 * 8, 4 * 16, 5 * 16, 6 * 16, 7 * 16, 4 * 32, 5 * 32, 6 * 32, 7 * 32, 4 * 64, 5 * 64, 6 * 64, 7 * 64, 4 * 128, 5 * 128, 6 * 128, 7 * 128, P2ALIGN(8192 / 7, 64), P2ALIGN(8192 / 6, 64), P2ALIGN(8192 / 5, 64), P2ALIGN(8192 / 4, 64), P2ALIGN(8192 / 3, 64), P2ALIGN(8192 / 2, 64), P2ALIGN(8192 / 1, 64), 4096 * 3, 8192 * 2, }; 為了實現內存塊尺寸到32個對象緩存的映射,Solaris聲明了一個全局數組kmem_alloc_table。數組中有2048個元素(KMEM_MAXBUF >> KMEM_ALIGH_SHIFT),每個元素是一個指向對象緩存的指針。數組中每個元素對應一個內存塊尺寸,尺寸從前往后依次遞增,每次遞增的值是8字節(也就是最小對齊邊界,在常量KMEM_ALIGN中定義)。第一個元素對應8字節的內存塊,第二個元素對應16字節的內存塊,……,最后一個元素對應16k字節的內存塊。在初始化的時候,系統令kmem_alloc_table數組中某一元素指向大于它所對應內存塊尺寸的第一個對象緩存。kmem_alloc_table數組元素和32個對象緩存的對應關系如圖5所示。 圖21 kmem_alloc_talbe數組與32個對象緩存之間的關系如果要分配一定尺寸的一塊內存,分配器首先在kmem_alloc_table數組中找到大于該尺寸的第一個元素,再根據該元素中的指針找到相應的對象緩存,然后就調用前面所講的kmem_cache_alloc函數從對象緩存中分配一塊內存。如果要分配大于16k字節的內存塊,就不能用上面提到的這套機制了,這時solaris就調用vmem_alloc函數直接從kmem_oversize_arena區域分配所需的內存。 kmem_free函數的功能是釋放未初始化內存塊,它的原理與kmem_alloc差不多,只不過它執行了一個相反的過程。kmem_free函數也是根據內存塊的大小執行不同的釋放操作,如果內存塊的尺寸小于16k,它就調用kmem_cache_free函數釋放內存塊,否則它就直接調用vmem_free函數把內存塊歸還到kmem_oversize_arena區域中去。

總結

以上是生活随笔為你收集整理的转一个solaris虚拟内存管理的wiki的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

久久久精品国产sm最大网站 | 激情内射亚州一区二区三区爱妻 | 99国产精品白浆在线观看免费 | 精品乱码久久久久久久 | 97无码免费人妻超级碰碰夜夜 | 久久99精品国产.久久久久 | 大乳丰满人妻中文字幕日本 | 成人免费视频视频在线观看 免费 | 麻豆av传媒蜜桃天美传媒 | 国产热a欧美热a在线视频 | 大肉大捧一进一出视频出来呀 | 搡女人真爽免费视频大全 | 人人爽人人澡人人人妻 | 97夜夜澡人人双人人人喊 | 狠狠色欧美亚洲狠狠色www | 免费人成网站视频在线观看 | 2020久久香蕉国产线看观看 | 丰满人妻翻云覆雨呻吟视频 | 国产乱人偷精品人妻a片 | 麻豆av传媒蜜桃天美传媒 | 樱花草在线社区www | 国产人成高清在线视频99最全资源 | 无码av岛国片在线播放 | 色综合久久久无码网中文 | 在线观看免费人成视频 | 亚洲精品久久久久久久久久久 | 久久亚洲精品成人无码 | aⅴ亚洲 日韩 色 图网站 播放 | www一区二区www免费 | 老太婆性杂交欧美肥老太 | 亚洲中文字幕久久无码 | 国产午夜手机精彩视频 | 国产精品.xx视频.xxtv | 免费网站看v片在线18禁无码 | 捆绑白丝粉色jk震动捧喷白浆 | 性欧美疯狂xxxxbbbb | 欧美人与禽zoz0性伦交 | 久久精品中文字幕大胸 | 亚洲爆乳精品无码一区二区三区 | 久青草影院在线观看国产 | 中文字幕无线码免费人妻 | 亚洲男人av天堂午夜在 | 夜夜夜高潮夜夜爽夜夜爰爰 | 国产婷婷色一区二区三区在线 | 久久精品中文字幕大胸 | 97精品人妻一区二区三区香蕉 | 久久国产精品_国产精品 | 亚洲日本va中文字幕 | 亚洲日韩精品欧美一区二区 | 丰满护士巨好爽好大乳 | 亚洲国产日韩a在线播放 | 熟妇人妻无码xxx视频 | 国产高潮视频在线观看 | 国产午夜手机精彩视频 | 蜜桃臀无码内射一区二区三区 | 亚洲精品久久久久avwww潮水 | 欧美性猛交内射兽交老熟妇 | 国产激情无码一区二区app | 精品日本一区二区三区在线观看 | 欧美freesex黑人又粗又大 | 亚洲国产高清在线观看视频 | 偷窥日本少妇撒尿chinese | 亚洲精品国产精品乱码视色 | 欧美成人家庭影院 | 一本无码人妻在中文字幕免费 | 亚洲人亚洲人成电影网站色 | 国产卡一卡二卡三 | 最新国产麻豆aⅴ精品无码 | 亚洲成在人网站无码天堂 | 一本大道久久东京热无码av | 精品国偷自产在线视频 | 熟妇人妻中文av无码 | 国产午夜亚洲精品不卡下载 | 正在播放老肥熟妇露脸 | 亚洲日韩av一区二区三区四区 | 99久久精品国产一区二区蜜芽 | 精品国产福利一区二区 | 亚洲色www成人永久网址 | 女高中生第一次破苞av | 无码av免费一区二区三区试看 | 成人aaa片一区国产精品 | 国产精品无码mv在线观看 | 2020久久香蕉国产线看观看 | 国产真人无遮挡作爱免费视频 | av无码不卡在线观看免费 | 国内老熟妇对白xxxxhd | 亚洲精品成a人在线观看 | 日本在线高清不卡免费播放 | 4hu四虎永久在线观看 | 国产精品亚洲а∨无码播放麻豆 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 99久久久国产精品无码免费 | 熟妇人妻中文av无码 | 亚洲伊人久久精品影院 | 久久久久免费看成人影片 | 欧美日韩久久久精品a片 | 中文无码精品a∨在线观看不卡 | 性生交大片免费看女人按摩摩 | 性生交大片免费看女人按摩摩 | 国语精品一区二区三区 | 亚洲色大成网站www | 精品久久久无码人妻字幂 | 国产乱人伦偷精品视频 | 亚洲成a人片在线观看无码3d | 精品国产福利一区二区 | 亚洲毛片av日韩av无码 | 久久综合色之久久综合 | 亚洲欧美精品伊人久久 | 性欧美牲交xxxxx视频 | 欧美日本精品一区二区三区 | 麻豆蜜桃av蜜臀av色欲av | 少妇无码一区二区二三区 | 亚洲精品一区二区三区四区五区 | 伊人久久大香线蕉av一区二区 | 精品久久8x国产免费观看 | 一本大道久久东京热无码av | 欧美性黑人极品hd | 亚洲精品一区二区三区在线观看 | 久久精品国产亚洲精品 | 97资源共享在线视频 | 一本久道高清无码视频 | 久久无码人妻影院 | 四虎国产精品一区二区 | 日韩精品无码免费一区二区三区 | 国产av无码专区亚洲awww | 香蕉久久久久久av成人 | 欧美 亚洲 国产 另类 | 无码播放一区二区三区 | 亚洲国产精品无码一区二区三区 | 天天躁日日躁狠狠躁免费麻豆 | 中文字幕无码免费久久9一区9 | 亚洲aⅴ无码成人网站国产app | 妺妺窝人体色www婷婷 | 丰满妇女强制高潮18xxxx | 国产情侣作爱视频免费观看 | 免费乱码人妻系列无码专区 | √8天堂资源地址中文在线 | 88国产精品欧美一区二区三区 | 欧美精品无码一区二区三区 | 精品少妇爆乳无码av无码专区 | 精品国产成人一区二区三区 | 成人亚洲精品久久久久软件 | 日本饥渴人妻欲求不满 | 1000部啪啪未满十八勿入下载 | 十八禁真人啪啪免费网站 | 男人扒开女人内裤强吻桶进去 | 国产精品18久久久久久麻辣 | 日本饥渴人妻欲求不满 | 国产后入清纯学生妹 | 玩弄人妻少妇500系列视频 | 女人色极品影院 | 性欧美熟妇videofreesex | 中文字幕人妻无码一区二区三区 | 色偷偷人人澡人人爽人人模 | 内射后入在线观看一区 | 久久国产精品二国产精品 | 国产成人综合色在线观看网站 | 亚洲一区二区三区无码久久 | 亚洲精品一区国产 | 国产成人精品三级麻豆 | 国产亚洲精品久久久久久国模美 | 好男人www社区 | 国产精品无码mv在线观看 | 精品国产精品久久一区免费式 | 亚洲va欧美va天堂v国产综合 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 国内揄拍国内精品人妻 | 四虎永久在线精品免费网址 | 亚洲成av人影院在线观看 | 大地资源中文第3页 | 亚洲熟妇色xxxxx欧美老妇y | 亚洲日韩一区二区 | 国产亚洲精品久久久久久久久动漫 | 夜夜夜高潮夜夜爽夜夜爰爰 | 激情内射亚州一区二区三区爱妻 | 久久aⅴ免费观看 | 麻豆人妻少妇精品无码专区 | 精品无码成人片一区二区98 | 在线播放无码字幕亚洲 | 综合激情五月综合激情五月激情1 | 久久婷婷五月综合色国产香蕉 | 精品国产av色一区二区深夜久久 | 图片区 小说区 区 亚洲五月 | 中文字幕av日韩精品一区二区 | 中文字幕无码免费久久9一区9 | 300部国产真实乱 | 人人爽人人爽人人片av亚洲 | 国产亚洲精品精品国产亚洲综合 | 99精品国产综合久久久久五月天 | 久久国内精品自在自线 | 国产性生大片免费观看性 | 永久免费精品精品永久-夜色 | 久久久久99精品国产片 | 成人无码精品1区2区3区免费看 | 99视频精品全部免费免费观看 | 亚洲经典千人经典日产 | 亚洲精品国产a久久久久久 | www一区二区www免费 | 18禁止看的免费污网站 | 人人妻人人澡人人爽欧美一区 | 在线播放免费人成毛片乱码 | 成人综合网亚洲伊人 | 国产精品-区区久久久狼 | 久久久久成人片免费观看蜜芽 | 又大又紧又粉嫩18p少妇 | 无码人妻丰满熟妇区五十路百度 | 亚洲男女内射在线播放 | 一区二区三区高清视频一 | 最新版天堂资源中文官网 | 中文字幕无码av波多野吉衣 | 久久久国产精品无码免费专区 | 人人妻人人澡人人爽欧美精品 | 国产精华av午夜在线观看 | 久久午夜无码鲁丝片秋霞 | 中文字幕乱码中文乱码51精品 | 玩弄少妇高潮ⅹxxxyw | 午夜肉伦伦影院 | 国产免费久久精品国产传媒 | 99精品视频在线观看免费 | 国产精品久久久av久久久 | 人人超人人超碰超国产 | 最近中文2019字幕第二页 | 国产精品人妻一区二区三区四 | 少妇无码av无码专区在线观看 | 精品国产青草久久久久福利 | 天天摸天天碰天天添 | 麻豆国产人妻欲求不满谁演的 | 桃花色综合影院 | 国产人妖乱国产精品人妖 | www国产亚洲精品久久久日本 | 亚洲另类伦春色综合小说 | 老熟女乱子伦 | 少妇高潮一区二区三区99 | 亚洲成av人影院在线观看 | 国产一区二区三区日韩精品 | 亚洲熟妇自偷自拍另类 | 久久久精品成人免费观看 | 久激情内射婷内射蜜桃人妖 | 草草网站影院白丝内射 | 亚洲综合色区中文字幕 | 久久久久99精品国产片 | 亚洲国产精品美女久久久久 | 久久久久久亚洲精品a片成人 | 综合网日日天干夜夜久久 | 亚洲综合另类小说色区 | 久久天天躁狠狠躁夜夜免费观看 | 97无码免费人妻超级碰碰夜夜 | 国产乡下妇女做爰 | 亚洲无人区午夜福利码高清完整版 | 亚洲人成影院在线无码按摩店 | 亚洲精品一区二区三区四区五区 | 亚洲中文字幕乱码av波多ji | 亚洲日韩av一区二区三区中文 | 国产精品美女久久久 | 国产电影无码午夜在线播放 | 亚洲天堂2017无码 | 成熟妇人a片免费看网站 | 三上悠亚人妻中文字幕在线 | 久久天天躁狠狠躁夜夜免费观看 | 亚洲春色在线视频 | 欧洲美熟女乱又伦 | 免费无码的av片在线观看 | 成人一在线视频日韩国产 | 精品夜夜澡人妻无码av蜜桃 | 丝袜足控一区二区三区 | 高潮毛片无遮挡高清免费视频 | 日韩av无码一区二区三区不卡 | 亚洲综合伊人久久大杳蕉 | 麻豆md0077饥渴少妇 | 亚洲精品久久久久avwww潮水 | 亚洲国产精品无码久久久久高潮 | 俄罗斯老熟妇色xxxx | 亚洲色偷偷男人的天堂 | 亚洲中文字幕成人无码 | 精品无人区无码乱码毛片国产 | 麻豆果冻传媒2021精品传媒一区下载 | 亚洲精品久久久久久久久久久 | 国产av一区二区三区最新精品 | 日本熟妇人妻xxxxx人hd | 东京无码熟妇人妻av在线网址 | 亚洲成a人片在线观看无码3d | 麻豆国产丝袜白领秘书在线观看 | 蜜臀av在线播放 久久综合激激的五月天 | 欧美日韩亚洲国产精品 | 亚洲人成网站在线播放942 | 久久综合网欧美色妞网 | 无码中文字幕色专区 | 国产特级毛片aaaaaaa高清 | 亚洲成a人片在线观看日本 | 亚洲成av人综合在线观看 | 特黄特色大片免费播放器图片 | 色婷婷欧美在线播放内射 | 少妇厨房愉情理9仑片视频 | 成人无码视频免费播放 | 欧美日韩一区二区三区自拍 | 无码纯肉视频在线观看 | 亚洲精品午夜无码电影网 | 中文无码精品a∨在线观看不卡 | 久久国产精品萌白酱免费 | 亚洲中文字幕成人无码 | 成人精品视频一区二区 | 少妇厨房愉情理9仑片视频 | 午夜无码人妻av大片色欲 | 激情内射日本一区二区三区 | 乱人伦中文视频在线观看 | 99麻豆久久久国产精品免费 | 国产精品二区一区二区aⅴ污介绍 | 成人无码精品1区2区3区免费看 | 娇妻被黑人粗大高潮白浆 | 亚洲中文字幕成人无码 | 亚洲阿v天堂在线 | 黑人巨大精品欧美一区二区 | 中文字幕日韩精品一区二区三区 | 亚洲熟悉妇女xxx妇女av | 久久久久免费看成人影片 | 欧美自拍另类欧美综合图片区 | 久久国产精品偷任你爽任你 | 国产在热线精品视频 | 无码人妻精品一区二区三区下载 | 国产婷婷色一区二区三区在线 | 日韩av无码一区二区三区不卡 | 一本久久a久久精品vr综合 | 天天爽夜夜爽夜夜爽 | 国产无遮挡又黄又爽又色 | 国产精品人妻一区二区三区四 | 大肉大捧一进一出视频出来呀 | 欧美熟妇另类久久久久久不卡 | 人人妻人人澡人人爽欧美一区 | 天天躁夜夜躁狠狠是什么心态 | 国产成人精品优优av | 午夜理论片yy44880影院 | 樱花草在线播放免费中文 | 装睡被陌生人摸出水好爽 | 又粗又大又硬毛片免费看 | 国产精品人人妻人人爽 | 国产精品亚洲а∨无码播放麻豆 | 99久久婷婷国产综合精品青草免费 | 一本久道久久综合狠狠爱 | 99久久久国产精品无码免费 | 国产精品嫩草久久久久 | 国产性生交xxxxx无码 | 性色av无码免费一区二区三区 | 国产无遮挡又黄又爽又色 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 香港三级日本三级妇三级 | 国产97人人超碰caoprom | 国产成人精品视频ⅴa片软件竹菊 | 日韩精品无码一区二区中文字幕 | 色一情一乱一伦一区二区三欧美 | 在线a亚洲视频播放在线观看 | 色欲综合久久中文字幕网 | 亚洲娇小与黑人巨大交 | 狂野欧美激情性xxxx | 综合激情五月综合激情五月激情1 | 国产乡下妇女做爰 | 国产特级毛片aaaaaa高潮流水 | 亚洲精品午夜无码电影网 | 国产亚洲精品久久久久久国模美 | 国产精品久久久 | 亚洲 另类 在线 欧美 制服 | 露脸叫床粗话东北少妇 | 东京无码熟妇人妻av在线网址 | 中文久久乱码一区二区 | 女高中生第一次破苞av | 亚洲精品国产精品乱码不卡 | 国产熟妇高潮叫床视频播放 | 国产精品va在线播放 | 97无码免费人妻超级碰碰夜夜 | 四虎国产精品一区二区 | 精品国产青草久久久久福利 | 天天做天天爱天天爽综合网 | 在线精品国产一区二区三区 | 欧美黑人乱大交 | √8天堂资源地址中文在线 | 7777奇米四色成人眼影 | 色老头在线一区二区三区 | 麻豆果冻传媒2021精品传媒一区下载 | 久在线观看福利视频 | 男女爱爱好爽视频免费看 | 国产成人一区二区三区在线观看 | 久久精品99久久香蕉国产色戒 | 无码人妻少妇伦在线电影 | 欧美人妻一区二区三区 | 国产绳艺sm调教室论坛 | 亚洲の无码国产の无码步美 | 在线 国产 欧美 亚洲 天堂 | 欧美大屁股xxxxhd黑色 | 国产又爽又黄又刺激的视频 | 精品国产成人一区二区三区 | 欧美三级a做爰在线观看 | 女人高潮内射99精品 | 好男人www社区 | 久久精品人人做人人综合 | 国产亚洲精品久久久久久久久动漫 | 久久国产精品偷任你爽任你 | 精品国产麻豆免费人成网站 | 无码一区二区三区在线观看 | 亚洲va中文字幕无码久久不卡 | 波多野42部无码喷潮在线 | 精品乱码久久久久久久 | 国产精品丝袜黑色高跟鞋 | 国产精品美女久久久久av爽李琼 | 亚洲国产精品成人久久蜜臀 | 国产人妻精品午夜福利免费 | 亚洲精品鲁一鲁一区二区三区 | 免费乱码人妻系列无码专区 | 天堂无码人妻精品一区二区三区 | 精品厕所偷拍各类美女tp嘘嘘 | 欧美激情综合亚洲一二区 | 久久综合狠狠综合久久综合88 | 国产人妻精品一区二区三区不卡 | 扒开双腿疯狂进出爽爽爽视频 | 国产精品高潮呻吟av久久4虎 | 无码纯肉视频在线观看 | 国产精品人人妻人人爽 | 国产精品久久国产精品99 | 丰满少妇女裸体bbw | 日韩在线不卡免费视频一区 | 亚洲精品综合一区二区三区在线 | 人人澡人人透人人爽 | 丰满护士巨好爽好大乳 | 亚洲精品中文字幕久久久久 | 午夜精品久久久久久久久 | 色婷婷香蕉在线一区二区 | 国产成人亚洲综合无码 | 欧美激情一区二区三区成人 | 高清国产亚洲精品自在久久 | 中文字幕人妻无码一区二区三区 | 日欧一片内射va在线影院 | 欧美大屁股xxxxhd黑色 | 亚洲日韩av一区二区三区四区 | 永久黄网站色视频免费直播 | 欧美自拍另类欧美综合图片区 | 国产av一区二区精品久久凹凸 | 国产午夜无码精品免费看 | 久久综合狠狠综合久久综合88 | 欧美三级a做爰在线观看 | 荫蒂被男人添的好舒服爽免费视频 | 天堂一区人妻无码 | 欧美国产亚洲日韩在线二区 | 中文字幕无码视频专区 | 美女极度色诱视频国产 | 久久久久久av无码免费看大片 | 啦啦啦www在线观看免费视频 | 狠狠cao日日穞夜夜穞av | 欧美黑人巨大xxxxx | 高潮毛片无遮挡高清免费视频 | 日本精品人妻无码77777 天堂一区人妻无码 | 一本久道久久综合婷婷五月 | 日韩人妻无码中文字幕视频 | 国色天香社区在线视频 | 18无码粉嫩小泬无套在线观看 | 精品成人av一区二区三区 | 中文久久乱码一区二区 | 三级4级全黄60分钟 | 丰满肥臀大屁股熟妇激情视频 | 日韩亚洲欧美精品综合 | 麻豆成人精品国产免费 | 精品夜夜澡人妻无码av蜜桃 | 九九热爱视频精品 | 久久久精品人妻久久影视 | 亚洲成av人片在线观看无码不卡 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 福利一区二区三区视频在线观看 | 久久久精品欧美一区二区免费 | 男女爱爱好爽视频免费看 | www国产精品内射老师 | 人妻有码中文字幕在线 | av在线亚洲欧洲日产一区二区 | 国产在线精品一区二区高清不卡 | 麻花豆传媒剧国产免费mv在线 | 亚洲精品无码人妻无码 | 乱人伦人妻中文字幕无码久久网 | 国产无遮挡又黄又爽免费视频 | 久久熟妇人妻午夜寂寞影院 | aa片在线观看视频在线播放 | 国产精品久久久久影院嫩草 | 久久亚洲a片com人成 | 午夜精品久久久久久久 | 少妇性l交大片 | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲一区二区观看播放 | 亚洲欧美日韩成人高清在线一区 | 麻豆国产97在线 | 欧洲 | 国产成人亚洲综合无码 | 色情久久久av熟女人妻网站 | 国产手机在线αⅴ片无码观看 | 波多野结衣 黑人 | 精品国产青草久久久久福利 | 亚洲综合无码一区二区三区 | 精品无人国产偷自产在线 | 久久久久成人精品免费播放动漫 | 久久天天躁狠狠躁夜夜免费观看 | 国产熟妇高潮叫床视频播放 | 久久久精品成人免费观看 | 亚洲国产精品久久久天堂 | 国产精品二区一区二区aⅴ污介绍 | 熟妇人妻无码xxx视频 | 国产精品久久久久久久影院 | 东京热一精品无码av | 在教室伦流澡到高潮hnp视频 | 美女扒开屁股让男人桶 | 亚洲成av人影院在线观看 | 日本一区二区三区免费高清 | 日日麻批免费40分钟无码 | 性欧美牲交xxxxx视频 | 任你躁在线精品免费 | 性啪啪chinese东北女人 | 九一九色国产 | yw尤物av无码国产在线观看 | 亚洲自偷自偷在线制服 | 亚洲 a v无 码免 费 成 人 a v | 亚洲精品中文字幕乱码 | 撕开奶罩揉吮奶头视频 | 亚洲人成人无码网www国产 | 亚洲精品成人av在线 | 欧美三级a做爰在线观看 | 久久www免费人成人片 | 亚洲七七久久桃花影院 | 色噜噜亚洲男人的天堂 | 又紧又大又爽精品一区二区 | 亚洲aⅴ无码成人网站国产app | 久久无码人妻影院 | 亚洲精品国产第一综合99久久 | 日本成熟视频免费视频 | 97人妻精品一区二区三区 | 精品久久久无码中文字幕 | 久久亚洲中文字幕无码 | 日本精品少妇一区二区三区 | 丰满人妻被黑人猛烈进入 | 精品无码国产一区二区三区av | 久久久成人毛片无码 | 中文字幕无码免费久久99 | 成年美女黄网站色大免费全看 | 亚洲成av人综合在线观看 | 日韩人妻无码中文字幕视频 | 人妻插b视频一区二区三区 | 亚洲の无码国产の无码步美 | 久久久久久亚洲精品a片成人 | 熟女体下毛毛黑森林 | 精品久久久久久亚洲精品 | 2020久久香蕉国产线看观看 | 亚洲日韩中文字幕在线播放 | a国产一区二区免费入口 | 亚洲熟妇色xxxxx欧美老妇 | 初尝人妻少妇中文字幕 | 日韩欧美中文字幕公布 | 丝袜人妻一区二区三区 | 一本久道久久综合婷婷五月 | 真人与拘做受免费视频一 | 国产精品久久精品三级 | 麻豆精产国品 | 综合激情五月综合激情五月激情1 | 日韩人妻系列无码专区 | 亚洲精品国产精品乱码不卡 | 黑人玩弄人妻中文在线 | 樱花草在线社区www | 久久久精品欧美一区二区免费 | 国产亚洲美女精品久久久2020 | 又大又黄又粗又爽的免费视频 | 高潮毛片无遮挡高清免费 | 波多野结衣av在线观看 | 人人澡人人透人人爽 | 无码一区二区三区在线 | 无套内射视频囯产 | 正在播放东北夫妻内射 | 国产亚洲精品久久久久久国模美 | 5858s亚洲色大成网站www | 国产精品免费大片 | 精品国精品国产自在久国产87 | √天堂中文官网8在线 | 丰满少妇人妻久久久久久 | 乱人伦人妻中文字幕无码久久网 | 无码中文字幕色专区 | 亚洲日韩av一区二区三区四区 | 永久免费精品精品永久-夜色 | 女人被男人躁得好爽免费视频 | 精品国偷自产在线视频 | 99久久婷婷国产综合精品青草免费 | 亚洲国产精品无码久久久久高潮 | 久久99热只有频精品8 | 久久精品99久久香蕉国产色戒 | 中文字幕+乱码+中文字幕一区 | 国产精品18久久久久久麻辣 | 国产人妻大战黑人第1集 | 国产精品手机免费 | 国产热a欧美热a在线视频 | 97se亚洲精品一区 | 日本熟妇乱子伦xxxx | 亚洲国产精品毛片av不卡在线 | 色婷婷综合中文久久一本 | 综合激情五月综合激情五月激情1 | 久久精品99久久香蕉国产色戒 | 欧洲精品码一区二区三区免费看 | 在线精品亚洲一区二区 | 永久免费观看国产裸体美女 | 成人精品视频一区二区三区尤物 | 99久久精品国产一区二区蜜芽 | 精品无码一区二区三区的天堂 | 无码任你躁久久久久久久 | 中文字幕人妻无码一区二区三区 | 精品国产福利一区二区 | 乱中年女人伦av三区 | 日日麻批免费40分钟无码 | 99久久精品国产一区二区蜜芽 | 精品成人av一区二区三区 | 久久国产精品二国产精品 | 免费无码一区二区三区蜜桃大 | 国产香蕉尹人视频在线 | 国产无遮挡吃胸膜奶免费看 | 久在线观看福利视频 | 女人被男人爽到呻吟的视频 | 亚洲精品www久久久 | 亚洲熟妇自偷自拍另类 | 免费国产黄网站在线观看 | 精品人妻av区 | 国语精品一区二区三区 | 成人无码精品1区2区3区免费看 | 97久久国产亚洲精品超碰热 | 国产成人综合美国十次 | 性生交大片免费看l | 亚洲一区二区三区在线观看网站 | 白嫩日本少妇做爰 | 狂野欧美性猛xxxx乱大交 | 红桃av一区二区三区在线无码av | 国内揄拍国内精品人妻 | 国产成人无码一二三区视频 | 精品久久久久久亚洲精品 | 色婷婷欧美在线播放内射 | 午夜性刺激在线视频免费 | 综合网日日天干夜夜久久 | 久9re热视频这里只有精品 | 久久国产精品萌白酱免费 | 高清无码午夜福利视频 | 超碰97人人做人人爱少妇 | 免费国产黄网站在线观看 | 欧美熟妇另类久久久久久多毛 | 国产69精品久久久久app下载 | 久久人人97超碰a片精品 | 亚洲精品成a人在线观看 | 久久久久久国产精品无码下载 | 97久久国产亚洲精品超碰热 | 日本在线高清不卡免费播放 | 人人爽人人爽人人片av亚洲 | 在线播放无码字幕亚洲 | 国产精品成人av在线观看 | 国产香蕉97碰碰久久人人 | 久久99国产综合精品 | 亚洲欧美日韩综合久久久 | 日本精品人妻无码免费大全 | 国产又爽又黄又刺激的视频 | 88国产精品欧美一区二区三区 | 亚洲国产精品无码一区二区三区 | 日本精品人妻无码免费大全 | 狂野欧美性猛交免费视频 | 人妻插b视频一区二区三区 | 精品久久久中文字幕人妻 | 成 人影片 免费观看 | 丝袜人妻一区二区三区 | 人人妻人人澡人人爽欧美精品 | 300部国产真实乱 | 欧美刺激性大交 | 福利一区二区三区视频在线观看 | 日韩少妇白浆无码系列 | 欧美老妇交乱视频在线观看 | 亚洲天堂2017无码中文 | 男人和女人高潮免费网站 | 99久久久国产精品无码免费 | 国产精品无码一区二区三区不卡 | 99久久人妻精品免费二区 | 中文字幕av伊人av无码av | 国产精品亚洲专区无码不卡 | 国产色在线 | 国产 | 性欧美熟妇videofreesex | av无码不卡在线观看免费 | 四虎4hu永久免费 | 一个人看的www免费视频在线观看 | 免费人成网站视频在线观看 | 性生交大片免费看女人按摩摩 | 精品午夜福利在线观看 | 色婷婷久久一区二区三区麻豆 | 中文字幕乱码中文乱码51精品 | 奇米影视888欧美在线观看 | 欧美日韩综合一区二区三区 | 欧美色就是色 | 领导边摸边吃奶边做爽在线观看 | 中文精品无码中文字幕无码专区 | 正在播放老肥熟妇露脸 | 中国女人内谢69xxxxxa片 | 欧美日韩在线亚洲综合国产人 | 青青草原综合久久大伊人精品 | 一本色道久久综合亚洲精品不卡 | 亚洲天堂2017无码 | 狂野欧美性猛交免费视频 | 国产香蕉尹人视频在线 | 在线欧美精品一区二区三区 | 国产午夜精品一区二区三区嫩草 | 丝袜 中出 制服 人妻 美腿 | 内射老妇bbwx0c0ck | 国产真人无遮挡作爱免费视频 | 99久久久无码国产aaa精品 | 欧美怡红院免费全部视频 | 日本成熟视频免费视频 | 水蜜桃色314在线观看 | 中文字幕+乱码+中文字幕一区 | 色婷婷久久一区二区三区麻豆 | 动漫av一区二区在线观看 | 黑人巨大精品欧美一区二区 | 激情五月综合色婷婷一区二区 | 蜜桃av抽搐高潮一区二区 | 人妻少妇被猛烈进入中文字幕 | 波多野结衣av一区二区全免费观看 | 女人被爽到呻吟gif动态图视看 | 四十如虎的丰满熟妇啪啪 | 麻豆国产97在线 | 欧洲 | 亚洲一区av无码专区在线观看 | 午夜丰满少妇性开放视频 | 清纯唯美经典一区二区 | 人人澡人人妻人人爽人人蜜桃 | 国产激情无码一区二区 | 色欲久久久天天天综合网精品 | 亚洲精品久久久久久久久久久 | 97人妻精品一区二区三区 | 日韩少妇内射免费播放 | 免费无码一区二区三区蜜桃大 | 亚洲自偷自偷在线制服 | 精品欧洲av无码一区二区三区 | 久久99精品久久久久久动态图 | 午夜福利一区二区三区在线观看 | 少妇厨房愉情理9仑片视频 | 日韩av无码中文无码电影 | 青青青手机频在线观看 | 精品一二三区久久aaa片 | 亚洲精品一区二区三区在线观看 | 国产精品永久免费视频 | 亚洲精品一区二区三区在线 | 67194成是人免费无码 | 无码人妻av免费一区二区三区 | 一区二区传媒有限公司 | 动漫av网站免费观看 | 国产精品二区一区二区aⅴ污介绍 | 牛和人交xxxx欧美 | 强开小婷嫩苞又嫩又紧视频 | 色一情一乱一伦一区二区三欧美 | 国产特级毛片aaaaaaa高清 | 国产精品视频免费播放 | 欧美老熟妇乱xxxxx | 成人性做爰aaa片免费看不忠 | 丰满护士巨好爽好大乳 | 亚洲国产精品无码久久久久高潮 | 日韩精品无码免费一区二区三区 | 5858s亚洲色大成网站www | 人妻有码中文字幕在线 | 日韩人妻无码中文字幕视频 | 亚洲一区二区三区 | 日日摸夜夜摸狠狠摸婷婷 | 无码人妻丰满熟妇区五十路百度 | 婷婷五月综合缴情在线视频 | 黑人玩弄人妻中文在线 | 国产另类ts人妖一区二区 | 国产精品亚洲五月天高清 | 夫妻免费无码v看片 | 成人欧美一区二区三区黑人 | 欧美国产亚洲日韩在线二区 | 青青久在线视频免费观看 | 少妇高潮喷潮久久久影院 | 日韩无码专区 | 一本一道久久综合久久 | 国产精品无套呻吟在线 | 国产性生大片免费观看性 | 无码精品人妻一区二区三区av | 东北女人啪啪对白 | www成人国产高清内射 | 未满小14洗澡无码视频网站 | 国产小呦泬泬99精品 | 又黄又爽又色的视频 | 久久午夜无码鲁丝片午夜精品 | 国产凸凹视频一区二区 | 国产午夜视频在线观看 | 色婷婷综合中文久久一本 | 亚洲国产精华液网站w | 成人欧美一区二区三区 | 131美女爱做视频 | 88国产精品欧美一区二区三区 | 亚洲理论电影在线观看 | 玩弄中年熟妇正在播放 | 国产精品亚洲а∨无码播放麻豆 | 国产乱子伦视频在线播放 | 人妻少妇被猛烈进入中文字幕 | 亚洲综合精品香蕉久久网 | 欧美激情一区二区三区成人 | 亚洲人成网站色7799 | 久久视频在线观看精品 | 国产人妻大战黑人第1集 | 熟妇人妻激情偷爽文 | 十八禁视频网站在线观看 | 麻花豆传媒剧国产免费mv在线 | 精品国产一区二区三区四区 | 三级4级全黄60分钟 | 久久国产劲爆∧v内射 | 欧美zoozzooz性欧美 | 亚洲精品鲁一鲁一区二区三区 | 久久精品中文字幕大胸 | 午夜丰满少妇性开放视频 | 无码午夜成人1000部免费视频 | 风流少妇按摩来高潮 | 大屁股大乳丰满人妻 | 亚洲成av人综合在线观看 | 亚洲精品一区二区三区在线观看 | 亚洲伊人久久精品影院 | 狂野欧美激情性xxxx | 亚洲成在人网站无码天堂 | 亚洲最大成人网站 | 无码人妻精品一区二区三区不卡 | 亚洲成在人网站无码天堂 | a在线观看免费网站大全 | 亚洲国产高清在线观看视频 | 水蜜桃亚洲一二三四在线 | 国产婷婷色一区二区三区在线 | 午夜福利不卡在线视频 | 无套内谢老熟女 | 2020久久香蕉国产线看观看 | 牛和人交xxxx欧美 | 日韩人妻无码中文字幕视频 | 国产极品美女高潮无套在线观看 | 欧美丰满老熟妇xxxxx性 | 久久人人爽人人人人片 | 欧美午夜特黄aaaaaa片 | 丝袜 中出 制服 人妻 美腿 | 自拍偷自拍亚洲精品10p | 色综合视频一区二区三区 | 久久久中文久久久无码 | 曰韩无码二三区中文字幕 | 特黄特色大片免费播放器图片 | 在线a亚洲视频播放在线观看 | 亚洲va中文字幕无码久久不卡 | 亚洲一区二区三区偷拍女厕 | 一本久道久久综合狠狠爱 | 无码人中文字幕 | 无码帝国www无码专区色综合 | 麻豆av传媒蜜桃天美传媒 | 国产人妻精品一区二区三区不卡 | 亚洲爆乳大丰满无码专区 | 精品一区二区不卡无码av | 久久99精品久久久久久动态图 | 亚洲熟女一区二区三区 | 日本xxxx色视频在线观看免费 | 亚洲自偷自偷在线制服 | 国产精品亚洲一区二区三区喷水 | 亚洲第一无码av无码专区 | 伊人久久大香线蕉av一区二区 | 欧美阿v高清资源不卡在线播放 | 99久久精品无码一区二区毛片 | 亚洲国产综合无码一区 | 免费中文字幕日韩欧美 | 中文字幕乱码中文乱码51精品 | 无码av最新清无码专区吞精 | 高中生自慰www网站 | 最近中文2019字幕第二页 | 偷窥日本少妇撒尿chinese | 熟妇人妻无码xxx视频 | 国产精品igao视频网 | 日韩精品a片一区二区三区妖精 | 亚洲成在人网站无码天堂 | 丁香啪啪综合成人亚洲 | 日本一卡2卡3卡四卡精品网站 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 少妇人妻av毛片在线看 | 国产无套内射久久久国产 | 小鲜肉自慰网站xnxx | 亚洲精品久久久久中文第一幕 | 亲嘴扒胸摸屁股激烈网站 | 欧美激情综合亚洲一二区 | 国产亚洲精品久久久久久大师 | 国产内射爽爽大片视频社区在线 | 色一情一乱一伦 | 欧美xxxxx精品 | 国产午夜福利100集发布 | 秋霞成人午夜鲁丝一区二区三区 | 成人试看120秒体验区 | 少妇一晚三次一区二区三区 | 欧美成人午夜精品久久久 | 在线观看国产午夜福利片 | 久久精品成人欧美大片 | 美女毛片一区二区三区四区 | 日本xxxx色视频在线观看免费 | 日本大香伊一区二区三区 | 亚洲中文字幕乱码av波多ji | 久久综合久久自在自线精品自 | 极品嫩模高潮叫床 | 啦啦啦www在线观看免费视频 | 国产香蕉尹人视频在线 | √8天堂资源地址中文在线 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产精品嫩草久久久久 | 中文字幕无码日韩欧毛 | 四虎国产精品免费久久 | 狠狠色欧美亚洲狠狠色www | 俺去俺来也www色官网 | 伊人久久大香线蕉亚洲 | 麻豆国产人妻欲求不满谁演的 | 2019nv天堂香蕉在线观看 | 欧洲美熟女乱又伦 | 久久天天躁夜夜躁狠狠 | 奇米影视888欧美在线观看 | 亚洲日韩中文字幕在线播放 | 久久成人a毛片免费观看网站 | 欧美成人家庭影院 | 天天摸天天碰天天添 | 爆乳一区二区三区无码 | 亚洲色www成人永久网址 | 97久久精品无码一区二区 | 熟女俱乐部五十路六十路av | 亚洲自偷自拍另类第1页 | 曰韩无码二三区中文字幕 | 久久精品无码一区二区三区 | 图片区 小说区 区 亚洲五月 | 欧美三级a做爰在线观看 | 一本无码人妻在中文字幕免费 | 啦啦啦www在线观看免费视频 | 美女扒开屁股让男人桶 | 久久久无码中文字幕久... | 日本精品人妻无码免费大全 | 国产乱人无码伦av在线a | 丝袜足控一区二区三区 | 日韩精品一区二区av在线 | 综合人妻久久一区二区精品 | 奇米影视7777久久精品 | 久久人人97超碰a片精品 | 国产精品无码永久免费888 | 久久五月精品中文字幕 | 天天躁日日躁狠狠躁免费麻豆 | 欧美 亚洲 国产 另类 | 国内精品一区二区三区不卡 | 国产xxx69麻豆国语对白 | 理论片87福利理论电影 | 中文字幕av无码一区二区三区电影 | 国产免费久久精品国产传媒 | 一本大道伊人av久久综合 | 亚洲s码欧洲m码国产av | 国产做国产爱免费视频 | 成人欧美一区二区三区黑人 | 欧美刺激性大交 | 永久免费精品精品永久-夜色 | 97人妻精品一区二区三区 | 国产人妻精品午夜福利免费 | 一本加勒比波多野结衣 | 久久人人爽人人爽人人片ⅴ | 久久久久av无码免费网 | 亚洲精品国产精品乱码不卡 | 日本xxxx色视频在线观看免费 | 又大又紧又粉嫩18p少妇 | 国产一精品一av一免费 | 无码吃奶揉捏奶头高潮视频 | 永久免费观看国产裸体美女 | 色狠狠av一区二区三区 | 欧美丰满熟妇xxxx性ppx人交 | 中文字幕日韩精品一区二区三区 | 精品国产麻豆免费人成网站 | 精品国产av色一区二区深夜久久 | 99久久婷婷国产综合精品青草免费 | 少女韩国电视剧在线观看完整 | 国产精品资源一区二区 | 高清国产亚洲精品自在久久 | 亚洲乱码日产精品bd | 欧美第一黄网免费网站 | 东京热男人av天堂 | 伊人久久大香线蕉av一区二区 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 人妻天天爽夜夜爽一区二区 | 九九在线中文字幕无码 | 无码人妻少妇伦在线电影 | 精品乱码久久久久久久 | 日本一区二区三区免费播放 | 日本一卡二卡不卡视频查询 | 亚洲乱码中文字幕在线 | 人妻互换免费中文字幕 | 国产精品亚洲lv粉色 | 日日天日日夜日日摸 | 久久久久久久人妻无码中文字幕爆 | 午夜精品久久久久久久 | 国产成人无码av一区二区 | 久久成人a毛片免费观看网站 | 精品无码国产自产拍在线观看蜜 | 性做久久久久久久免费看 | 欧美精品在线观看 | 国产激情综合五月久久 | 国产精品亚洲综合色区韩国 | 综合人妻久久一区二区精品 | 中文字幕无线码 | 又紧又大又爽精品一区二区 | 又湿又紧又大又爽a视频国产 | 动漫av网站免费观看 | 一个人看的www免费视频在线观看 | www一区二区www免费 | 欧美乱妇无乱码大黄a片 | 国产精品igao视频网 | 少妇性荡欲午夜性开放视频剧场 | 精品无人区无码乱码毛片国产 | 在线观看免费人成视频 | 国産精品久久久久久久 | 亚洲人成无码网www | 久激情内射婷内射蜜桃人妖 | 国产午夜福利100集发布 | 国产偷自视频区视频 | 一本一道久久综合久久 | 日产精品高潮呻吟av久久 | 国内揄拍国内精品人妻 | 女高中生第一次破苞av | 狠狠色噜噜狠狠狠狠7777米奇 | 九九久久精品国产免费看小说 | 久久久中文字幕日本无吗 | 日产国产精品亚洲系列 | 中文字幕人妻无码一夲道 | 精品无码av一区二区三区 | 久久久久免费精品国产 | 国产超级va在线观看视频 | 日本精品少妇一区二区三区 | 久久99国产综合精品 | 亚洲理论电影在线观看 | 99久久精品无码一区二区毛片 | 曰韩少妇内射免费播放 | 国产极品美女高潮无套在线观看 | 蜜臀aⅴ国产精品久久久国产老师 | 色欲av亚洲一区无码少妇 | 女人被男人躁得好爽免费视频 | 国产成人久久精品流白浆 | 黄网在线观看免费网站 | 国产美女极度色诱视频www | 国产免费久久精品国产传媒 | 波多野结衣 黑人 | 大地资源中文第3页 | 国产福利视频一区二区 | 欧美日韩一区二区三区自拍 | 日韩av激情在线观看 | 狠狠cao日日穞夜夜穞av | 嫩b人妻精品一区二区三区 | 亚洲小说图区综合在线 | 在线播放亚洲第一字幕 | 国产精品美女久久久网av | www国产精品内射老师 | 亚洲成av人影院在线观看 | 久久精品丝袜高跟鞋 | 亚洲日韩av片在线观看 | 日本精品久久久久中文字幕 | 日日躁夜夜躁狠狠躁 | 亚洲中文字幕无码中文字在线 | 亚洲中文字幕无码一久久区 | 成人无码精品1区2区3区免费看 | 久久97精品久久久久久久不卡 | 最新版天堂资源中文官网 | 国产亚洲精品久久久久久国模美 | 99精品国产综合久久久久五月天 | 亚洲国产精品无码久久久久高潮 | 网友自拍区视频精品 | 1000部夫妻午夜免费 | 国产av人人夜夜澡人人爽麻豆 | 欧美性色19p | ass日本丰满熟妇pics | 曰韩少妇内射免费播放 | 国产又粗又硬又大爽黄老大爷视 | 小sao货水好多真紧h无码视频 | 国内精品人妻无码久久久影院 | 日本一本二本三区免费 | 一二三四社区在线中文视频 | 中文精品久久久久人妻不卡 | 国产成人综合在线女婷五月99播放 | 亚洲国产av精品一区二区蜜芽 | 久青草影院在线观看国产 | 久久久国产一区二区三区 | 国产高清不卡无码视频 | 成人女人看片免费视频放人 | 在线观看免费人成视频 | 久久99国产综合精品 | 国产一精品一av一免费 | 精品亚洲成av人在线观看 | 麻豆国产丝袜白领秘书在线观看 | 激情五月综合色婷婷一区二区 | 四虎4hu永久免费 | 99久久婷婷国产综合精品青草免费 | 久久www免费人成人片 | 扒开双腿吃奶呻吟做受视频 | 影音先锋中文字幕无码 | 中文字幕无线码 | 久久99国产综合精品 | 亚洲午夜福利在线观看 | 精品日本一区二区三区在线观看 | 熟女少妇人妻中文字幕 | 兔费看少妇性l交大片免费 | 久久精品国产日本波多野结衣 | 国产亚洲日韩欧美另类第八页 | 中文精品无码中文字幕无码专区 | 日韩av激情在线观看 | 任你躁在线精品免费 | 国产亚洲精品久久久ai换 | 国产精品18久久久久久麻辣 | 性生交大片免费看l | 麻豆人妻少妇精品无码专区 | 日本又色又爽又黄的a片18禁 | 天天拍夜夜添久久精品大 | 狠狠噜狠狠狠狠丁香五月 | 亚洲色www成人永久网址 | 国产欧美精品一区二区三区 | 色婷婷综合激情综在线播放 | 国产亚洲精品久久久闺蜜 | 精品国产福利一区二区 | 欧美日本日韩 | 亚洲国产av美女网站 | 丰满人妻被黑人猛烈进入 | 国精品人妻无码一区二区三区蜜柚 | 在线精品亚洲一区二区 | 任你躁国产自任一区二区三区 | 麻豆果冻传媒2021精品传媒一区下载 | 无码av中文字幕免费放 | 人妻少妇精品无码专区二区 | 国产在线aaa片一区二区99 | v一区无码内射国产 | 亚洲精品一区二区三区大桥未久 | 欧美性色19p | 无码一区二区三区在线观看 | 少妇太爽了在线观看 | 日本饥渴人妻欲求不满 | 人妻无码αv中文字幕久久琪琪布 | 国产性生大片免费观看性 | 一个人免费观看的www视频 | 国精品人妻无码一区二区三区蜜柚 | 最新国产麻豆aⅴ精品无码 | 午夜精品久久久久久久 | 成 人 网 站国产免费观看 | 亚洲日韩乱码中文无码蜜桃臀网站 | 国产亚av手机在线观看 | 婷婷六月久久综合丁香 | 免费无码一区二区三区蜜桃大 | 久久久久久久久蜜桃 | 在线观看国产一区二区三区 | 久久久久亚洲精品男人的天堂 | 亚洲国产精品久久久久久 | 精品日本一区二区三区在线观看 | 无码一区二区三区在线观看 | 国产成人无码午夜视频在线观看 | 国产成人无码午夜视频在线观看 | 欧美三级a做爰在线观看 | 久久熟妇人妻午夜寂寞影院 | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲欧美精品伊人久久 | 曰韩无码二三区中文字幕 | 超碰97人人做人人爱少妇 | 色老头在线一区二区三区 | 欧美35页视频在线观看 | 久久国产自偷自偷免费一区调 | 人妻夜夜爽天天爽三区 | 亚洲色偷偷偷综合网 | 国产麻豆精品一区二区三区v视界 | 国产精品人人妻人人爽 | 黑人大群体交免费视频 | 午夜不卡av免费 一本久久a久久精品vr综合 | 无码国产色欲xxxxx视频 | 久久久久99精品国产片 | 88国产精品欧美一区二区三区 | 亚洲国产精品久久久天堂 | 久久久久成人片免费观看蜜芽 | 亚洲人成无码网www | 久久伊人色av天堂九九小黄鸭 | 国产成人无码区免费内射一片色欲 | 国产成人综合色在线观看网站 | 领导边摸边吃奶边做爽在线观看 | 久久伊人色av天堂九九小黄鸭 | 国产人成高清在线视频99最全资源 | 国内丰满熟女出轨videos | 日韩精品无码免费一区二区三区 | 天堂亚洲2017在线观看 | 亚洲一区二区三区国产精华液 | 国产在线aaa片一区二区99 | 国产另类ts人妖一区二区 | 国产美女极度色诱视频www | 在线成人www免费观看视频 | 奇米影视888欧美在线观看 | 成人无码影片精品久久久 | 欧美肥老太牲交大战 | 无码精品国产va在线观看dvd | 久久亚洲精品成人无码 | 九九在线中文字幕无码 | 欧美日韩一区二区免费视频 | 蜜臀av在线观看 在线欧美精品一区二区三区 | а√资源新版在线天堂 | 亚洲一区二区三区偷拍女厕 | 色婷婷欧美在线播放内射 | 精品国偷自产在线 | 国产成人综合在线女婷五月99播放 | 在线看片无码永久免费视频 | 欧美日韩一区二区三区自拍 | 玩弄少妇高潮ⅹxxxyw | 久久精品国产精品国产精品污 | 在线播放免费人成毛片乱码 | 国产精品久久久久久亚洲影视内衣 | 少妇人妻大乳在线视频 | 欧美 日韩 人妻 高清 中文 | 在线a亚洲视频播放在线观看 | 免费人成在线视频无码 | 亚洲欧洲日本无在线码 | 国产激情一区二区三区 | 全黄性性激高免费视频 | 超碰97人人做人人爱少妇 | 曰韩少妇内射免费播放 | 伊人久久大香线焦av综合影院 | 国产精品久久久久久亚洲毛片 | 亚洲 另类 在线 欧美 制服 | 欧美日本免费一区二区三区 | 一本久久伊人热热精品中文字幕 | 国产艳妇av在线观看果冻传媒 | 久久亚洲精品中文字幕无男同 | 秋霞成人午夜鲁丝一区二区三区 | 亚洲国产成人av在线观看 | 水蜜桃亚洲一二三四在线 | 久久97精品久久久久久久不卡 | 久久精品女人的天堂av | 一本久道久久综合婷婷五月 | 1000部啪啪未满十八勿入下载 | 亚洲一区二区三区 | 美女极度色诱视频国产 | 丰满肥臀大屁股熟妇激情视频 | 欧洲vodafone精品性 | 精品无码国产自产拍在线观看蜜 | 国产人妻精品一区二区三区 | 无码人妻出轨黑人中文字幕 | 国产精品99爱免费视频 | 久久99国产综合精品 | 55夜色66夜色国产精品视频 | 午夜熟女插插xx免费视频 | 国产精品久久久午夜夜伦鲁鲁 | 亚洲精品久久久久avwww潮水 | 亚洲狠狠婷婷综合久久 | 国产午夜无码视频在线观看 | 午夜不卡av免费 一本久久a久久精品vr综合 | 精品亚洲成av人在线观看 | 欧美zoozzooz性欧美 | 久久久久久久女国产乱让韩 | 亚洲区欧美区综合区自拍区 | 婷婷六月久久综合丁香 | 久久国产精品萌白酱免费 | 无码吃奶揉捏奶头高潮视频 | 久久久久久久久888 | 欧美日韩久久久精品a片 | 亚洲a无码综合a国产av中文 | 好爽又高潮了毛片免费下载 | 久久综合激激的五月天 | 亚洲国产欧美国产综合一区 | 亚洲人成影院在线观看 | 99视频精品全部免费免费观看 | 成 人 网 站国产免费观看 | 国产av无码专区亚洲awww | 无码av最新清无码专区吞精 | 四十如虎的丰满熟妇啪啪 | 国产亚洲美女精品久久久2020 | 99久久99久久免费精品蜜桃 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 久久国产精品萌白酱免费 | 无码精品国产va在线观看dvd | 国产精品对白交换视频 | 青草青草久热国产精品 | 欧美日韩综合一区二区三区 | 亚洲人成影院在线观看 | 天堂一区人妻无码 | 中文字幕无码日韩专区 | 无码人妻少妇伦在线电影 | 国产熟妇另类久久久久 | 夜夜躁日日躁狠狠久久av | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 性开放的女人aaa片 | 亚洲天堂2017无码中文 | 亚洲国产精品一区二区第一页 | 老司机亚洲精品影院 | 无套内射视频囯产 | 国产亚洲精品久久久久久久久动漫 | 精品国产麻豆免费人成网站 | 少妇厨房愉情理9仑片视频 | 在线观看免费人成视频 | 黑人巨大精品欧美一区二区 | 亚洲国产成人av在线观看 | 精品少妇爆乳无码av无码专区 | 国产绳艺sm调教室论坛 | av无码电影一区二区三区 | 亚拍精品一区二区三区探花 | 无码吃奶揉捏奶头高潮视频 | 伊人色综合久久天天小片 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 国产性生交xxxxx无码 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 日韩人妻系列无码专区 | 精品少妇爆乳无码av无码专区 | 欧洲熟妇色 欧美 | 国产乱人偷精品人妻a片 | 亲嘴扒胸摸屁股激烈网站 | 欧美性猛交xxxx富婆 | 亚洲国产欧美日韩精品一区二区三区 | 成人aaa片一区国产精品 | 中文字幕无码视频专区 | 色五月五月丁香亚洲综合网 | 人妻体内射精一区二区三四 | 欧美午夜特黄aaaaaa片 | 亚洲欧美日韩成人高清在线一区 | 精品一区二区三区无码免费视频 | 无码人妻丰满熟妇区毛片18 | 久久精品国产99久久6动漫 | 香蕉久久久久久av成人 | 青青草原综合久久大伊人精品 | 99久久精品午夜一区二区 | 国产性生大片免费观看性 | 国产精品a成v人在线播放 | 麻豆蜜桃av蜜臀av色欲av | 色婷婷香蕉在线一区二区 | 精品一区二区不卡无码av | 又湿又紧又大又爽a视频国产 | 又大又硬又黄的免费视频 | 精品无人区无码乱码毛片国产 | 久久99精品久久久久婷婷 | 人妻无码αv中文字幕久久琪琪布 | 中文字幕日韩精品一区二区三区 | 成人无码精品1区2区3区免费看 | 国产另类ts人妖一区二区 | 中文无码精品a∨在线观看不卡 | 亚洲精品中文字幕久久久久 | 亚洲最大成人网站 | 久久久www成人免费毛片 | 老熟妇乱子伦牲交视频 | 国产亚洲美女精品久久久2020 | 亚洲国产精品成人久久蜜臀 | 成 人影片 免费观看 | 自拍偷自拍亚洲精品10p | 国产在线无码精品电影网 | 国产乱人偷精品人妻a片 | 狂野欧美激情性xxxx | 亚洲国产精品毛片av不卡在线 | 97se亚洲精品一区 | 永久免费观看美女裸体的网站 | 国内老熟妇对白xxxxhd | 国产麻豆精品一区二区三区v视界 | 日本免费一区二区三区最新 | 55夜色66夜色国产精品视频 | 麻花豆传媒剧国产免费mv在线 | 亚洲精品国产精品乱码视色 | 精品人人妻人人澡人人爽人人 | 成人综合网亚洲伊人 | 亚洲 高清 成人 动漫 | 国产精品亚洲lv粉色 | 99精品无人区乱码1区2区3区 | 久久国产自偷自偷免费一区调 | 真人与拘做受免费视频一 | 少妇的肉体aa片免费 | 麻豆蜜桃av蜜臀av色欲av | 亚洲日韩av一区二区三区中文 | 亚洲国产综合无码一区 | 国产精品亚洲综合色区韩国 | 亚洲va欧美va天堂v国产综合 | 色一情一乱一伦一视频免费看 | 亚洲国产一区二区三区在线观看 | 国产色xx群视频射精 | 在教室伦流澡到高潮hnp视频 | 久久无码专区国产精品s | 无码午夜成人1000部免费视频 | 久久zyz资源站无码中文动漫 | 亚洲精品国偷拍自产在线观看蜜桃 | 99视频精品全部免费免费观看 | 国产精品久久福利网站 | 男人的天堂2018无码 | 无码一区二区三区在线 | 国产人妻久久精品二区三区老狼 | 在线天堂新版最新版在线8 | 又粗又大又硬毛片免费看 | 亚洲精品欧美二区三区中文字幕 | 国产精品久久久 | 领导边摸边吃奶边做爽在线观看 | 午夜精品久久久内射近拍高清 | 国产精品无码一区二区桃花视频 | 国产激情一区二区三区 | 天堂а√在线地址中文在线 | 少妇高潮喷潮久久久影院 | 久久久久免费精品国产 | av无码电影一区二区三区 | av香港经典三级级 在线 | 67194成是人免费无码 | 少妇愉情理伦片bd | 欧美xxxx黑人又粗又长 | 国产无av码在线观看 | 无码人妻丰满熟妇区毛片18 | 欧美自拍另类欧美综合图片区 | 人妻体内射精一区二区三四 | 国产精品久久久久影院嫩草 | 午夜时刻免费入口 | 国产后入清纯学生妹 | 精品国产福利一区二区 | 一个人看的www免费视频在线观看 | 国产精品久久国产精品99 | 精品国产aⅴ无码一区二区 | 国产高清av在线播放 | 欧美国产日韩亚洲中文 | 日本在线高清不卡免费播放 | 丰满人妻翻云覆雨呻吟视频 | 亚洲色欲色欲欲www在线 | 日日碰狠狠躁久久躁蜜桃 | 伊人久久大香线蕉午夜 | 国产成人无码av片在线观看不卡 | 乱码午夜-极国产极内射 | 国产性生大片免费观看性 | 亚洲精品无码人妻无码 | 麻豆国产97在线 | 欧洲 | 色欲人妻aaaaaaa无码 | 人妻无码久久精品人妻 | 日韩成人一区二区三区在线观看 | 日韩无码专区 | 国产一区二区不卡老阿姨 | 亚洲伊人久久精品影院 | 国产精品久久久午夜夜伦鲁鲁 | 88国产精品欧美一区二区三区 | ass日本丰满熟妇pics | 香蕉久久久久久av成人 | 无人区乱码一区二区三区 | 丰满人妻一区二区三区免费视频 | 久久成人a毛片免费观看网站 | 欧美熟妇另类久久久久久多毛 | av无码电影一区二区三区 | 丁香花在线影院观看在线播放 | 狠狠综合久久久久综合网 | 国产在热线精品视频 | 亚洲人成影院在线观看 | 午夜福利一区二区三区在线观看 | 无码人妻精品一区二区三区下载 | 狠狠躁日日躁夜夜躁2020 | 国产精品欧美成人 | 天天躁日日躁狠狠躁免费麻豆 | 成人片黄网站色大片免费观看 | 久久久久av无码免费网 | 久久久精品456亚洲影院 | 夜夜高潮次次欢爽av女 | 久久午夜无码鲁丝片 | 国产超碰人人爽人人做人人添 | 日产精品99久久久久久 | 久久久av男人的天堂 | 97夜夜澡人人爽人人喊中国片 | 亚洲自偷自偷在线制服 | 成人免费视频视频在线观看 免费 | 久久国内精品自在自线 | 国产精品香蕉在线观看 | 日韩精品无码免费一区二区三区 | 中文字幕无码av激情不卡 | 毛片内射-百度 | 国产成人综合美国十次 | 免费无码一区二区三区蜜桃大 | 亚洲色欲色欲天天天www | 蜜臀av在线播放 久久综合激激的五月天 | 国产无av码在线观看 | 免费乱码人妻系列无码专区 | 欧美老人巨大xxxx做受 | 俺去俺来也www色官网 | 男女超爽视频免费播放 | 国产精品无码一区二区桃花视频 | 久青草影院在线观看国产 | 成人无码视频在线观看网站 | 国产精品无码久久av | 人妻aⅴ无码一区二区三区 | 国产美女精品一区二区三区 | 无码国产乱人伦偷精品视频 | 欧美日本免费一区二区三区 | 国产精品久久久久久亚洲影视内衣 | 麻豆国产丝袜白领秘书在线观看 | 精品一区二区三区波多野结衣 | 国产香蕉尹人综合在线观看 | 亚洲日本va中文字幕 | 亚洲娇小与黑人巨大交 | 亚洲欧美日韩国产精品一区二区 | 丝袜人妻一区二区三区 | 久久精品国产99精品亚洲 | 成人欧美一区二区三区黑人 | 欧美猛少妇色xxxxx | 丰满肥臀大屁股熟妇激情视频 | 亚洲色成人中文字幕网站 | 色噜噜亚洲男人的天堂 | 最近的中文字幕在线看视频 | 西西人体www44rt大胆高清 | 日韩少妇白浆无码系列 | 少妇无码吹潮 | 一区二区三区乱码在线 | 欧洲 | 国产精品国产三级国产专播 | 四虎影视成人永久免费观看视频 | 99视频精品全部免费免费观看 | 国产网红无码精品视频 | 97夜夜澡人人爽人人喊中国片 | 亚洲自偷自拍另类第1页 | 樱花草在线播放免费中文 | 国产真实夫妇视频 | 欧美国产亚洲日韩在线二区 | 1000部夫妻午夜免费 | 亚洲狠狠婷婷综合久久 | 国产午夜精品一区二区三区嫩草 | 激情人妻另类人妻伦 | 成人亚洲精品久久久久软件 | 小sao货水好多真紧h无码视频 | 国产成人av免费观看 | 国产精品久久久久9999小说 | 精品熟女少妇av免费观看 | 欧美日韩精品 | 黑人玩弄人妻中文在线 | 国产精品99久久精品爆乳 | 精品无码一区二区三区爱欲 | 一区二区三区乱码在线 | 欧洲 | 天堂亚洲免费视频 | 精品国产青草久久久久福利 | 中文字幕无码av波多野吉衣 | 99久久精品无码一区二区毛片 | 国产成人无码av片在线观看不卡 | www一区二区www免费 | 成人欧美一区二区三区 | 精品少妇爆乳无码av无码专区 | 亚洲国产一区二区三区在线观看 | av人摸人人人澡人人超碰下载 | 美女极度色诱视频国产 | 男女超爽视频免费播放 | 国产人妻精品一区二区三区 | 377p欧洲日本亚洲大胆 | 日日躁夜夜躁狠狠躁 | 丁香花在线影院观看在线播放 | 无码人妻精品一区二区三区下载 | 久久99精品久久久久久 | 精品无码国产一区二区三区av | 中文字幕av无码一区二区三区电影 | 一本色道婷婷久久欧美 | 内射老妇bbwx0c0ck | 激情爆乳一区二区三区 | 欧美人与物videos另类 | 亚洲日韩av一区二区三区四区 | 国产精品久久久久无码av色戒 | 女人和拘做爰正片视频 | 午夜福利一区二区三区在线观看 | 亚洲国产欧美日韩精品一区二区三区 | 激情亚洲一区国产精品 | 国产av一区二区三区最新精品 | 99re在线播放 | 丰满肥臀大屁股熟妇激情视频 | 夜精品a片一区二区三区无码白浆 | 亚洲码国产精品高潮在线 | 一本久道久久综合婷婷五月 | 久久国产精品_国产精品 | 成人无码视频免费播放 | 一个人看的视频www在线 | 九九在线中文字幕无码 | 在线天堂新版最新版在线8 | 美女张开腿让人桶 | 亚洲日韩av一区二区三区中文 | 国产成人久久精品流白浆 | 亚洲 高清 成人 动漫 | 国产人妻久久精品二区三区老狼 | 国产人妻精品一区二区三区 | 亚洲男女内射在线播放 | 成熟妇人a片免费看网站 | 国产高清不卡无码视频 | 国产亚洲欧美在线专区 | 婷婷综合久久中文字幕蜜桃三电影 | 日日摸夜夜摸狠狠摸婷婷 | 亚洲欧洲日本无在线码 | 免费网站看v片在线18禁无码 | 双乳奶水饱满少妇呻吟 | 亚洲精品国偷拍自产在线观看蜜桃 | 高中生自慰www网站 | 大乳丰满人妻中文字幕日本 | 久久精品国产精品国产精品污 | 欧美黑人巨大xxxxx | 欧美人与善在线com | 日韩成人一区二区三区在线观看 | 亚洲精品一区二区三区大桥未久 | 国产精品18久久久久久麻辣 | 欧美日韩视频无码一区二区三 | 中文字幕av伊人av无码av | 1000部啪啪未满十八勿入下载 | 婷婷综合久久中文字幕蜜桃三电影 | 无码人妻精品一区二区三区下载 | 少妇人妻偷人精品无码视频 | av在线亚洲欧洲日产一区二区 | 樱花草在线社区www | 久久人妻内射无码一区三区 | 国产综合色产在线精品 | 久久精品无码一区二区三区 | 无码国模国产在线观看 | 国产97在线 | 亚洲 | 女人色极品影院 | 免费人成在线视频无码 | 亚洲综合在线一区二区三区 | 骚片av蜜桃精品一区 | 天天爽夜夜爽夜夜爽 | 人人妻人人澡人人爽人人精品浪潮 | 日韩欧美中文字幕公布 | 日韩人妻系列无码专区 | 俄罗斯老熟妇色xxxx | 国产真实乱对白精彩久久 | 水蜜桃色314在线观看 | 伊人久久大香线焦av综合影院 | 精品久久8x国产免费观看 | 欧美老妇与禽交 | 一本加勒比波多野结衣 | 丰满少妇高潮惨叫视频 | 国产香蕉97碰碰久久人人 | 欧洲熟妇色 欧美 | 亚洲va欧美va天堂v国产综合 | 久久久久人妻一区精品色欧美 | 午夜免费福利小电影 | 曰韩少妇内射免费播放 | 午夜免费福利小电影 | 亚洲男人av天堂午夜在 | 亚洲国产欧美国产综合一区 | 色一情一乱一伦一区二区三欧美 | 中文字幕 亚洲精品 第1页 | 在线观看国产一区二区三区 | 亚洲欧洲无卡二区视頻 | 欧美兽交xxxx×视频 | 国产成人精品一区二区在线小狼 | 综合人妻久久一区二区精品 | 午夜福利一区二区三区在线观看 | 欧美国产日韩久久mv | 自拍偷自拍亚洲精品10p | 最新国产麻豆aⅴ精品无码 | 国产人妻人伦精品1国产丝袜 | 精品人妻中文字幕有码在线 | 骚片av蜜桃精品一区 | 精品国偷自产在线视频 | 特级做a爰片毛片免费69 | 日韩精品一区二区av在线 | 国产疯狂伦交大片 | 丰满人妻精品国产99aⅴ | 欧美日韩精品 | 亚洲第一无码av无码专区 | 77777熟女视频在线观看 а天堂中文在线官网 | 鲁鲁鲁爽爽爽在线视频观看 | 沈阳熟女露脸对白视频 | 亚洲无人区午夜福利码高清完整版 | 欧美自拍另类欧美综合图片区 | 欧美人与禽猛交狂配 | 99视频精品全部免费免费观看 | 最近的中文字幕在线看视频 | 天堂а√在线地址中文在线 | 久久久久久亚洲精品a片成人 | 国产乡下妇女做爰 | 亚洲自偷精品视频自拍 | 蜜桃无码一区二区三区 | 一区二区三区乱码在线 | 欧洲 | 久久久久亚洲精品男人的天堂 | 日本精品少妇一区二区三区 | 99精品视频在线观看免费 | 在线a亚洲视频播放在线观看 | 亚洲色在线无码国产精品不卡 | 无码午夜成人1000部免费视频 | 日日天日日夜日日摸 | 国产精品欧美成人 | 精品亚洲韩国一区二区三区 | 日本丰满护士爆乳xxxx | 精品 日韩 国产 欧美 视频 | 男人的天堂2018无码 | 午夜理论片yy44880影院 | 亚洲成a人片在线观看日本 | 日日摸夜夜摸狠狠摸婷婷 | 无码av中文字幕免费放 | 人妻有码中文字幕在线 | 国产精品人人妻人人爽 | 动漫av一区二区在线观看 | 午夜熟女插插xx免费视频 | 青青青手机频在线观看 | 乱人伦人妻中文字幕无码久久网 | 丁香啪啪综合成人亚洲 | 国产亚洲精品久久久久久大师 | 娇妻被黑人粗大高潮白浆 | 国产尤物精品视频 | yw尤物av无码国产在线观看 | 亚洲七七久久桃花影院 | 国产激情无码一区二区app | 高潮毛片无遮挡高清免费视频 | 九九热爱视频精品 | 国产精品无码一区二区三区不卡 | 又色又爽又黄的美女裸体网站 |