青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

桃源谷

心靈的旅行

人生就是一場旅行,不在乎旅行的目的地,在乎的是沿途的風景和看風景的心情 !
posts - 32, comments - 42, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

跟著開源/來學習源C語言代碼的讀法

Posted on 2009-02-01 15:54 lymons 閱讀(5699) 評論(0)  編輯 收藏 引用 所屬分類: CUnix/Linux文章翻譯
From 長城
 

跟著開源/來學習源C語言代碼的讀法

http://itpro.nikkeibp.co.jp/article/COLUMN/20070622/275606/

 

まつもと ゆきひろ
(Yukihiro "Matz" Matsumoto)

翻譯: Lymons

 「Code Reading―從開源里學習軟件開發(fā)的技法」有這樣一本書。我是這本書日本版的譯者, 呵呵有點王婆賣瓜---自賣自夸的感覺,但是把讀源代碼作為主題的在市面還沒有其他的書。我認為這是一本網羅了從技法到工具,數據結構,構架,還有利用代碼的實際讀法的實例的好書。

照片1●「Code Reading―跟著開源來學習軟件的開發(fā)技法」

 這本書的前言里,編程高手Dave Thomas寫下了下面的話。

 沒有研讀過其他作家作品的偉大作家,沒有研究過其他畫家筆法的偉大畫家,沒有盜取過并肩作戰(zhàn)的同事的技術的技巧高明的外科醫(yī)生,沒有在副駕駛的位置積累實際經驗的波音767的機長,在現實生活中真的會存在他們這樣的人嗎?

 的確是不存在上面降到的那些人。我們通常說的,在軟件開發(fā)以外的領域里進行的修煉,也就是去觀摩他人的工作,先是去模仿,然后是盡全力的做而后拿出自己的獨有特點。在拳術里有句話就叫”守.破.離“。

注:

“守破離“ 就是指:

遵從繼承過來的東西

摒棄與現代不合適的東西

加入新的東西,獨自專研,而后超越了前人 

『守(しゅ)』『破(は)』『離(り)』とは 指導者から何かを學び始めてから、ひとり立ちしていくまでに人は、『守』?『破』?『離』という順に段階を進んでいきます。

 

『守』

 最初の段階では、指導者の教えを守っていきます。 できるだけ多くの話を聞き、指導者の行動を見習って、指導者の価値観をも自分のものにしていきます。 學ぶ人は、すべてを習得できたと感じるまでは、指導者の指導の通りの行動をします。 そして、指導者が「疑問に対して自分で考えろ」と言うことが多くなったら、次の段階に移っていきます。

『破』

 次の段階では、指導者の教えを守るだけではなく、破る行為をしてみます。 自分獨自に工夫して、指導者の教えになかった方法を試してみます。 そして、うまくいけば、自分なりの発展を試みていきます。

『離』

 最後の段階では、指導者のもとから離れて、自分自身で學んだ內容を発展させていきます。

 先去模仿別人這是當然的,但是在IT業(yè)界里卻不必遵守的一面也有.在商用軟件的世界里源代碼是一個企業(yè)生存的飯碗,外界的人是看不到它們的.商用軟件里,這些私有的代碼也就是財產,這些代碼是無論如何也不能被讀到的.軟件開發(fā)的很多技術,在各個軟件公司中都是前輩通過口頭教授的方式來傳遞給后輩.

清楚閱讀代碼的目的

 多虧了開源.軟件,我們才能把這些實際的代碼看的一清二楚,能夠對它們進行學習了.雖然是這樣,但是僅僅通過毫無目的地去讀代碼,并不能讓誰都能成為一名優(yōu)秀的程序員.很遺憾,源代碼并不像小說,音樂,電影一樣,能夠根據人類的感性直接進行運轉起來的.源代碼是在讓人和計算機都能理解的,用編程語言這種稍微特殊的形式來描寫出來的.因此,不能像普通小說那樣去讀它.在有數萬行的代碼,如果漫無目的地從最開頭去讀,我想幾乎沒有人能夠去輕而易舉地理解其中的內容.但是,因為在源代碼中并沒有像小說那樣的故事,所以沒有必要把源代碼全部的通讀一遍*1.還不如只截取非常有意思的地方,或者有必要的地方,來學習先人的智慧就足夠了.

 那么,閱讀源代碼有各種各樣的必要的東西,最開始的一個必要的東西恐怕就是目的了吧.根據想要學習什么來閱讀源代碼,可以富有成效地去理解它,學習到其中的知識. 例如,”學習遞歸下降語句解析的實現方法”啊,”處理系中垃圾回收機制是如何實現”的啦,”這個處理系為什么運行速度會這么快”等. 把哪些東西學到手作為閱讀的目的,是一個在膨脹的代碼中要選擇閱讀那個地方的方針.

 讀代碼的目的,不僅僅是為了學習. 例如, 在軟件維護和調試的時候,必須要讀懂相關的源代碼. 因為工作的原因去維護其他人寫的軟件的情況并不是一間稀奇的事情. 為了又要改善軟件,又要追加功能,又要修正BUG, 必要要對目標的源代碼進行閱讀和理解. 即使是自己寫過的源代碼,經過很長的一段時間后它的內容和背景也幾乎記不清楚的情況也經常發(fā)生. 在軟件業(yè)里,有”半年前的自己就是別人”的這樣一個諺語. 因此, 即使自己寫過的軟件, 最終自己也有必要去閱讀它.

要擁有閱讀方法的策略

 即使完全地了解目的了,胡亂地對源代碼瞎讀一通也是不能達成目的的. 讀代碼的測試有好幾種, 但是我只給大家介紹我經常使用的那幾種(圖1)。

圖1●閱讀源代碼的的三種策略

降落傘法

 有目的地去閱讀源代碼的時候, 必須要讀完程序的全部代碼是非常少見的事情.實際上是, 那些想要知道的知識是代碼中被隱藏的部分, 存在BUG的部分, 從全體看來,找到只不過是其中的一小部分而已的地方, 僅僅閱讀這部分代碼就足夠了. 所謂“降落傘法”就是, 找到其中的重要的地方, 僅僅閱讀這個地方的源代碼的策略. 就像降落傘部隊在突襲某個重要據點一樣. 降落傘法的本質則是, 要找到哪個部分是重要的. 實際的例子在后面要介紹,但是檢索是這里的關鍵.

深度優(yōu)先探索法

 極其少見地,想要把握程序的全體流程的情況也是有的. 例如想要把握Linux啟動時的控制流程時. 在這個場合, 從程序啟動時最開始被執(zhí)行的main函數開始, 按照深度優(yōu)先的方式一個一個地去遍歷被調用的函數, 一直到不再調用其他的函數的最末端函數為止, 然后是開始反向遍歷閱讀這個路徑上的代碼. 利用像這樣的自底向上的閱讀方式,在”不知道的函數假設它不存在”的狀態(tài)下能夠進行閱讀, 能夠高效率地去閱讀源代碼. 為了肯定這個方法的發(fā)明人,根據他的名字這種方式也被叫做”hira方法”,實際上,在閱讀Linux源代碼的時候經常會使用這種方法*2

調試法

 程序的狀態(tài)是伴隨著運行有這個各種各樣的變化. 因此, 雖說讀解程序, 但是僅僅通過閱讀程序的字面意思并不能理解它的真意. 有時候,閱讀者有必要把自己想象成一臺計算機來判斷變量和對象的狀態(tài).

 但是, 試著考慮一下, 即使我們不用想象, 計算機最終還是要執(zhí)行這個程序, 所以如果我們能觀察它在執(zhí)行時候的樣子的話, 就能正確的知道運行時候的狀態(tài)了.  這就是調試(debug). 使用調試的話,能讓程序在任意的地點停止,就可以調查這個時侯的變量的狀態(tài). 調試就是為了找到BUG而被引入的軟件, 但是為了能夠知道軟件在運行時候的狀態(tài), Code.Reading也同樣有效.

尋找源代碼的方法

 閱讀源代碼的時候,必須要得到關鍵的源代碼. 可以利用互聯網無限制的得到免費的源代碼. 在這里介紹幾種開源.軟件的獲取方法.

freshmeat 略

SourceForge 略

Google 略

源代碼檢索

 最近,即使不下載全部的源代碼,也能登陸即刻檢索源代碼的Web網站. 有代表的網站如, Koders(http://www.koders.com/,圖3)和Google CodeSearch(http://www.google.com/codesearch,圖4).

圖3●檢索源代碼網站的Koders

 

圖4●檢索源代碼網站的Google CodeSearch

 在檢索源代碼的時候, 必須要注意以下的幾點.

OS 略

語言 略

許可證 略

 

關鍵代碼的檢索方法

 軟件的源代碼, 大體都有預想以上的規(guī)模. 超過600萬行的Linux是一個非常極端的例子, 但是, Ruby那樣并不是很龐大的軟件也超過了10萬行. 想這樣龐大的規(guī)模, 閱讀所有的代碼是一件不現實的事情. 閱讀源代碼的時候, 找到掩藏這必要信息的關鍵場所是非常重要的.

 在讀解源代碼的時候, 首先要理解程序的全體框架是非常有必要的. 程序的所有代碼沒有必要閱讀, 但是, 為了找到自己想要查找的信息在被安放在什么地方, 制作出程序全體的結構圖就可以讓閱讀變得非常方便的.

 因此,最有用的是源代碼的文件名。大體的軟件的源代碼都被分成很多的文件.在各個文件被應該命名成跟程序機能相關聯的名字. 例如, 想要讀取內存管理的源代碼的時候, “就可以懷疑memory.c和gc.c這樣的文件”就是我們要找的.

 檢索源代碼的工具也是必不可少的. 這些工具被總結在表2里.

表2●源代碼檢索必備的工具一覽

 那么讓我們找實際的代碼試一試閱讀它吧.

 

Code.Reading的實際演練
1
pom程序

 2年前,在生產我的小兒子的時候, 清晨4點就要帶著妻子去醫(yī)院而出了門,正好看見空中美麗的照耀大地的滿月. 有那么一說,孩子的分娩與月亮的圓缺有關系. UNIX中有pomphase of the moon這樣一個C語言的程序, 用來表示月亮的圓缺月齡.

 根據列表1可以看出來是滿月 我共有4個孩子, 其他的三個中一個幾乎是新月(5%), 一個幾乎是滿月(98%), 另一個是介于半月和滿月之間(62%). 4人里有3人是滿月活新月,所以這是非常高的幾率哦. 然而, UNIXpom不能計算1970年以前的月齡因此,我妻子的月齡也就不能計算.

% pom 04102804

Thu 2004 Oct 28 04:00:00 (JST): The Moon was Full

列表1●表示月齡的軟件pom的執(zhí)行結果

 在這里讀它的源代碼吧. 首先, 從找它的源代碼開始. 我們試著使用GoogleCodeSearch5訪問網站http://www.google.com/codesearch后輸入查找關鍵字,phase of the moon pom”這樣的詞就行. 檢索的結果有好幾個候補. 找了幾個后我想我找到了pom.c的文件.

 pom.c是一個有286行的小程序文件頭是表示許可證和被包含的頭文件的地方,暫且略過. 要了解全體的動作則必須先從main( )函數開始看列表2)。

列表 2●pom.cmain函數
[點擊圖像放大]

 上面能夠看到代碼的大部分內容英語的時制滿月/新月等, 也就明白了正在使用的東西包括, 月齡的計算使用通過potm( )函數來進行的.  叫做days的浮點數被傳遞到potm( )函數中. Days是從基準點19891231開始的一個日數.

 在計算days的那行代碼列表2(1)調整了UNIX的時刻197011日開始的描述和被potm( )處理的時刻. 在這里出現的常量86400等于24小時×60×60也就是1整天的描述. 暫且把potm( )的處理邏輯作為黑盒(black box)先擱置在一邊.

 我們關心的是”為什么1970年以前的不能計算呢”pom程序里一處理1970年以前的日期的話, 會出現 列表3那樣的錯誤消息. 一檢索這個消息字符串我們會找到在列表4中表示的代碼.

pom: specified date is outside allowed range

列表3●1970年以前的日期傳遞到pom中會打印出來的錯誤消息

 

if ((tval = mktime(lt)) == -1)

 errx(1, "specified date is outside allowed range");

列表4●包含列表3中錯誤消息的代碼

 似乎是因為C的庫函數mktime( )不能處理1970年以前的時間的這個理由pom才不能計算的. 如果是1970年以后的時間,在基準點以前的月齡也能計算, 那就說明potm( )的算法里好像沒有對1970年的限制.

6●Ruby版本的pom200410284時的月齡的表示結果

 總而言之,如果不使用mktime()就能計算days的話那當然好了. 但在C中不使用mktime()來計算時間好像很困難. 于是, 試著使用Ruby來實現吧RubyDateTime類對于日期的計算是非常拿手的. 1970年的限制沒有了,反而公元前數千年到公元數萬年的日期都能輕而易舉的計算出來.

 列表5是把pom.c的代碼翻譯成Ruby代碼的結果potm( )函數的算法是原封不動的轉換成了Ruby代碼. main( )中的代碼的邏輯在前面已經表示過了所以這里全部都省略掉了,該程序也能用百分比的形式來表示月齡6)。

# Copyright (c) 1989, # Copyright (c) 1989, 1993

# The Regents of the University of California.

# All rights reserved.

 

require 'date'

 

EPOCH_MINUS_1970=(20 * 365 + 5 - 1)

 # 20 years, 5 leaps, back 1 day to Jan 0

 

EPSILONg=279.403303 # solar ecliptic long at EPOCH

RHOg=282.768422 # solar ecliptic long of perigee at EPOCH

ECCEN=0.016713 # solar orbit eccentricity

LZERO=318.351648 # lunar mean long at EPOCH

Pzero=36.340410 # lunar mean long of perigee at EPOCH

Nzero=318.510107 # lunar mean long of node at EPOCH

 

include Math

 

def potm(days)

 n = 360 * days / 365.242191

 n = adj360(n)

 msol = n + EPSILONg - RHOg

 msol = adj360(msol)

 ec = 360 / PI * ECCEN * sin(dtor(msol))

 lambdasol = n + ec + EPSILONg

 lambdasol = adj360(lambdasol)

 l = 13.1763966 * days + LZERO

 l = adj360(l);

 mm = l - (0.1114041 * days) - Pzero

 mm = adj360(mm);

 nm = Nzero - (0.0529539 * days)

 nm = adj360(nm);

 ev = 1.2739 * sin(dtor(2*(l - lambdasol) - mm))

 ac = 0.1858 * sin(dtor(msol))

 a3 = 0.37 * sin(dtor(msol))

 mmprime = mm + ev - ac - a3

 ec = 6.2886 * sin(dtor(mmprime))

 a4 = 0.214 * sin(dtor(2 * mmprime))

 lprime = l + ev + ec - ac + a4

 v = 0.6583 * sin(dtor(2 * (lprime - lambdasol)))

 ldprime = lprime + v

 d = ldprime - lambdasol

 return(50.0 * (1 - cos(dtor(d))))

end

 

def dtor(deg)

 deg * Math::PI / 180

end

 

def adj360(deg)

 loop do

  if (deg < 0)

   deg += 360;

  elsif (deg > 360)

   deg -= 360;

  else

   return deg

  end

 end

end

 

tmpt = ARGV[0] ? DateTime.parse(ARGV[0]) : DateTime.now

days = tmpt - DateTime.parse("1989-12-31T00:00Z")

printf "%d%% full\n", (potm(days.to_f) + 0.5).to_i

列表5●pom程序的Ruby版代碼

 用它來計算的話,我家的男性們結果是60%的滿月, 而女性們結果幾乎都是新月和滿月.  雖然就憑我們家里的這么點兒例子也不能說明什么或得出什么結論…

 另外,列表5中的程序和原始的pom程序一樣按照BSD協議許可來公開.

 

Code.Reading的實際例子
2
閱讀語言的UTF-8處理

 在看看別的例子吧pom例子中的代碼規(guī)模實在是太小了, 所以這次咱們試一試在大規(guī)模的代碼中來查找目標代碼.

 Unicode字符串的編碼方式之一就有UTF-8格式. 很少有人知道, 實際上UTF-8并沒有限定在Unicode之內. 把任意的31位的整數數列符號化成可變長的字節(jié)序列6 . 7表示的是它的比特位.模式.

7●UTF-8比特位.模式
[點擊這里放大圖像]

 那么,我們考慮實現一個把1個字符從整數轉換成字節(jié)序列,或者從字節(jié)序列轉換成整數的函數按照7的比特位.模式,拼了老命好像也能實現這個功能, 但是為了方便期間, 還是參考一下前人寫過的代碼吧.

 作為參考, 只要是實現了處理UTF-8的字符串這個功能, 不管這個程序用什么語言來編制都沒有關系.從各方面來考慮,在本文中將對腳本語言的代碼進行說明. 因此,我們在這里準備了Perl,Python,Ruby的源代碼.

 因為想要查找UTF-8關聯的機能, 暫且從使用grep命令來檢索源代碼開始. 首先是看Perl的源代碼, UTF-8中含有在C語言標識符不能識別的橫線, 所以忽略掉它用utf8作為關鍵字來進行檢索. 使用命令行 grep -i utf8 *.c”來檢索的話, utf8.c文件里找到了uvchr_to_utf8_flags( )utf8n_to_uvchr( )這兩個函數. 但是, 一看這個文件的源代碼的話, 因為不了解Perl的內部結構它的源代碼非常難讀列表6)。Python中調查了也是同樣, 在文件Object/unicodeobject.c中有PyUnicode_EncodeUTF8( )PyUnicode_DecodeUTF8( )這兩個函數. 雖然不講它的代碼,但是也有必要了解Python的內部結構的相關知識.

UV

Perl_utf8n_to_uvchr(pTHX_ U8 *s, STRLEN curlen, STRLEN *retlen, U32 flags)

{

 UV uv = Perl_utf8n_to_uvuni(aTHX_ s, curlen, retlen, flags);

 return UNI_TO_NATIVE(uv);

}

列表6●Perlutf8n_to_uvchr( )函數的源代碼片段

 在最后讓我們看看Ruby的代碼, 比較好的是在文件pack.c里的函數uv_to_utf8( )utf8_to_uv( )不依賴于Ruby的內部結構, 可以簡單的留用下來作為我們的參考列表77

列表7●Ruby里的uv_to_utf8( )utf8_to_uv( )函數的源代碼片段

 一讀這里的實際代碼,就能發(fā)現UTF-8的定義了雖然這樣, utf8_to_uv函數中輸入的字節(jié)序列很有可能不正確, 所以對于不正確的輸入要進行嚴格的檢查 特別是在utf8_to_uv函數的末尾追加了對”冗余的UTF-8序列”的處理是很重要的. 濫用冗余的UTF-8序列的話,那就會有含有危險字符會被黑客鉆空子的危險. 可以說只能通過閱讀實際的代碼才能得到這些知識.

 在這個函數中使用了Ruby的內部錯誤報告函數rb_raise( )如果想延用上面的代碼的話, 則需要把rb_raise( )函數換成其他的錯誤報告函數.

 Code.Reading, 程序員進行學習, 修煉, 代碼Review, 軟件維護, 調試等等, 在編程的所有領域都要掌握的基本工作方式這次是因為篇幅有限, 在這里只能介紹Code.Reading的最有價值的部分了. 有機會的話, Code.Reading和調試這部分我也想再詳盡的講一講. 那這樣的話,看看Code Reading的書籍, 再考慮考慮自己的代碼閱讀能力, 好嗎.

 就到這里,下次再見

 [2007/06/29]

我的個人簡歷第一頁 我的個人簡歷第二頁
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久久久亚洲综合影院红桃| 欧美成人精品三级在线观看| 美女被久久久| 亚洲精品日产精品乱码不卡| 香港久久久电影| 欧美高清在线视频观看不卡| 国产老女人精品毛片久久| 亚洲黄色毛片| 欧美一区二区三区免费观看 | 国产精品日韩电影| 国产午夜精品久久| 亚洲国产欧美在线人成| 亚洲一区二区三区777| 老色批av在线精品| 一区二区三区www| 久久综合网络一区二区| 国产麻豆精品theporn| 亚洲精品日韩一| 久久久av水蜜桃| av成人免费在线| 另类图片国产| 国产三区精品| 亚洲一区视频在线观看视频| 欧美aⅴ一区二区三区视频| 亚洲性视频网址| 欧美电影电视剧在线观看| 国内精品模特av私拍在线观看| 中文国产成人精品| 欧美国产日产韩国视频| 性欧美videos另类喷潮| 欧美日韩一级黄| 亚洲精品一区二区在线| 久久综合久久综合这里只有精品| 一区二区三区久久精品| 欧美激情一区二区三区成人 | 欧美成人亚洲成人日韩成人| 国产欧美日韩一区二区三区在线观看| 99精品国产在热久久婷婷| 美日韩精品免费观看视频| 新狼窝色av性久久久久久| 欧美天天综合网| 亚洲精品中文字| 亚洲电影在线看| 久久久久久精| 国模套图日韩精品一区二区| 午夜精品久久| 亚洲一区二区网站| 欧美视频在线视频| 一区二区三区.www| 亚洲精品一区在线观看| 欧美国产精品| 亚洲免费成人av| 亚洲国产天堂久久综合网| 免费观看成人| 亚洲国产日韩一级| 欧美va亚洲va日韩∨a综合色| 欧美在线综合视频| 国模一区二区三区| 久久天堂国产精品| 久久久久久久综合狠狠综合| 狠狠爱综合网| 另类酷文…触手系列精品集v1小说| 午夜综合激情| 精品不卡在线| 免费永久网站黄欧美| 麻豆视频一区二区| 91久久精品美女高潮| 亚洲国产一区二区三区高清| 欧美成人按摩| 一区二区三区精品| 一区二区三区|亚洲午夜| 国产精品久久久久久久午夜| 午夜视频一区| 久久激情五月婷婷| 亚洲二区在线视频| 亚洲欧洲一区二区三区久久| 欧美日韩国产丝袜另类| 亚洲免费婷婷| 午夜精品久久99蜜桃的功能介绍| 国产美女精品在线| 久久全球大尺度高清视频| 久久久久久91香蕉国产| 亚洲激情视频| 一本色道久久综合亚洲91| 国产精品丝袜白浆摸在线| 久久久精品国产免大香伊| 久久在线免费| 中文一区二区在线观看| 亚洲影院免费观看| 国内一区二区三区| 欧美黄色一区二区| 欧美午夜电影在线观看| 欧美一级专区免费大片| 久久精品免费电影| 日韩亚洲欧美一区| 亚洲在线黄色| 91久久久久久| 亚洲一区网站| 亚洲国产精品毛片| av成人免费观看| 黑人一区二区三区四区五区| 欧美激情二区三区| 国产精品乱码一区二区三区| 久久亚洲精品欧美| 欧美日韩影院| 久久综合色影院| 欧美久久视频| 欧美中文在线观看国产| 欧美成人久久| 欧美影片第一页| 欧美高清hd18日本| 欧美在线视频免费| 欧美福利视频在线观看| 欧美一级视频精品观看| 久久野战av| 午夜精品福利在线观看| 美女视频一区免费观看| 亚洲欧美国产另类| 美日韩精品视频| 亚洲欧美日韩一区| 欧美a级片网| 欧美中文字幕精品| 欧美区二区三区| 久热国产精品| 国产精品欧美风情| 亚洲区欧美区| 激情久久影院| 亚洲在线观看免费视频| 亚洲美女视频在线免费观看| 欧美中在线观看| 亚洲欧美经典视频| 欧美精品色一区二区三区| 久久久成人网| 国产精品xxxav免费视频| 欧美激情一区二区| 国产自产女人91一区在线观看| 日韩亚洲欧美综合| 亚洲国产精品福利| 久久精品99久久香蕉国产色戒| 亚洲午夜激情| 欧美福利视频在线| 美日韩免费视频| 国产在线播精品第三| 亚洲少妇一区| 一区二区91| 男男成人高潮片免费网站| 久久久久久久久综合| 国产精品va在线播放| 亚洲欧洲日韩女同| 亚洲国产精品久久久久久女王| 午夜精品剧场| 午夜精品久久久久久久久久久久 | 欧美午夜片在线观看| 欧美激情偷拍| 1024成人| 久久高清免费观看| 久久超碰97人人做人人爱| 国产精品xnxxcom| 一本色道久久88亚洲综合88| 一本久道久久综合中文字幕| 男女精品视频| 欧美aa在线视频| 在线日本欧美| 久久久成人网| 免费观看日韩| 亚洲国产精品成人| 毛片精品免费在线观看| 欧美成年人在线观看| 亚洲国产精品久久人人爱蜜臀| 久久九九免费| 欧美成人免费观看| 亚洲第一天堂av| 噜噜噜噜噜久久久久久91| 欧美va天堂| 亚洲国产日韩欧美在线99| 男人天堂欧美日韩| 亚洲电影专区| 99热精品在线| 欧美日韩一区二区三区四区在线观看| 亚洲精品少妇| 亚洲无线一线二线三线区别av| 欧美日韩久久精品| 一本色道久久综合精品竹菊| 亚洲欧美日韩在线一区| 国产精品人成在线观看免费| 亚洲摸下面视频| 久久久人成影片一区二区三区观看| 国产亚洲一本大道中文在线| 久久黄色小说| 欧美激情小视频| 99精品国产一区二区青青牛奶| 欧美日韩精品中文字幕| 一区二区日韩精品| 久久福利资源站| 有坂深雪在线一区| 欧美激情日韩| 亚洲一区在线免费| 葵司免费一区二区三区四区五区| 亚洲国产精品热久久| 欧美日韩国产精品自在自线|