• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    openEuler 中C 標(biāo)準(zhǔn)庫替換的兼容性分析

    2023-07-20 11:21:06吳亦澤于佳耕武延軍
    計算機(jī)研究與發(fā)展 2023年7期
    關(guān)鍵詞:定義重要性生態(tài)

    吳亦澤 于佳耕 鄭 晨 武延軍,3

    1 (中國科學(xué)院軟件研究所 北京 100190)

    2 (中國科學(xué)院大學(xué) 北京 101408)

    3 (計算機(jī)科學(xué)國家重點實驗室(中國科學(xué)院軟件研究所)北京 100190)

    應(yīng)用程序編程接口(application programming interface,API)是為其他軟件提供服務(wù)的軟件接口[1],將計算機(jī)與軟件或軟件與軟件連接,為軟件開發(fā)者提供幫助.應(yīng)用軟件使用操作系統(tǒng)提供的功能時,需要調(diào)用操作系統(tǒng)提供的API.在Linux 各發(fā)行版中,為了讓應(yīng)用開發(fā)者能更方便地使用系統(tǒng)API 以實現(xiàn)更復(fù)雜的功能,系統(tǒng)將API 進(jìn)一步封裝至C 標(biāo)準(zhǔn)庫(本文簡稱C 庫)中,并將C 庫的API 供用戶調(diào)用.C 庫連接了應(yīng)用軟件和操作系統(tǒng),C 庫的接口實現(xiàn)影響應(yīng)用軟件對系統(tǒng)功能的使用.如果應(yīng)用軟件不能通過調(diào)用C庫接口來和系統(tǒng)建立聯(lián)系,很多關(guān)鍵的應(yīng)用功能也將無法實現(xiàn).

    常見的GNU/Linux 類桌面和服務(wù)器系統(tǒng)都采用GNU C library(glibc)這套C 語言標(biāo)準(zhǔn)庫,它實現(xiàn)了多種多樣的C 庫接口,支持各類系統(tǒng)平臺,功能十分齊全.glibc 使用LGPL v2.1(GNU Lesser General Public License v2.1)協(xié)議.與GPL(GNU General Public License)協(xié)議要求“任何使用、修改和衍生GPL 庫的軟件必須采用GPL 協(xié)議并開源”不同的是,LGPL 允許軟件通過類庫引用的方式使用LGPL 庫而無需開源,但對于系統(tǒng)開發(fā)者而言,在對庫進(jìn)行修改或衍生時LGPL仍具有限制性和傳染性.因此,在商業(yè)化系統(tǒng)中使用glibc 存在強(qiáng)制開源的不便和安全問題.

    為了避免系統(tǒng)搭載的C 庫因開源協(xié)議而在商業(yè)化場景下帶來問題,開源歐拉(openEuler)操作系統(tǒng)商業(yè)發(fā)行版的開發(fā)者正在考慮用musl libc 替換glibc.musl libc 是一個使用MIT 許可證的輕量級C 庫,MIT許可證在有版權(quán)聲明的條件下允許任意地使用、復(fù)制、修改和散布軟件而無需開源.musl libc 可用于從小型嵌入式系統(tǒng)到通用桌面、服務(wù)器系統(tǒng)的很多場景,具有體量小、魯棒性和安全性強(qiáng)、易于裝載等優(yōu)勢.因其基礎(chǔ)架構(gòu)較為成熟,使用的協(xié)議也適用于商業(yè)場景,故musl libc 成為替換glibc 的首要選擇.

    新C 庫對原有應(yīng)用軟件的兼容是C 庫替換工作的關(guān)鍵——新C 庫應(yīng)當(dāng)保證在原有C 庫下能正確運行的應(yīng)用軟件在替換后也能正確運行.目前,musl libc 相比glibc 有較多功能缺失,如果直接進(jìn)行替換,將導(dǎo)致C 庫對應(yīng)用軟件的兼容性較低,而低兼容性嚴(yán)重影響操作系統(tǒng)提供的服務(wù)質(zhì)量,降低商業(yè)系統(tǒng)的市場競爭力.因此,在替換前需要通過補(bǔ)全開發(fā)將musl libc 的兼容性提高到足夠高的水平.

    兼容性分析對新C 庫的開發(fā)很有幫助[2],然而現(xiàn)有的兼容性分析方法并不適用于openEuler 對musl libc 的補(bǔ)全工作(見1.3 節(jié)和6.3 節(jié)).針對這個問題,本文提出新的兼容性分析算法來研究openEuler 的4 種主要軟件生態(tài)中的musl libc 兼容性和缺失API 優(yōu)先級.本文的研究目的是幫助openEuler 的C 庫開發(fā)者了解musl libc 在openEuler 操作系統(tǒng)上的兼容性,并參照優(yōu)先級順序補(bǔ)全開發(fā)接口,合理安排開發(fā)工作.

    本文的主要貢獻(xiàn)有4 個方面:

    1)量化對比了musl libc 與glibc 的接口.根據(jù)接口開發(fā)現(xiàn)狀,將全部接口劃分為主要接口和非主要接口,并分別進(jìn)行接口對比分析,量化了musl libc 和glibc 的接口差異和重合率,論證了對musl libc 進(jìn)行補(bǔ)全的必要性和可行性.

    2)量化分析了musl libc 對應(yīng)用軟件生態(tài)的兼容情況.根據(jù)應(yīng)用軟件對缺失API 的調(diào)用情況和應(yīng)用之間的依賴關(guān)系提出了兼容的定義,將依賴關(guān)系構(gòu)建為圖模型,將兼容的定義形式化,并統(tǒng)計分析了應(yīng)用軟件生態(tài)的兼容情況.

    3)提出了兼容性度量算法——PackageRank.PackageRank 在圖模型上為應(yīng)用軟件賦分,并通過計算兼容應(yīng)用的得分占比來度量兼容性.

    4)提出了缺失API 優(yōu)先級算法——APIRank.APIRank 是PackageRank 的延伸,根據(jù)缺失API 被應(yīng)用軟件調(diào)用的情況,對圖模型作出進(jìn)一步擴(kuò)展,并在新的圖模型上為API 賦分,以度量缺失API 的優(yōu)先級.

    1 相關(guān)工作

    1.1 C 標(biāo)準(zhǔn)庫

    除glibc 和musl libc 外,還有多種其他C 標(biāo)準(zhǔn)庫的實現(xiàn),如eglibc,uClibc,dietlibc 等.eglibc 是glibc 的一個分支,專為嵌入式場景設(shè)計,嚴(yán)格兼容二進(jìn)制的glibc,使用LGPL v2.1 協(xié)議,2014 年初停止開發(fā);uClibc為嵌入式Linux 系統(tǒng)開發(fā),其迎合小型C 庫需求,使用LGPL v2.1 協(xié)議,自2012 年5 月以來未有新發(fā)行版本;dietlibc 適用于小型場景,可以為多種體系結(jié)構(gòu)的Linux系統(tǒng)提供靜態(tài)鏈接二進(jìn)制庫,使用GPL v2 協(xié)議,最新版本于2018 年9 月發(fā)行,版本間隔為4~5 年.相較之下,musl libc 使用MIT 協(xié)議,版本更新周期為6~12個月,最新版本發(fā)布于2022 年4 月.

    musl libc 官方發(fā)布了對自己C 庫的兼容性分析報告[3],將musl libc(1.1.24)與多種C 語言標(biāo)準(zhǔn)和其他C 庫進(jìn)行了比較.分析顯示,musl libc 對POSIX 2008,C99,C11 標(biāo)準(zhǔn)的兼容性良好,分別有12 個、2 個、88個API 未實現(xiàn),對比POSIX 2008 標(biāo)準(zhǔn)有2 個API 有函數(shù)原型但沒有實現(xiàn).在與glibc,uClibc,dietlibc 進(jìn)行對比時,musl libc 的魯棒性、安全性、構(gòu)建環(huán)境適配性均優(yōu)于其他C 庫;性能和體系結(jié)構(gòu)適配性略低于glibc 而遠(yuǎn)優(yōu)于uClibc 和dietlibc;體量略大于dietlibc,略小于uClibc,遠(yuǎn)小于glibc.此外,musl libc 在I/O、信號處理、正則表達(dá)式功能和動態(tài)鏈接等方面與glibc存在功能性差異.

    我們在Ubuntu 20.04 桌面版(Intel?Core? i7-8550U CPU @ 1.80GHz 2.00 GHz)上使用libc-bench-20110206[4]測試集分別對glibc(2.34)和musl libc(1.2.2)作了性能和內(nèi)存占有量的測試,測試結(jié)果展示在圖1中,其中測試用例和測試項目的含義見libc-bench[4].

    Fig.1 Experimental results of performance and memory usage on glibc and musl libc圖1 glibc 與musl libc 的性能和內(nèi)存占有量實驗結(jié)果

    數(shù)據(jù)顯示,musl libc 在27 個測試中僅有3 個的性能比glibc 更高(運行時間更短),而內(nèi)存占有量則有24 個更?。ㄇ一径加忻黠@的優(yōu)勢).這表明,雖然musl libc 的性能仍需提升,但其內(nèi)存占有量低,因此補(bǔ)全開發(fā)工作將更為方便和靈活.

    綜合以上分析,musl libc 架構(gòu)成熟,許可協(xié)議對商用友好,適合進(jìn)行補(bǔ)全開發(fā)和C 庫替換.另一方面,性能較低、功能有差別和缺陷等問題使得直接替換并不可行,補(bǔ)全開發(fā)工作是必要的.

    1.2 openEuler

    openEuler 是一個開源、免費的Linux 發(fā)行版平臺,它通過開放形式的社區(qū)與全球的開發(fā)者共同構(gòu)建一個開放、多元和架構(gòu)包容的軟件生態(tài)體系.2020年3 月,openEuler 社區(qū)正式發(fā)布了首個長期支持版本——openEuler 20.03 LTS,并與多家操作系統(tǒng)廠商共同發(fā)布了基于openEuler 的商業(yè)系統(tǒng)發(fā)行版.openEuler每6 個月發(fā)布一個社區(qū)創(chuàng)新版本,提供6 個月社區(qū)支持,而LTS 版本的發(fā)布間隔周期為2 年,提供4 年社區(qū)支持.目前,openEuler 22.03 LTS 已經(jīng)發(fā)布,有多家國內(nèi)外機(jī)構(gòu)宣布將推出基于openEuler 22.03 LTS 的商業(yè)發(fā)行版.

    1.3 兼容性研究

    在兼容性度量方法中,一種簡單而直接的方法是計數(shù)滿足兼容條件的API 個數(shù)[5-8].其算法比較容易實現(xiàn),但缺乏準(zhǔn)確性,即只關(guān)注API 本身是否兼容,并未考慮真實場景的API 調(diào)用情況.

    一些兼容性研究者已經(jīng)意識到應(yīng)當(dāng)在度量方法中引入應(yīng)用軟件對API 調(diào)用情況進(jìn)行考量,而單一內(nèi)核(unikernel)的出現(xiàn)也啟發(fā)了他們做出這樣的改變.單一內(nèi)核由應(yīng)用程序與其依賴的系統(tǒng)組件的最小集打包制成,具有單一地址空間,可以直接在管理程序(hypervisor)或硬件層面運行[9].由于單一內(nèi)核是根據(jù)應(yīng)用需求搭建的最小集,它必須確保囊括的API 足夠兼容應(yīng)用.一種搭建思路是以現(xiàn)有通用系統(tǒng)的構(gòu)件為基礎(chǔ)進(jìn)一步開發(fā),例如Rumprun[10]和OSv[11]是由BSD 模塊重組生成,Lupine Linux[12]則采用了Linux內(nèi)核的特殊配置和Kernel Mode Linux 補(bǔ)丁.另外還可以設(shè)計API 兼容層來增強(qiáng)自己系統(tǒng)的兼容性[13-14].這樣搭建的單一內(nèi)核仍在使用通用系統(tǒng)的API 標(biāo)準(zhǔn),因此兼容性是其開發(fā)過程的關(guān)鍵,它們的兼容性度量也應(yīng)當(dāng)從API 調(diào)用的角度出發(fā).

    文獻(xiàn)[2]以Ubuntu 15.04 為基準(zhǔn),分析了其他一些Linux 類系統(tǒng)或構(gòu)件(系統(tǒng)調(diào)用、C 庫、文件系統(tǒng)等)的API 重要性(API importance)和加權(quán)完整性(weighted completeness).文獻(xiàn)[2]的作者認(rèn)為“產(chǎn)生兼容性度量不準(zhǔn)確問題的根本原因是缺乏對系統(tǒng)API 在實際中被調(diào)用情況的數(shù)據(jù)統(tǒng)計和分析”.該文獻(xiàn)利用Ubuntu/Debian 的應(yīng)用軟件安裝次數(shù)統(tǒng)計,從概率角度度量其他系統(tǒng)或構(gòu)件的兼容性.該文提出2個度量概念:

    1)API 重要性.一部操作系統(tǒng)上會安裝多個應(yīng)用軟件,這樣的一個“安裝集”是該文獻(xiàn)統(tǒng)計的基本單位.API 的重要性定義為“調(diào)用該API 的應(yīng)用被安裝的概率”.一個應(yīng)用軟件被安裝的概率是包含該應(yīng)用的安裝集個數(shù)(該應(yīng)用的安裝次數(shù))與所有安裝集個數(shù)(即系統(tǒng)總安裝次數(shù))的比值,將不同應(yīng)用軟件的安裝視為獨立事件,便可以通過將所有調(diào)用某個API 的應(yīng)用軟件的安裝概率相乘,來計算API 重要性.

    2)加權(quán)完整性.加權(quán)完整性用于度量系統(tǒng)或構(gòu)件對應(yīng)用的兼容性.應(yīng)用軟件分為被支持的(supported)和不被支持的(unsupported),而加權(quán)完整性的定義為“安裝集中被支持應(yīng)用數(shù)量占該集中所有應(yīng)用數(shù)量的比值的數(shù)學(xué)期望”.仍將不同應(yīng)用軟件的安裝視為獨立事件,便能計算出加權(quán)完整性的估計值.

    許多有待進(jìn)一步開發(fā)的系統(tǒng)構(gòu)件都有API 兼容性上的不足,但也有研究表明Linux API 提供的功能是溢出的.Quach 等人[15]認(rèn)為現(xiàn)代Linux 內(nèi)核中無用的二進(jìn)制內(nèi)容可能引發(fā)棧膨脹(stack bloating),而DeMarinis 等人[16]指出多余的API 為系統(tǒng)黑客留下了更大的攻擊面.這些研究也從另一個角度辯證地解讀了兼容性:兼容作用應(yīng)當(dāng)貼合應(yīng)用的需求,盲目地追求兼容可能帶來負(fù)面效果,提升API 兼容性的開發(fā)工作需要有的放矢.

    本文采用靜態(tài)分析度量兼容性,此外還可以采用動態(tài)分析或靜態(tài)和動態(tài)分析結(jié)合的方法.文獻(xiàn)[2]也采用了靜態(tài)分析度量系統(tǒng)和構(gòu)件的兼容性,Cui 等人[17]利用動態(tài)二進(jìn)制翻譯(dynamic binary translation)技術(shù)分析了Intel SGX Enclaves 的系統(tǒng)調(diào)用的兼容性,Atlidakis 等人[18]將靜態(tài)和動態(tài)結(jié)合來分析POSIX標(biāo)準(zhǔn)是否仍符合現(xiàn)代應(yīng)用的需求.鄭煒等人[19]總結(jié)了近年來安卓移動應(yīng)用兼容性的靜態(tài)和動態(tài)分析方法.動態(tài)分析收集程序的運行時數(shù)據(jù),比靜態(tài)分析更加接近實際場景,但往往又無法準(zhǔn)確模擬程序?qū)嶋H工作時的行為.在兼容性研究中,測試用例的選取不當(dāng)會導(dǎo)致兼容問題不能在測試中暴露,降低兼容性分析的準(zhǔn)確性.

    2 musl libc 與glibc 的接口對比

    本節(jié)將進(jìn)行musl libc 與glibc 的接口對比分析.本節(jié)的結(jié)果是本文后續(xù)內(nèi)容的基礎(chǔ)和依據(jù).

    在本文的研究中,musl libc 和glibc 均由官方倉庫源碼編譯并安裝,見表1.編譯C 庫時使用的編譯器是x86_64-linux-gnu-gcc 9.4.0,安裝C 庫的系統(tǒng)是Ubuntu 20.04 桌面版.

    Table 1 Versions and Repository Addresses of C Libraries表1 C 庫的版本號與倉庫地址

    2.1 接口名稱提取

    鏈接器在鏈接時需要知道庫文件內(nèi)部定義了哪些接口,這要求被鏈接接口的信息必須完整保存在庫文件的符號表中.因此,可以從庫文件的符號表內(nèi)提取接口名稱.

    本文研究中的接口名稱提取自C 庫中的可執(zhí)行文件(executable and linkable format,ELF).具體方法為:遍歷C 庫所在目錄中的所有文件,讀取其中每個ELF的符號表.對于每個符號表項,如果其類型(type)為FUNC 或IFUNC 且可見度(bind)為GLOBAL 或 WEAK,則提取其符號名(name).這樣提取的接口名稱僅包含可被鏈接的接口,而不可鏈接的接口與C 庫的兼容無關(guān)(僅定義在內(nèi)部,不能被應(yīng)用軟件調(diào)用),故不在本文的研究范圍內(nèi).

    經(jīng)過提取,glibc 共有6 466 個接口,musl libc 共有1 898 個.

    2.2 主要接口

    C 庫的接口有這樣的命名習(xí)慣:以字母起始的接口供用戶調(diào)用,以下劃線起始的接口實現(xiàn)內(nèi)部和底層的功能(與操作系統(tǒng)交互、初始化和退出、編譯優(yōu)化等).例如,printf 是標(biāo)準(zhǔn)輸出的常用接口,而__libc_start_main 是C 程序初始化啟動的一部分,gcc 在編譯時可能會將printf 替換為_printf_chk 以防止棧溢出[2].本文將名稱以字母起始的接口稱為主要接口.

    應(yīng)用軟件開發(fā)者應(yīng)該避免直接調(diào)用非主要接口[20],故C 庫的底層差異不會導(dǎo)致兼容問題.然而,在靜態(tài)分析應(yīng)用軟件對接口的調(diào)用情況時,非主要接口可能會帶來兼容性的誤判.例如,應(yīng)用軟件調(diào)用的printf在gcc 編譯時被替換為_printf_chk,由于musl libc 未實現(xiàn)_printf_chk,所以分析結(jié)果將顯示該應(yīng)用軟件調(diào)用了未實現(xiàn)的接口,從而存在兼容問題.但是,如果使用musl-gcc 編譯,程序可以正確鏈接musl libc 的printf 接口,所以兼容問題實際上并不存在.

    雖然本文的研究角度是二進(jìn)制兼容,但這樣的誤判將導(dǎo)致兼容性分析結(jié)果不準(zhǔn)確,這是我們希望避免的.因此,本文在兼容性度量時只對主要接口做統(tǒng)計和分析.除特別注明外,后文中所述的結(jié)果均以主要接口為研究對象.

    經(jīng)篩選,glibc 有2 883 個主要接口,musl libc 有1 516 個.

    2.3 接口對比分析

    全部接口和主要接口的統(tǒng)計結(jié)果見表2.除接口數(shù)量外,為比較C 庫的接口實現(xiàn)相似度,表2 還統(tǒng)計了接口重合率,即C 庫的共同接口數(shù)與該C 庫在該項的總接口數(shù)的比值.

    Table 2 APIs Comparison of musl libc and glibc表2 musl libc 和glibc 的接口對比

    結(jié)果顯示,2 個C 庫的主要接口重合率均遠(yuǎn)高于各自的非主要接口重合率(glibc:52.2%和5.6%;musl libc:99.2%和52.1%).這表明C 庫頂層接口的相似度較高,而底層實現(xiàn)區(qū)別較大.此外,glibc 中55%(3 583/6 466)的接口為非主要接口,可見其底層實現(xiàn)十分復(fù)雜,大量的非主要接口將嚴(yán)重影響接口對比結(jié)果的準(zhǔn)確性,對后續(xù)的分析也不利,而只分析主要接口便能避免這個問題.

    musl libc 的主要接口集幾乎完全包含在glibc 的主要接口集中(重合率為99.2%).因此,從主要接口的角度來看,musl libc 可以基本被視為glibc 的子集.這表明musl libc 充分遵從了glibc 的接口命名習(xí)慣,為open-Euler 的C 庫移植和替代工作帶來了很大便利.但同時,musl libc 的主要接口僅覆蓋glibc 主要接口的一半左右(52.2%),這也勢必降低了musl libc 對應(yīng)用軟件的兼容性.

    表3 列出的12 個主要接口是musl libc 獨有的.我們在統(tǒng)計應(yīng)用軟件調(diào)用接口的情況(具體方法見第3 節(jié))后發(fā)現(xiàn),這12 個接口均未被任何應(yīng)用軟件調(diào)用.值得一提的是,接口strlcat 和strlcpy 其實在應(yīng)用軟件中十分常見,雖然glibc 并未實現(xiàn)這2 個接口,但應(yīng)用開發(fā)者仍會想辦法使用它們:有些開發(fā)者將它們實現(xiàn)在自己的鏈接庫中(例如x86_64 的multipathtools-0.8.5-7,strlcpy),有些靜態(tài)鏈接了他們自己編寫的函數(shù)(例如aarch64 的entr-4.5-1,strlcpy).也正因如此,這些應(yīng)用軟件才能夠在glibc 下正確調(diào)用這2 個接口.

    Table 3 Main APIs Owned by musl libc表3 musl libc 獨有的主要接口

    musl libc 相比glibc 有1 379 個主要接口尚未實現(xiàn),但它們的情況與musl libc 獨有的12 個接口截然不同.由于glibc 的廣泛使用,應(yīng)用軟件開發(fā)者一般都遵循glibc 的規(guī)范而進(jìn)行相應(yīng)的編程適配.如果開發(fā)者認(rèn)為glibc 已經(jīng)實現(xiàn)了某個接口,他們大多會選擇直接調(diào)用它而不會再自行實現(xiàn)該接口,因為非標(biāo)準(zhǔn)實現(xiàn)不僅帶來了更大的工作量,而且存在安全性隱患,也不利于代碼復(fù)用和移植.然而,開發(fā)者想要調(diào)用的接口可能是musl libc 未實現(xiàn)的,這便引發(fā)了musl libc 的兼容性問題.

    “接口重合率”是度量兼容性的一種思路.如果將其用于本文的研究,能得到結(jié)論:musl libc 的兼容性是52.2%.然而,這種思路并未考慮被兼容的應(yīng)用軟件所包含的信息.C 庫通過實現(xiàn)接口來為應(yīng)用軟件提供功能支持,而應(yīng)用軟件通過調(diào)用接口來滿足自身的功能需求.在兼容的過程中,主體是C 庫,客體是應(yīng)用軟件,而用接口重合率來度量兼容性的方法僅考慮了主體,而忽略了客體.由此可見,應(yīng)用軟件對C 庫接口的調(diào)用情況也應(yīng)當(dāng)被納入兼容性的度量中.我們將在第4~5 節(jié)中提出了相應(yīng)的算法,更加全面而準(zhǔn)確地度量兼容性,并進(jìn)一步度量了每個缺失API 的優(yōu)先級.

    3 應(yīng)用軟件生態(tài)兼容分析

    應(yīng)用軟件生態(tài)是指系統(tǒng)上可運行的所有應(yīng)用軟件的集合,本文中簡稱為軟件生態(tài)或生態(tài).不同系統(tǒng)的應(yīng)用軟件生態(tài)不同,故C 庫的兼容情況也有區(qū)別.本文研究musl libc 在openEuler 操作系統(tǒng)的4 種軟件生態(tài)中的兼容性,軟件生態(tài)分別為aarch64 服務(wù)器、x86_64 服務(wù)器、aarch64 嵌入式和x86_64 嵌入式.

    openEuler 軟件生態(tài)中的應(yīng)用軟件均可通過RPM(RedHat package manager)格式的軟件包安裝.RPM 包中含有應(yīng)用軟件安裝所需的文件和信息,包括ELF、文檔、協(xié)議等.為提高結(jié)果的準(zhǔn)確性,本文所統(tǒng)計和分析的應(yīng)用軟件生態(tài)均排除了glibc 和musl libc 的基本包與擴(kuò)展包,如表4 所示.

    Table 4 Basic Package and Extended Package of C Libraries表4 C 庫的基本包與擴(kuò)展包

    本節(jié)將介紹C 庫兼容應(yīng)用軟件的定義,并依照此定義分析4 種生態(tài)中的應(yīng)用軟件兼容情況.

    3.1 直接兼容的定義

    兼容的直觀判定標(biāo)準(zhǔn)是,新C 庫能否保證應(yīng)用軟件的全部可執(zhí)行文件正確運行.C 庫無法支持可執(zhí)行文件正確運行的原因有很多,被調(diào)用的接口未實現(xiàn)、實現(xiàn)的功能有缺陷或錯誤、應(yīng)用開發(fā)者編程錯誤、鏈接器有漏洞等都是可能的原因.本文只考慮C庫未實現(xiàn)需要調(diào)用的接口的情況,即只要C 庫實現(xiàn)了應(yīng)用軟件調(diào)用的接口,就認(rèn)為該調(diào)用不會發(fā)生錯誤.另一方面,如果C 庫未實現(xiàn)需要調(diào)用的接口,本文也假設(shè)應(yīng)用軟件開發(fā)者未在別處(如自行開發(fā)的鏈接庫中)實現(xiàn)這些接口(2.3 節(jié)中解釋了這樣假設(shè)的合理性).

    既然C 庫接口不會被自行實現(xiàn),那么應(yīng)用軟件調(diào)用的庫接口便完全依賴C 庫提供.因此,如果C 庫要保證應(yīng)用軟件不出現(xiàn)錯誤,就必須實現(xiàn)應(yīng)用軟件調(diào)用的全部接口.這種“保證”是C 庫對應(yīng)用軟件的直接支持,本文將其稱為直接兼容.

    定義1.C 庫直接不兼容應(yīng)用軟件.如果在該應(yīng)用軟件的RPM 包中存在某個ELF,該ELF 調(diào)用了C庫缺失的接口,則C 庫直接不兼容該應(yīng)用軟件.如果不滿足上述條件,則C 庫直接兼容該應(yīng)用軟件.

    上述的接口“調(diào)用”指的是靜態(tài)調(diào)用,即ELF 的符號表中存在能夠動態(tài)鏈接該接口的條目.提取符號表中動態(tài)鏈接項的符號名,便提取出了所調(diào)用接口的名稱.

    然而,即使“調(diào)用”了C 庫缺失的接口,ELF 運行時也未必會發(fā)生錯誤,因為執(zhí)行流可能并不會經(jīng)過這個接口.例如,某個負(fù)責(zé)崩潰處理功能的接口在符號表中有相應(yīng)的項,但若程序未遇到崩潰,便不會真正調(diào)用它.因此,即使存在對缺失接口的“調(diào)用”,應(yīng)用軟件在運行時也未必出現(xiàn)錯誤.

    本文不考慮動態(tài)調(diào)用引起的偏差,即應(yīng)用軟件對任何C 庫缺失接口的靜態(tài)調(diào)用都會被判定為直接不兼容.事實上,可以充分信任應(yīng)用軟件開發(fā)者的編程能力,從而相信這些極少或從未被真正調(diào)用過的接口并非冗余,而是開發(fā)者希望該應(yīng)用實現(xiàn)的功能(如崩潰處理功能)的一部分,它們的缺失也會使應(yīng)用的正確運行不再得到保證.

    3.2 不兼容的傳遞性

    RPM 包中還記錄著應(yīng)用軟件對其他應(yīng)用軟件的依賴關(guān)系,這種顯式的依賴關(guān)系是功能上的依賴.除此之外,應(yīng)用之間還存在隱性的依賴關(guān)系,例如用戶在使用一個后端應(yīng)用時必須搭配某個前端應(yīng)用才能獲得良好體驗.本文只考慮RPM 包中顯式標(biāo)注的依賴關(guān)系,不考慮其他隱性依賴關(guān)系.

    應(yīng)用軟件的兼容與否和它所依賴的其他應(yīng)用軟件有關(guān).對于某個應(yīng)用軟件,即使它所依賴的應(yīng)用軟件使用C 庫時都能正確運行,它也未必能正確運行,故“應(yīng)用是否被兼容”和“所依賴應(yīng)用是否被兼容”沒有直接關(guān)系.但反之,如果所依賴的應(yīng)用不能正確運行,應(yīng)用軟件本身的正確運行便也無法得到保證,則是一個因果關(guān)系.

    因此,不兼容具有傳遞性,即C 庫如果不兼容某個應(yīng)用軟件,則也不兼容依賴該應(yīng)用軟件的其他應(yīng)用軟件,即使這些應(yīng)用軟件自身是被直接兼容的.圖2 是一個例子:A,B,C,D這4 個應(yīng)用中,C依賴A,D依賴A和B,E依賴C和D,箭頭表示依賴關(guān)系.庫直接兼容應(yīng)用A,C,D,E,直接不兼容B.雖然D被直接兼容,但因為B是直接不兼容的,而D依賴B,所以B的不兼容傳遞到D,D也不被兼容.同理,D再將不兼容性傳遞到E,E也不被兼容.

    Fig.2 Illustration of transitivity of incompatibility圖2 不兼容的傳遞性示意圖

    3.3 兼容的定義

    從3.1 節(jié)的直接兼容和3.2 節(jié)中的不兼容傳遞性出發(fā),可以對C 庫兼容應(yīng)用軟件做出定義.

    定義2.C 庫是否兼容應(yīng)用軟件.

    1)如果C 庫直接不兼容一個應(yīng)用軟件,則C 庫不兼容該應(yīng)用軟件.

    2)如果C 庫不兼容一個應(yīng)用軟件所依賴的某個應(yīng)用軟件,則C 庫不兼容該應(yīng)用軟件.

    3)如果無法通過以上2 條定義證明C 庫不兼容一個應(yīng)用軟件,則C 庫兼容該應(yīng)用軟件.

    定義2是遞歸的.首先有一些應(yīng)用是直接不兼容的,從而依賴它們的應(yīng)用是不兼容的.不兼容性沿著依賴關(guān)系網(wǎng)傳遞,直至所有不兼容的應(yīng)用都被傳遞到,而未被傳遞到的應(yīng)用就是兼容的.

    定義2也是無歧義的.該定義將應(yīng)用軟件嚴(yán)格分為兼容的和不兼容的,不存在一個應(yīng)用可以同時被判定為兼容和不兼容的情況.這是非常重要的,因為模糊的定義將從根本上降低兼容性分析結(jié)果的準(zhǔn)確性.

    3.4 軟件生態(tài)圖

    定義2是自然語言表述的兼容定義,不利于直接用于判定應(yīng)用軟件是否兼容.數(shù)學(xué)化的模型在判定時將更為有效.

    應(yīng)用軟件之間的依賴關(guān)系存在方向性.由此,可以將整個軟件生態(tài)視為一張有向圖,應(yīng)用軟件與圖中的點一一對應(yīng),而依賴關(guān)系與圖中的有向邊也一一對應(yīng).我們把這樣的圖模型稱為軟件生態(tài)圖.

    定義3.軟件生態(tài)圖.它是一張表示軟件生態(tài)中的應(yīng)用軟件及其之間依賴關(guān)系的有向圖.圖中的每個點對應(yīng)生態(tài)中的一個應(yīng)用軟件,每條邊對應(yīng)一個依賴關(guān)系,邊的方向規(guī)定為:應(yīng)用A依賴應(yīng)用B,對應(yīng)從A指向B的邊.

    在軟件生態(tài)圖中,我們把被兼容的應(yīng)用稱為兼容點,不被兼容的應(yīng)用稱為不兼容點,同理也有直接兼容點和直接不兼容點.我們提出定義2 在軟件生態(tài)圖模型下的一個等價定義,并證明其等價性.

    定義4.軟件生態(tài)圖中的不兼容點.它是那些可通過圖中的路徑到達(dá)直接不兼容點的結(jié)點(路徑長度可以為0),即

    其中Sdi是直接不兼容(directly incompatible)的結(jié)點集,(v,vn,vn1,…,v1,v0)表示從v經(jīng)過vn,vn-1,…,v1到v0的路徑.

    定義4與定義2 的等價性證明為:

    1)對于可通過一條路徑到達(dá)直接不兼容點的點,如果這條路徑長度為0,則該點是直接不兼容點,當(dāng)然也是不兼容點;否則,可以將該點記為a,路徑記為(a,an,an-1, …,a1,a0),n≥0,a0是直接不兼容點.根據(jù)定義2,a0是不兼容點,a1因為依賴了不兼容點a0,也是不兼容點.反復(fù)進(jìn)行推理可知,a1, …,an-1,an,a都是不兼容點.

    2)對于一個不兼容點b,現(xiàn)在要找到一條從它到某個不兼容點的路徑.根據(jù)定義2 第3 條,一定存在證明b是不兼容點的方法.也就是說,通過某種方法運用定義2 的第1 條和第2 條,最終可以推導(dǎo)出b不兼容.如果運用了定義2 的第1 條,即b是直接不兼容點,則長度為0 的路徑即為所求;否則,它依賴另一個不兼容點(第2 條),即存在從它到另一個不兼容點b0的邊.如果b0是直接不兼容點,則證明完成;否則,又存在b0到另一個不兼容點b1的邊.反復(fù)進(jìn)行這樣的推理,如果一直沒有訪問直接不兼容點,將不斷訪問b,b0,b1, …點序列,點序列與推理過程是一一對應(yīng)的.也就是說,既然存在b是不兼容點的證明方法,就存在相應(yīng)的點序列.可以認(rèn)為證明方法對應(yīng)的點序列是無重復(fù)的(序列中每個點都是不同的),因為出現(xiàn)重復(fù)點意味著推理過程遍歷了一個環(huán),而這又意味著循環(huán)論證.循環(huán)論證本身不能作為證明方法,故最終還是需要從某個點跳出這個環(huán)才能完成證明,故不妨第一次訪問“跳出點”時就跳出,訪問過程便沒有了環(huán).又由于圖中點的個數(shù)有限,故無重復(fù)的點序列只能是有限長度的,因而可以把證明方法對應(yīng)的點序列記作b,b0,b1, …,bn,n≥0.這表明,整個推理過程只會重復(fù)有限次便停止在bn,而推理停止的唯一原因為bn是直接不兼容點.(b,b0,b1, …,bn)就是所求路徑.

    根據(jù)定義4,只要遍歷某個應(yīng)用結(jié)點的所有無環(huán)路徑,就可以判定該應(yīng)用是否被兼容.

    3.5 應(yīng)用軟件生態(tài)兼容分析結(jié)果

    表5 展示了openEuler 的4 種軟件生態(tài)的musl libc 兼容情況,其中第n級不兼容數(shù)的含義為在第n輪傳遞后新增加的不兼容應(yīng)用個數(shù),兼容率為被兼容的應(yīng)用個數(shù)占全部應(yīng)用個數(shù)的比例.

    Table 5 Statistics of Compatible Applications in the Four Ecosystems表5 4 種生態(tài)中的兼容的應(yīng)用軟件統(tǒng)計

    比較表5 中數(shù)據(jù)發(fā)現(xiàn),C 庫在相同應(yīng)用場景(服務(wù)器或嵌入式)、不同體系結(jié)構(gòu)下有著相近的直接兼容率和不兼容傳遞模式,而在相同體系結(jié)構(gòu)、不同應(yīng)用場景下數(shù)據(jù)的差異很大:服務(wù)器場景中兼容率分別為31.89%和31.87%,其各級不兼容傳遞的應(yīng)用個數(shù)分別為537/547,6 936/6 985,4 721/4 727,198/190,7/10;嵌入式場景中兼容率分別為45.24%和44.58%,其各級不兼容傳遞的應(yīng)用個數(shù)分別為33/33,13/13.而在不同應(yīng)用場景下,兼容率的差值分別為13.35%(aarch64)和12.71%(x86_64),不兼容傳遞模式也有明顯區(qū)別.

    這表明,軟件生態(tài)兼容情況受應(yīng)用場景的影響很明顯,而受硬件體系結(jié)構(gòu)的影響很微弱.

    4 兼容性算法

    兼容性的度量是許多系統(tǒng)開發(fā)者的需求,而好的度量方法是獲得優(yōu)質(zhì)度量結(jié)果的關(guān)鍵所在.

    3.5 節(jié)中提到的兼容率是一種樸素的度量方法,它基于一個簡單的數(shù)學(xué)原理——計數(shù).每個應(yīng)用軟件都在計數(shù)時被同等地視作“1”,兼容應(yīng)用的個數(shù)和所有應(yīng)用的個數(shù)的比值就是度量結(jié)果.因此,兼容率不能體現(xiàn)不同應(yīng)用軟件之間的差別.

    應(yīng)用軟件在生態(tài)中的重要性并不等同,這種差異體現(xiàn)在:

    1)系統(tǒng)用戶的角度.生態(tài)中的一些應(yīng)用提供的功能十分基礎(chǔ),很多其他應(yīng)用都依賴有基礎(chǔ)功能的應(yīng)用,這些“基礎(chǔ)應(yīng)用”往往存在于不同用戶所使用的應(yīng)用軟件的交集中.例如,所有的Python 擴(kuò)展包都需要Python 解釋器來運行,故Python 解釋器便時常存在于交集中.用戶樂于身處能滿足他們個性化需求的軟件生態(tài)中,而這源于基礎(chǔ)應(yīng)用對生態(tài)中其他應(yīng)用的廣泛支持.對整個用戶群體而言,基礎(chǔ)應(yīng)用正常工作時的收益和崩潰時的損失都比其他應(yīng)用更大,這便是應(yīng)用重要性差異的體現(xiàn).

    2)應(yīng)用軟件開發(fā)者的角度.應(yīng)用軟件開發(fā)者大多選擇以那些已經(jīng)廣泛支持其他應(yīng)用的應(yīng)用為基礎(chǔ),開發(fā)自己的應(yīng)用軟件,因為基礎(chǔ)應(yīng)用的功能豐富,正確性和安全性得到廣泛的實踐驗證,一般能得到持續(xù)穩(wěn)定的維護(hù),從而使得開發(fā)工作更加便捷、產(chǎn)品穩(wěn)定性更佳、產(chǎn)品便于和其他應(yīng)用互通或適配,等等.這些優(yōu)勢使得開發(fā)者的產(chǎn)品更受用戶青睞,而這又促使更多開發(fā)者在這些基礎(chǔ)應(yīng)用之上開展工作,形成以基礎(chǔ)應(yīng)用為中心、其他應(yīng)用對其依賴的生態(tài)結(jié)構(gòu),這是應(yīng)用重要性差異的又一體現(xiàn).

    本節(jié)基于3.4 節(jié)中的軟件生態(tài)圖模型,提出了利用PackageRank 算法計算應(yīng)用軟件的重要性和C 庫的兼容性,以在兼容性度量時體現(xiàn)重要性差異.

    4.1 影響應(yīng)用軟件重要性的因素

    應(yīng)用軟件之間的依賴關(guān)系能反映其重要性差異.不論是從系統(tǒng)用戶還是應(yīng)用軟件開發(fā)者的角度,依賴關(guān)系都和應(yīng)用軟件重要性有著緊密的聯(lián)系.

    被大量應(yīng)用軟件依賴的應(yīng)用軟件相對更加重要.然而,把被依賴次數(shù)當(dāng)作應(yīng)用軟件的重要性也有失偏頗,如某個“只被一個很重要的應(yīng)用依賴”的應(yīng)用可能比“被多個很不重要的應(yīng)用依賴”的應(yīng)用更重要,因為它事關(guān)生態(tài)中的重要應(yīng)用軟件的正常運行.

    綜上所述,應(yīng)用軟件的重要性受2 種因素影響:

    1)被其他應(yīng)用依賴的次數(shù);

    2)依賴它的應(yīng)用的重要性.

    4.2 PackageRank 算法

    PackageRank 算法是本文提出的兼容性度量算法.該算法分為2 個部分:計算應(yīng)用軟件的重要性、計算C 庫的兼容性.

    4.2.1 計算應(yīng)用軟件的重要性

    PackageRank 算法同時考慮了4.1 節(jié)所述的影響應(yīng)用軟件重要性的2 種因素.它的思想基于Page 等人[21]提出的PageRank 算法,即PageRank 算法應(yīng)用于代表互聯(lián)網(wǎng)的有向圖中,而PackageRank 算法則是將其應(yīng)用到軟件生態(tài)圖.

    圖3 展示了經(jīng)過簡化的PackageRank 算法,它是一個迭代過程:每個結(jié)點將它現(xiàn)有的得分沿所有“出邊”平均分發(fā),并將所有“入邊”的得分求和,作為新一輪迭代之前的得分.本文將PackageRank 算法經(jīng)過多次迭代得到的穩(wěn)定結(jié)果作為應(yīng)用軟件的重要性度量值.

    Fig.3 Illustration of PackageRank algorithm圖3 PackageRank 算法示意圖

    Package Rank 算法的含義是:

    1)“入邊得分求和”使得被更多應(yīng)用依賴的應(yīng)用因為有更多得分來源而獲得更高得分;

    2)“出邊平均分發(fā)”使得被更高得分的應(yīng)用依賴的應(yīng)用能獲得更高得分.

    由此可見,PackageRank 算法兼顧了影響應(yīng)用軟件重要性的2 個因素.

    簡化的PackageRank 存在2 個問題,Page 等人[21]將它們分別稱為排序沉沒(rank sink)和懸鏈接(dangling link),本文也采用這2 個稱呼.

    1)排序沉沒.軟件生態(tài)圖中可能存在環(huán),即應(yīng)用之間可以環(huán)形依賴.當(dāng)環(huán)中的全部應(yīng)用都被兼容時,它們都能正確運行,否則便都不能正確運行.如果存在指向環(huán)中某個點的邊,所有的點又均沒有指向環(huán)外其他點的邊,則得分可以進(jìn)入環(huán)但不能排出,從而在環(huán)中無限積累,如圖4 所示.可能存在1 個或多個這樣的環(huán),而不在這些環(huán)內(nèi)的點最終都將沒有得分.

    Fig.4 Illustration of rank sink圖4 排序沉沒示意圖

    2)懸鏈接.有些應(yīng)用不依賴任何其他應(yīng)用,即它對應(yīng)的點在軟件生態(tài)圖中沒有出邊.在迭代過程中,賦予這些點的分?jǐn)?shù)將從圖中泄漏,如圖5 所示.

    為了解決排序沉沒和懸鏈接,算法在每次迭代后令每個結(jié)點都“流失”一定比例的得分,同時向所有結(jié)點補(bǔ)充分配分?jǐn)?shù)以維持總得分恒定.其中,得分流失和補(bǔ)充使得所有得分不會全部流入閉環(huán)中,而得分補(bǔ)充還可以補(bǔ)足因懸鏈接而泄漏的得分.

    考慮到上述問題和解決方法,我們把由Package-Rank 計算的應(yīng)用軟件重要性定義.

    定義5.應(yīng)用軟件的重要性.重要性度量結(jié)果為向量R,滿足:

    其中R(i)是應(yīng)用i的得分,流失因子ε <1,Bi是依賴應(yīng)用i的應(yīng)用軟件集合,E是重新分配和補(bǔ)充得分的方法,并且通過方法E來保持‖R‖1=1,E(i)是為應(yīng)用i補(bǔ)充的得分的初值(或稱為補(bǔ)充方案,εE(i)是真實的補(bǔ)充值).

    可以根據(jù)軟件生態(tài)圖構(gòu)造矩陣An×n(n是生態(tài)中應(yīng)用的個數(shù)):將所有應(yīng)用軟件編號為1~n.對于1≤i≤n和1≤j≤n,如果應(yīng)用i被應(yīng)用j依賴,則Aij= 1 /Nj,Nj是應(yīng)用j依賴的應(yīng)用個數(shù)(點j的出度);否則Aij=0.算法收斂后的向量R(第i維上的值是應(yīng)用i的得分)滿足R=AR.An×n稱為依賴關(guān)系矩陣.

    算法1 展示了PackageRank 計算應(yīng)用軟件重要性的過程.

    算法1.PackageRank 計算應(yīng)用軟件重要性R.

    初始向量R0可以是任何滿足‖R‖1=1的向量,它并不影響最終收斂時的結(jié)果.本文采用等值向量作為初始向量,即

    流失因子ε的大小會影響算法的計算結(jié)果.如果ε過大,依賴關(guān)系網(wǎng)在算法中的作用將被減弱,導(dǎo)致結(jié)果不準(zhǔn)確;如果過小,算法收斂速度更慢.Page 等人[21]建議ε=0.15,以表征網(wǎng)絡(luò)用戶隨機(jī)跳轉(zhuǎn)訪問網(wǎng)頁的概率;而由于ε在此處僅為避免排序沉沒,選取的值太大將帶來較大誤差,故本文設(shè)定ε=0.001.重新補(bǔ)充分配得分的方法是平均分配,這是因為open Euler 缺乏其他與應(yīng)用軟件相關(guān)的統(tǒng)計數(shù)據(jù)或信息.

    圖6 展示了排名前N的應(yīng)用軟件重要性(PackageRank 得分)之和隨N的變化曲線.相同應(yīng)用場景、不同體系結(jié)構(gòu)的軟件生態(tài)得到了形狀相似的結(jié)果曲線,但不同應(yīng)用場景的結(jié)果有明顯差異,這和第3 節(jié)中兼容分析的結(jié)論是相同的.

    Fig.6 Importance of applications computed by PackageRank圖6 PackageRank 計算的應(yīng)用軟件重要性

    不同應(yīng)用軟件的重要性得分差距很大,少量的應(yīng)用聚集了大量的重要性得分,同時很大一部分應(yīng)用的得分是極小的.圖6(a)(b)顯示,服務(wù)器生態(tài)中7 個應(yīng)用的重要性得分之和已經(jīng)達(dá)到全部應(yīng)用的25%,28 個應(yīng)用達(dá)到了50%,近800 個達(dá)到了75%,而生態(tài)中共有1.8 萬余個應(yīng)用軟件;嵌入式生態(tài)的得分分布相對更加均衡,但也存在明顯的差距.

    這一軟件生態(tài)的特點符合自然界生態(tài)系統(tǒng)的規(guī)律.少數(shù)食物鏈頂端的物種能得到大量的能量輸入,在系統(tǒng)中也更具支配性;而底端的低級生物只能靠更多的數(shù)量來維持平衡.軟件生態(tài)和自然界生態(tài)系統(tǒng)的發(fā)展過程有所相似,依賴關(guān)系網(wǎng)和食物鏈網(wǎng)也是類似的結(jié)構(gòu),而PackageRank 的結(jié)果也正是自然界的生態(tài)規(guī)律在軟件生態(tài)中的延伸,這體現(xiàn)了算法的合理性.此外,嵌入式生態(tài)中的得分分布更為均衡的原因則是其生態(tài)規(guī)模更小、復(fù)雜度更低,重要的應(yīng)用不能積累足夠的分?jǐn)?shù)而與其他應(yīng)用拉開差距.

    4.2.2 計算C 庫的兼容性

    兼容性的度量方法應(yīng)當(dāng)體現(xiàn)應(yīng)用軟件重要性的差異.C 庫兼容更重要的應(yīng)用軟件,對生態(tài)的積極作用更顯著,C 庫的兼容性便得到更大幅度的提升;C庫不兼容重要應(yīng)用,對生態(tài)造成的破壞也更大,兼容性將受到更大的影響.因此,通過對被兼容應(yīng)用的重要性評價(PackageRank 得分)來計算兼容性是十分合適的.

    雖然PackageRank 為每個應(yīng)用軟件輸出一個確定的得分,但如果將所有應(yīng)用軟件的得分縮放同樣的比例,得到的結(jié)果仍是穩(wěn)定的.通過改變定義5 中‖R‖1的值,就能實現(xiàn)得分的縮放.因此,得分的比值更具意義,它反映的是生態(tài)中各個應(yīng)用的“相對重要性”.這個屬性是應(yīng)用軟件生態(tài)的固有屬性,與得分的縮放無關(guān).我們采用所有被兼容應(yīng)用的重要性得分之和與全部應(yīng)用得分之和的比值來度量C 庫的兼容性.由于‖R‖1=1,故只需將所有被兼容應(yīng)用的得分求和便能得到這個比值.

    定義6.C 庫在軟件生態(tài)內(nèi)的兼容性.兼容性定義為所有被兼容應(yīng)用的重要性得分之和與全部應(yīng)用得分之和的比值,即為所有被兼容應(yīng)用的得分之和.

    表6 展示了musl libc 在openEuler 的4 種生態(tài)中的兼容性度量結(jié)果.

    Table 6 Compatibility of musl libc表6 musl libc 的兼容性%

    不同應(yīng)用場景的兼容性差別很大,而體系結(jié)構(gòu)對兼容性的影響很小.嵌入式生態(tài)的C 庫兼容性較服務(wù)器生態(tài)高出26%左右,而實際情況也確實如此,即嵌入式生態(tài)的應(yīng)用多為主流應(yīng)用,它們更多地調(diào)用常用的API,而缺失API 普遍是不常用且功能特殊的,因此應(yīng)用軟件調(diào)用缺失API 的概率更低.

    至此,我們發(fā)現(xiàn)musl libc 對應(yīng)用軟件的兼容性仍有很大的提升空間,在替換前需要進(jìn)一步補(bǔ)全開發(fā)工作.

    5 缺失API 優(yōu)先級算法

    C 庫的開發(fā)者不僅需要了解C 庫的兼容性,而且更需要獲知缺失API 的優(yōu)先級,以便按序進(jìn)行補(bǔ)全.

    缺失API 的優(yōu)先級差異體現(xiàn)在兼容性價值上:C庫通過補(bǔ)全API 而兼容更多應(yīng)用軟件運行,不同API被應(yīng)用軟件調(diào)用的情況有差別,應(yīng)用軟件的重要性又有差別,從而補(bǔ)全不同的API 對生態(tài)的兼容性價值也有高低之分.

    本節(jié)提出了有接口的軟件生態(tài)圖模型,并在該模型上提出了APIRank 算法以度量缺失API 優(yōu)先級,然后按照優(yōu)先級次序進(jìn)行了API 補(bǔ)全模擬.

    5.1 影響缺失API 優(yōu)先級的因素

    與4.1 節(jié)類似,缺失API 的優(yōu)先級也受多重因素的影響.被大量應(yīng)用軟件調(diào)用的缺失API 應(yīng)優(yōu)先實現(xiàn),以滿足眾多應(yīng)用的功能需求;重要的應(yīng)用軟件調(diào)用的缺失API 應(yīng)優(yōu)先實現(xiàn),以保證重要應(yīng)用的正常運行.此外,如果一個應(yīng)用軟件調(diào)用的缺失API 數(shù)量過多,要兼容該應(yīng)用就需要大量的工作,兼容性提升效率降低,且開發(fā)過程不易調(diào)試[21],故這些API 的優(yōu)先級降低.因此,缺失API 的優(yōu)先級受3 種因素的影響:

    1)調(diào)用它的應(yīng)用軟件的數(shù)量;

    2)調(diào)用它的應(yīng)用軟件的重要性;

    3)調(diào)用它的應(yīng)用軟件所調(diào)用的缺失API 總數(shù).

    5.2 APIRank 算法

    為綜合考慮5.1 節(jié)所述的3 個因素,我們基于軟件生態(tài)圖和PackageRank 算法作進(jìn)一步延伸,提出了有接口的軟件生態(tài)圖模型和APIRank 算法以度量缺失API 的優(yōu)先級.

    在軟件生態(tài)圖中,應(yīng)用軟件之間的依賴關(guān)系對應(yīng)著圖中的有向邊.這種將依賴關(guān)系模型化的思路在有接口的軟件生態(tài)圖中得到了延續(xù).應(yīng)用軟件對API 的調(diào)用可以被視作一種廣義的“依賴”關(guān)系.應(yīng)用軟件“依賴”API,正如應(yīng)用軟件依賴其他應(yīng)用一樣.依照這個思路,可以構(gòu)造一張由應(yīng)用軟件和缺失API 共同組成的有向圖,并根據(jù)廣義依賴關(guān)系在圖中連接對應(yīng)的邊.我們把這樣的有向圖稱為有接口的軟件生態(tài)圖.

    定義7.有接口的軟件生態(tài)圖.它是一張表示軟件生態(tài)中應(yīng)用軟件和缺失API 及其之間廣義依賴關(guān)系的有向圖.圖中的每個點對應(yīng)生態(tài)中的一個應(yīng)用軟件或一個缺失API,每條邊對應(yīng)一個廣義依賴關(guān)系,邊的方向規(guī)定為:應(yīng)用A依賴應(yīng)用B,對應(yīng)一條從A指向B的邊;應(yīng)用C調(diào)用缺失APID,對應(yīng)一條從C指向D的邊.

    算法1 中的PackageRank 的計算過程同樣可以用于有接口的軟件生態(tài)圖,收斂后圖中每個結(jié)點也會有一個穩(wěn)定的得分.本文將收斂后代表缺失API 的結(jié)點的得分視為缺失API 的優(yōu)先級,這個算法稱為APIRank,如圖7 所示,它是圖4 添加了缺失的API 而生成的.

    Fig.7 Illustration of APIRank圖7 APIRank 示意圖

    APIRank 算法的含義是:

    1)被更多應(yīng)用軟件調(diào)用的缺失API 有更多的分?jǐn)?shù)來源,從而獲得更高的分?jǐn)?shù);

    2)更重要的應(yīng)用有更高的分?jǐn)?shù),它調(diào)用的缺失API 也能獲得更高的分?jǐn)?shù);

    3)調(diào)用多個缺失API 的應(yīng)用有更多的出邊,每個缺失API 能從出邊獲得的分?jǐn)?shù)更低.

    由此可見,APIRank 算法兼顧了影響接口優(yōu)先級的3 個因素.

    同樣地,可以根據(jù)有接口的軟件生態(tài)圖構(gòu)造矩陣A(n+m)×(n+m)(n是應(yīng)用個數(shù),m是缺失API 個數(shù)):所有應(yīng)用編號為1~n,所有缺失API 編號為n+1~n+m.對于1≤i≤n+m和1≤j≤n+m,如果點j有指向點i的邊,則Aij= 1 /Nj,Nj是點j的出度;否則Aij= 0.A(n+m)×(n+m)稱為廣義依賴關(guān)系矩陣.

    算法2 展示了APIRank 計算缺失API 優(yōu)先級的過程.

    算法2.APIRank 計算缺失API 優(yōu)先級.

    同樣地,APIRank 也采用等值向量作為初始向量,流失因子ε=0.001.

    根據(jù)缺失API 的得分R的高低,可以對其優(yōu)先級進(jìn)行排序.

    5.3 接口補(bǔ)全模擬

    我們模擬了按照缺失API 優(yōu)先級排序進(jìn)行補(bǔ)全時,musl libc 兼容性隨著每個API 的補(bǔ)全而逐步提升的過程,如圖8 所示.

    Fig.8 Increase of compatibility in simulations process of API complementation圖8 API 補(bǔ)全模擬過程中兼容性的提升過程

    圖8 的結(jié)果顯示,musl libc 兼容性的提升呈階梯型,這是因為在開發(fā)過程中往往需要實現(xiàn)多個API才能兼容某一個應(yīng)用軟件,而該應(yīng)用軟件的兼容能夠(或許會大幅度地)提升C 庫的兼容性.同一應(yīng)用場景、不同體系結(jié)構(gòu)的兼容性提升過程相似,而不同應(yīng)用場景的過程區(qū)別較大,這也完全符合我們的預(yù)期.

    注意到,當(dāng)C 庫達(dá)到完全兼容(兼容性為100%)時,并非所有的缺失API 均已被補(bǔ)全,即代表完全兼容的點的橫坐標(biāo)值均小于表2 中的主要接口缺失總數(shù)(1 379).這表明有些缺失API 未被生態(tài)中的任何應(yīng)用軟件調(diào)用.根據(jù)本文對兼容的定義,這些缺失API 沒有對應(yīng)用軟件生態(tài)提供任何有效的兼容支持,目前并不需要補(bǔ)全它們就能達(dá)到完全兼容,它們也不包含在有接口的軟件生態(tài)圖中,從而不存在APIRank 算法得分(無優(yōu)先級).

    圖9 展示了被調(diào)用和未被調(diào)用的缺失API 數(shù)量和占比.我們發(fā)現(xiàn)未被調(diào)用的API 所占的比例很高:嵌入式生態(tài)中有95.9%的缺失接口未被應(yīng)用軟件調(diào)用過;服務(wù)器生態(tài)中,aarch64 和x86_64 的數(shù)據(jù)分別是85.3%和85.1%.API 未被任何應(yīng)用軟件調(diào)用,一般是因為其功能過于特殊而缺乏實用場景,或存在與其功能類似但更受應(yīng)用開發(fā)者喜愛(性能更好,更符合編程習(xí)慣等原因)的其他API.嵌入式生態(tài)的比例比服務(wù)器生態(tài)低10%,而這也和嵌入式生態(tài)的兼容性更高(見表6)相呼應(yīng).

    Fig.9 Proportion of called missing API and not called missing API圖9 被調(diào)用和未被調(diào)用的缺失API 占比

    openEuler 的C 庫開發(fā)者當(dāng)前無需擔(dān)心這些未被調(diào)用的API 會帶來兼容性問題.而且,目前未被調(diào)用的API 短期內(nèi)也很可能不會被應(yīng)用軟件的開發(fā)者使用,因此C 庫開發(fā)者有較長的時間來逐一補(bǔ)全它們(如果需要),同時該C 庫又能不受影響地提供服務(wù).

    6 評 估

    本節(jié)評估了PackageRank 算法和APIRank 算法的效果,分析算法誤差,對比其他現(xiàn)有算法,展望算法的延伸,以及闡明本文研究的局限.

    6.1 算法效果

    6.1.1 PackageRank 算法效果

    PackageRank 算法的評估采用aarch64 體系結(jié)構(gòu)的結(jié)果作為例子.表7 給出了在aarch64 的2 種應(yīng)用場景下PackageRank 得分排名較高的應(yīng)用的分值.為了更清晰地顯示結(jié)果,表7 中的得分是經(jīng)過等比例放大的,這樣的放大并不影響算法結(jié)果的穩(wěn)定和準(zhǔn)確.

    Table 7 Statistics of High-ranked Applications of PackageRank in aarch64表7 aarch64 體系結(jié)構(gòu)下PackageRank 高優(yōu)先級應(yīng)用的統(tǒng)計

    PackageRank 考慮了影響應(yīng)用軟件重要性的2 個因素:被依賴次數(shù)、依賴應(yīng)用的重要性.由表7 可知,這2 個因素實際都對結(jié)果產(chǎn)生了影響.服務(wù)器生態(tài)中,bash,texlive-base 都既被大量應(yīng)用依賴(入邊數(shù)很高),又被高分應(yīng)用依賴并獲得了大量得分(最大入邊分?jǐn)?shù)高,最大入邊分?jǐn)?shù)來源的分?jǐn)?shù)和排名高);texlivekpathsea 是典型的僅因大量應(yīng)用依賴而積累出高分的例子,有3 190 個依賴它的應(yīng)用,但其中最高得分的應(yīng)用也僅排名65;ncurses-base 則完全因為高分應(yīng)用的依賴才成為了排名第3 的應(yīng)用,它只有2 個依賴者,而其中ncurse-libs 為它輸送了96.9%(3 487.70/3 598.00)的高額分?jǐn)?shù).嵌入式生態(tài)中,bash 受2 種因素影響而排名第1,zlib,libselinux 主要因為被依賴次數(shù)高,而libsepol 則主要因為從libselinux(排名第4)處獲得大量分?jǐn)?shù)而排在第3 位.

    此外,服務(wù)器生態(tài)中的perl-libs 和perl-Exporter存在雙向依賴,這是排序沉沒問題出現(xiàn)的例子,在算法中已經(jīng)解決了這個問題(4.2 節(jié)).

    應(yīng)當(dāng)指出,平均入邊分?jǐn)?shù)與入邊數(shù)的乘積并不等于得分,而是約等于得分減1(存在微小誤差).這是因為PackageRank 在迭代時對每個點進(jìn)行了等額的得分補(bǔ)充(4.2 節(jié)).補(bǔ)充的得分并不來自入邊,而表7 中的得分就是將這部分補(bǔ)充的得分縮放為1.00后的結(jié)果.

    上述分析表明PackageRank 算法有效地實現(xiàn)了對應(yīng)用軟件重要性的多重影響因素的兼顧.

    6.1.2 APIRank 算法效果

    APIRank 算法的評估采用x86_64 體系結(jié)構(gòu)的結(jié)果作為例子.表8 列出了在x86_64 的2 種應(yīng)用場景下APIRank 算法中優(yōu)先級較高的API 的分值.

    Table 8 Statistics of High-ranked APIs of APIRank in x86_64表8 x86_64 體系結(jié)構(gòu)下APIRank 高優(yōu)先級API 的統(tǒng)計

    服務(wù)器生態(tài)中,應(yīng)用軟件的高分對其所調(diào)用的缺失API 的優(yōu)先級提升作用明顯:PackageRank 中排名第1 的coreutils 調(diào)用了6 個缺失API,它們均排在前7 名中.另一方面,被大量應(yīng)用軟件調(diào)用也能提升API 優(yōu)先級,fcntl64 有遠(yuǎn)超其他API 的被調(diào)用數(shù)(入邊數(shù)),這也使得它排在第2 名.另外一個例子則能體現(xiàn)這2 個因素對優(yōu)先級的共同影響:dlvsym 和argz_add 得分接近,但分別主要受被調(diào)用數(shù)和調(diào)用者重要性的因素影響,表明在不同主要因素影響下缺失API 也能得到相近的分?jǐn)?shù).

    嵌入式生態(tài)結(jié)構(gòu)比較簡單,且其應(yīng)用軟件調(diào)用的缺失API 數(shù)量更少,因此API 優(yōu)先級得分比較接近,但仍能看出多個因素共同影響優(yōu)先級的效果.特別地,mallinfo 和obstack_vprintf 的得分接近,前者的被調(diào)用數(shù)和調(diào)用者最高得分都更高(3 對1,3.26 對1.00),但其調(diào)用者(e2fsprogs)所調(diào)用的總?cè)笔PI 數(shù)更多(4 個,另外1 條出邊是應(yīng)用依賴關(guān)系),故其得分與后者接近,這體現(xiàn)了第3 個因素對結(jié)果的影響.

    上述分析表明APIRank 算法有效地實現(xiàn)了對缺失API 優(yōu)先級的多重影響因素的兼顧.

    6.2 算法誤差

    本文算法的誤差有2 個來源:

    1)流失因子ε和得分補(bǔ)充.本文中ε=0.001,得分補(bǔ)充方法為平均分配,因此在每輪迭代后有0.1%的分?jǐn)?shù)從各個結(jié)點中流失,并平均分配到所有結(jié)點.因此,兼容性誤差在0.1%以內(nèi);缺失API 優(yōu)先級的數(shù)值存在誤差,但排序不存在誤差,即按比例流失和平均分配不影響得分之間的大小關(guān)系.

    2)收斂極限的設(shè)定.本文收斂極限設(shè)定為“迭代向量差的2-范數(shù)不超過10-5”,因此兼容性的誤差在0.001%以內(nèi),缺失API 優(yōu)先級的平均誤差在10-7以內(nèi).

    綜上,兼容性誤差在0.1%以內(nèi),缺失API 優(yōu)先級的平均誤差在10-7以內(nèi).由于在4 種生態(tài)內(nèi)的所有缺失API 的優(yōu)先級得分均高于10-5,故APIRank 的平均誤差低于1%.

    6.3 算法對比

    第4 節(jié)提出了本文的兼容性算法PackageRank,而1.3 節(jié)中也提到了其他2 種兼容性度量方法.

    1)算法A:已實現(xiàn)的API 個數(shù);

    2)算法B:文獻(xiàn)[2]的加權(quán)完整性.

    算法A的度量方式因缺乏應(yīng)用軟件所包含的信息而不準(zhǔn)確,在本節(jié)中不再討論.

    算法B是將其他系統(tǒng)與Ubuntu 15.04 作比較,或模擬將系統(tǒng)構(gòu)件安裝在Ubuntu 15.04 上并研究其兼容性.之所以選擇Ubuntu 15.04 為基準(zhǔn)系統(tǒng),是因為它是“管理良好的、廣泛支持應(yīng)用軟件的、統(tǒng)計軟件包安裝數(shù)據(jù)的Linux 發(fā)行版”.文獻(xiàn)[2]統(tǒng)計API 調(diào)用情況時使用Ubuntu 的RPM 包,API 重要性和加權(quán)完整性的計算也均采用Ubuntu 的安裝次數(shù)統(tǒng)計.

    我們認(rèn)為算法B不適用于openEuler 對musl libc兼容性分析的原因是:

    1)openEuler 的應(yīng)用軟件生態(tài)與Ubuntu 有區(qū)別,RPM 包的內(nèi)容也有所不同;

    2)openEuler 不具備像Ubuntu 一樣完備的應(yīng)用軟件安裝記錄;

    3)應(yīng)用軟件的安裝并非獨立事件,而是存在互相依賴關(guān)系.

    表9 列出了通過各種算法計算的musl libc 兼容性.其中,“算法B”一欄是文獻(xiàn)[2]給出的度量結(jié)果,而“算法B*”一欄是將算法B的基準(zhǔn)系統(tǒng)設(shè)定為open-Euler 得到的結(jié)果.由于不具備安裝次數(shù)統(tǒng)計,我們在算法B*中將下載次數(shù)設(shè)為相同.按照算法2 的定義,此時計算的兼容性值即為應(yīng)用軟件的兼容率.如第4節(jié)所言,兼容率不能準(zhǔn)確地反映兼容性,因此在缺乏數(shù)據(jù)統(tǒng)計時,本文提出的兼容性算法比算法B更為準(zhǔn)確.

    對比其他算法,本文提出的PackageRank 算法的優(yōu)勢和特點在于:

    1)為系統(tǒng)提供從自身應(yīng)用軟件生態(tài)出發(fā)的、個性化的兼容性評估.不同系統(tǒng)能夠搭載的應(yīng)用軟件范圍(即生態(tài))不同(Ubuntu/Debian 生態(tài)中有30 976 個應(yīng)用[2],openEuler x86_64 服務(wù)器生態(tài)有18 288 個,open-Euler x86_64 嵌入式生態(tài)有83 個),很難為多種多樣的系統(tǒng)確定統(tǒng)一的“基準(zhǔn)生態(tài)”.本文的算法以每種系統(tǒng)或構(gòu)件各自的應(yīng)用軟件生態(tài)信息作為輸入,反映API 在其真實應(yīng)用場景的兼容性,為開發(fā)者提供準(zhǔn)確的、個性化的評估結(jié)果.

    2)適用于缺乏應(yīng)用軟件安裝統(tǒng)計的系統(tǒng).包括openEuler 在內(nèi)的大多數(shù)操作系統(tǒng)的發(fā)行版都不具備像Ubuntu/Debian 一樣完備的應(yīng)用軟件安裝記錄.即使存在統(tǒng)計數(shù)據(jù),如果數(shù)據(jù)量不足而不能視為滿足“大數(shù)定律”,那么“用頻率估計概率”也并不準(zhǔn)確.在統(tǒng)計數(shù)據(jù)缺失時,本文提出的算法既能夠利用有限的信息,又能緊密結(jié)合API 的調(diào)用情況,準(zhǔn)確地度量兼容性.算法所需的信息僅是應(yīng)用軟件的RPM 包.對于大多數(shù)系統(tǒng)而言,它們的生態(tài)中應(yīng)用軟件的RPM包都是完整且容易獲取的.

    APIRank 的優(yōu)勢和特點除包含前述內(nèi)容外還有:面向仍有開發(fā)需求的系統(tǒng)和構(gòu)件,為API 的補(bǔ)全實現(xiàn)工作提供幫助.現(xiàn)有研究大多面向已經(jīng)完整實現(xiàn)的系統(tǒng)和構(gòu)件,分析已有API,而本文的算法僅度量缺失API 的優(yōu)先級,為仍需開發(fā)的系統(tǒng)和構(gòu)件提供補(bǔ)全順序的建議.本文算法并非為Linux API 的全局現(xiàn)狀和生態(tài)環(huán)境做分析,而是為系統(tǒng)和構(gòu)件開發(fā)者提供方案建議.

    6.4 展 望

    1)目前并沒有將PackageRank 和APIRank 應(yīng)用于完整開發(fā)過程的例子,但openEuler 已經(jīng)開始按照APIRank 計算出的優(yōu)先級順序開展補(bǔ)全工作.在開發(fā)過程中發(fā)現(xiàn),有些高優(yōu)先級API 并非在musl libc 中實現(xiàn),而是以別名實現(xiàn)(如error)或在其他分支庫中實現(xiàn)(如backtrace),這表明高優(yōu)先級API 在musl libc 的開發(fā)者看來也十分重要,因此他們沒有拒絕實現(xiàn)這些API,只是其實現(xiàn)細(xì)節(jié)與glibc 存在區(qū)別.APIRank的分析結(jié)果和musl libc 開發(fā)者的觀點存在一致,有望為補(bǔ)全工作提供準(zhǔn)確的信息和實質(zhì)性的幫助.

    2)在PackageRank 和APIRank 中,除應(yīng)用軟件全集外,系統(tǒng)開發(fā)者還可以選擇將某個目標(biāo)應(yīng)用集作為研究對象,從而獲知系統(tǒng)或構(gòu)件對該目標(biāo)集的兼容性和缺失API 優(yōu)先級.

    3)PackageRank 和APIRank 不針對某種特定系統(tǒng)或構(gòu)件,因此它們有望適用于其他場景下的API兼容性分析,如其他C 庫、系統(tǒng)調(diào)用、向量化參數(shù)等.此外,還有望將它們應(yīng)用于系統(tǒng)模擬器的兼容性度量.

    6.5 局 限

    1)有2 處假設(shè)存在不準(zhǔn)確性:應(yīng)用的可執(zhí)行文件存在可鏈接API 的符號表條目,即視為API 被調(diào)用;API 存在即視為API 能正確工作.在3.1 節(jié)中,已經(jīng)對它們的不準(zhǔn)確性做出說明.

    2)僅采用靜態(tài)分析而未考慮API 調(diào)用頻率等其他有關(guān)API 調(diào)用的信息,而靜態(tài)分析方法也無法準(zhǔn)確給出這些信息.

    3)沒有參考用戶對應(yīng)用軟件的使用喜好和傾向,包括應(yīng)用軟件之間的其他隱性關(guān)聯(lián).

    4)未全面考慮編譯環(huán)境和源碼對API 調(diào)用情況的影響,即應(yīng)用軟件的開發(fā)者可能會通過宏命令,根據(jù)編譯環(huán)境的不同而調(diào)用不同的接口(特別是那些不在ANSI/ISO C 標(biāo)準(zhǔn)中的接口).應(yīng)用軟件的編譯環(huán)境會影響接口調(diào)用,接口缺失仍存在誤判.

    5)實驗對象單一.本文的算法僅在openEuler 上的musl libc 兼容性研究中使用,未曾在其他系統(tǒng)或構(gòu)件上開展工作.

    7 結(jié)束語

    本文研究了openEuler 的4 種軟件生態(tài)中的musl libc 兼容性和缺失API 優(yōu)先級,以幫助openEuler 的C 庫開發(fā)者進(jìn)行接口補(bǔ)全工作.

    本文的分析結(jié)果表明:一方面,musl libc 目前的兼容性仍有待提高,若要用其替代glibc 則需要進(jìn)一步開發(fā);另一方面,開發(fā)者可以根據(jù)本文的缺失API優(yōu)先級按序而高效地開展工作.

    本文基于應(yīng)用之間的依賴關(guān)系和應(yīng)用對API 的調(diào)用關(guān)系進(jìn)行兼容性和缺失API 優(yōu)先級的度量.從依賴關(guān)系和調(diào)用關(guān)系到兼容性和優(yōu)先級的轉(zhuǎn)化,是本文的核心思想和成果.

    作者貢獻(xiàn)聲明:吳亦澤提出算法、完成實驗并撰寫論文;于佳耕提出算法思路和指導(dǎo)意見并修改論文;鄭晨提出指導(dǎo)意見并修改論文;武延軍給出選題、提出指導(dǎo)意見并修改論文.

    猜你喜歡
    定義重要性生態(tài)
    “生態(tài)養(yǎng)生”娛晚年
    “0”的重要性
    論七分飽之重要性
    住進(jìn)呆萌生態(tài)房
    生態(tài)之旅
    幼兒教育中閱讀的重要性
    甘肅教育(2020年21期)2020-04-13 08:09:24
    讀《邊疆的重要性》有感
    成功的定義
    山東青年(2016年1期)2016-02-28 14:25:25
    生態(tài)
    修辭學(xué)的重大定義
    欧美日本中文国产一区发布| 国产成人精品婷婷| 性高湖久久久久久久久免费观看| 狠狠精品人妻久久久久久综合| 好男人视频免费观看在线| 国产精品国产三级国产av玫瑰| 边亲边吃奶的免费视频| 欧美老熟妇乱子伦牲交| 在线亚洲精品国产二区图片欧美 | 亚洲第一av免费看| 51国产日韩欧美| 国产综合精华液| 婷婷色综合大香蕉| 欧美激情极品国产一区二区三区 | 简卡轻食公司| 亚洲av电影在线观看一区二区三区| 五月伊人婷婷丁香| 精品国产露脸久久av麻豆| 国产av一区二区精品久久| 国产一级毛片在线| 国模一区二区三区四区视频| 桃花免费在线播放| 免费观看av网站的网址| 成年女人在线观看亚洲视频| 青春草国产在线视频| 卡戴珊不雅视频在线播放| 自拍欧美九色日韩亚洲蝌蚪91| 久久99精品国语久久久| 久久久久久久久久久免费av| 久久久a久久爽久久v久久| 中文乱码字字幕精品一区二区三区| 欧美少妇被猛烈插入视频| 国产精品偷伦视频观看了| 久久久国产精品麻豆| h视频一区二区三区| 飞空精品影院首页| 亚洲四区av| 99九九线精品视频在线观看视频| 26uuu在线亚洲综合色| 欧美日韩综合久久久久久| 亚洲av成人精品一区久久| 少妇 在线观看| 久久国产亚洲av麻豆专区| 亚洲av福利一区| 日韩视频在线欧美| 狂野欧美激情性bbbbbb| 欧美日韩视频高清一区二区三区二| 日本色播在线视频| 99视频精品全部免费 在线| 秋霞伦理黄片| 自线自在国产av| 午夜激情av网站| 国产成人免费无遮挡视频| 一本—道久久a久久精品蜜桃钙片| 人成视频在线观看免费观看| 精品人妻熟女毛片av久久网站| 国产色爽女视频免费观看| 婷婷色av中文字幕| 人妻少妇偷人精品九色| 午夜福利视频精品| 亚洲欧洲日产国产| 国产一区二区在线观看日韩| 最近中文字幕2019免费版| 午夜免费观看性视频| 国产欧美日韩一区二区三区在线 | 国产精品人妻久久久久久| 中文字幕免费在线视频6| 国产精品99久久99久久久不卡 | 日韩av免费高清视频| 亚洲美女黄色视频免费看| 老司机影院毛片| h视频一区二区三区| 高清毛片免费看| 国产视频内射| 亚洲国产精品成人久久小说| 国产免费一区二区三区四区乱码| 在线观看国产h片| 日韩三级伦理在线观看| 免费观看a级毛片全部| 制服丝袜香蕉在线| 尾随美女入室| 国产高清三级在线| 欧美 日韩 精品 国产| a 毛片基地| 一本久久精品| 日日爽夜夜爽网站| 免费av中文字幕在线| 五月伊人婷婷丁香| 在线看a的网站| 久久久久国产网址| 80岁老熟妇乱子伦牲交| 国产色爽女视频免费观看| 女的被弄到高潮叫床怎么办| 人妻少妇偷人精品九色| 精品卡一卡二卡四卡免费| 97在线视频观看| 搡女人真爽免费视频火全软件| 午夜日本视频在线| 亚洲av欧美aⅴ国产| 久久午夜福利片| 搡女人真爽免费视频火全软件| 伊人亚洲综合成人网| 精品国产一区二区三区久久久樱花| 99re6热这里在线精品视频| 80岁老熟妇乱子伦牲交| 日本91视频免费播放| 欧美日韩亚洲高清精品| 国内精品宾馆在线| 欧美性感艳星| 97在线视频观看| 日韩中文字幕视频在线看片| 国产精品一国产av| 视频在线观看一区二区三区| 夜夜看夜夜爽夜夜摸| 亚洲久久久国产精品| 精品亚洲成国产av| 飞空精品影院首页| 欧美日韩视频高清一区二区三区二| 少妇被粗大猛烈的视频| 99视频精品全部免费 在线| 国产精品99久久久久久久久| 成人综合一区亚洲| videos熟女内射| 亚洲图色成人| 精品99又大又爽又粗少妇毛片| 久久久精品区二区三区| 下体分泌物呈黄色| 王馨瑶露胸无遮挡在线观看| 日韩成人av中文字幕在线观看| 91久久精品国产一区二区三区| 亚洲精品久久久久久婷婷小说| 国产精品一区二区在线观看99| 国产探花极品一区二区| 久热这里只有精品99| 日日啪夜夜爽| 亚洲精品国产av蜜桃| 亚洲国产欧美日韩在线播放| 国产无遮挡羞羞视频在线观看| 免费黄色在线免费观看| 大香蕉97超碰在线| 黄色毛片三级朝国网站| 综合色丁香网| 视频中文字幕在线观看| 日韩成人av中文字幕在线观看| 国产日韩一区二区三区精品不卡 | 日日爽夜夜爽网站| 最近中文字幕高清免费大全6| 久久综合国产亚洲精品| 亚洲欧洲日产国产| 亚州av有码| 极品人妻少妇av视频| 国产国语露脸激情在线看| 99热国产这里只有精品6| 免费播放大片免费观看视频在线观看| 亚洲美女黄色视频免费看| 久久热精品热| 人妻夜夜爽99麻豆av| 久久99一区二区三区| 亚洲av日韩在线播放| 久久久久久久久久久久大奶| 寂寞人妻少妇视频99o| 高清午夜精品一区二区三区| 在线天堂最新版资源| 国产有黄有色有爽视频| 高清午夜精品一区二区三区| 日韩熟女老妇一区二区性免费视频| 在线精品无人区一区二区三| 伦精品一区二区三区| 日韩,欧美,国产一区二区三区| 看免费成人av毛片| 亚洲中文av在线| av有码第一页| 黄色配什么色好看| 国产成人精品福利久久| 久久精品人人爽人人爽视色| .国产精品久久| 插逼视频在线观看| 制服丝袜香蕉在线| 高清午夜精品一区二区三区| 色94色欧美一区二区| 成人亚洲欧美一区二区av| 夜夜看夜夜爽夜夜摸| 亚洲av日韩在线播放| 男女免费视频国产| 永久网站在线| 天天操日日干夜夜撸| 男女啪啪激烈高潮av片| 国产极品天堂在线| 国产精品无大码| 国产 一区精品| 五月伊人婷婷丁香| 最新中文字幕久久久久| 美女国产视频在线观看| 一本—道久久a久久精品蜜桃钙片| 国产精品国产三级国产av玫瑰| av免费在线看不卡| 亚州av有码| 色哟哟·www| 久久综合国产亚洲精品| 黄色怎么调成土黄色| 免费观看性生交大片5| 黄色毛片三级朝国网站| 亚洲综合精品二区| 男人爽女人下面视频在线观看| 一边摸一边做爽爽视频免费| 国产视频内射| 自线自在国产av| 国产日韩欧美亚洲二区| 在线观看一区二区三区激情| av视频免费观看在线观看| 日韩在线高清观看一区二区三区| 熟女av电影| 欧美老熟妇乱子伦牲交| 欧美日本中文国产一区发布| 国产高清不卡午夜福利| 在线看a的网站| 日韩人妻高清精品专区| 22中文网久久字幕| 街头女战士在线观看网站| 精品久久久久久久久亚洲| 国产伦精品一区二区三区视频9| av免费在线看不卡| av一本久久久久| 日本爱情动作片www.在线观看| 91在线精品国自产拍蜜月| 毛片一级片免费看久久久久| 国产精品嫩草影院av在线观看| 久久人人爽人人片av| 亚洲国产欧美日韩在线播放| 丝瓜视频免费看黄片| 国产日韩欧美在线精品| 欧美激情 高清一区二区三区| 狠狠精品人妻久久久久久综合| 99热这里只有精品一区| 亚洲精品一区蜜桃| 两个人免费观看高清视频| 一个人看视频在线观看www免费| 看免费成人av毛片| 免费高清在线观看日韩| 两个人的视频大全免费| 日本av免费视频播放| 国产成人免费观看mmmm| 中文精品一卡2卡3卡4更新| 啦啦啦在线观看免费高清www| 在线观看国产h片| 好男人视频免费观看在线| 国产片特级美女逼逼视频| 亚洲五月色婷婷综合| 午夜精品国产一区二区电影| 国产精品麻豆人妻色哟哟久久| 日韩成人伦理影院| 在线精品无人区一区二区三| 国产免费现黄频在线看| 两个人的视频大全免费| 欧美亚洲 丝袜 人妻 在线| 免费观看a级毛片全部| 我的女老师完整版在线观看| 成人影院久久| 男男h啪啪无遮挡| 成年人午夜在线观看视频| 女的被弄到高潮叫床怎么办| 久久狼人影院| 亚洲久久久国产精品| 高清午夜精品一区二区三区| 91国产中文字幕| 久久久久视频综合| xxxhd国产人妻xxx| 欧美精品亚洲一区二区| 蜜桃久久精品国产亚洲av| 国产色婷婷99| 亚洲国产精品999| 在线天堂最新版资源| av播播在线观看一区| 中国三级夫妇交换| 久久久久人妻精品一区果冻| 欧美日韩国产mv在线观看视频| 99热全是精品| 久久久国产欧美日韩av| 欧美老熟妇乱子伦牲交| 免费av不卡在线播放| 日本与韩国留学比较| 亚洲精品色激情综合| xxxhd国产人妻xxx| 老司机亚洲免费影院| 国产精品久久久久久久久免| 99久久精品一区二区三区| 精品人妻熟女毛片av久久网站| 欧美日韩一区二区视频在线观看视频在线| 18在线观看网站| 亚洲精品色激情综合| 免费观看性生交大片5| 国产精品久久久久久精品电影小说| 久久99热6这里只有精品| 欧美精品高潮呻吟av久久| www.av在线官网国产| 纵有疾风起免费观看全集完整版| 午夜av观看不卡| 男女边吃奶边做爰视频| 一区二区三区四区激情视频| 简卡轻食公司| 久久精品国产鲁丝片午夜精品| 人妻一区二区av| 国产免费一级a男人的天堂| 亚洲综合色惰| 在线观看国产h片| 高清欧美精品videossex| 国产淫语在线视频| 久久女婷五月综合色啪小说| 各种免费的搞黄视频| 99久久综合免费| 如何舔出高潮| 在线播放无遮挡| 久久热精品热| 又粗又硬又长又爽又黄的视频| 一级毛片我不卡| 国产精品人妻久久久久久| 国产黄频视频在线观看| a级毛片免费高清观看在线播放| 成人无遮挡网站| 成人二区视频| 国产精品不卡视频一区二区| 91久久精品电影网| 一本色道久久久久久精品综合| 免费观看性生交大片5| 亚洲欧美一区二区三区国产| 在线观看一区二区三区激情| 人人妻人人澡人人爽人人夜夜| 国产午夜精品久久久久久一区二区三区| 五月玫瑰六月丁香| 大片免费播放器 马上看| 香蕉精品网在线| 久热这里只有精品99| 最近中文字幕2019免费版| 久久精品国产自在天天线| 99九九线精品视频在线观看视频| 老司机亚洲免费影院| av在线app专区| 久久女婷五月综合色啪小说| 国产一区二区在线观看日韩| 亚洲精品国产色婷婷电影| 国产亚洲精品久久久com| 97在线人人人人妻| 性高湖久久久久久久久免费观看| 国产探花极品一区二区| 九草在线视频观看| 汤姆久久久久久久影院中文字幕| 精品午夜福利在线看| 久久久久人妻精品一区果冻| 亚洲精品第二区| 秋霞伦理黄片| 美女大奶头黄色视频| 国产精品人妻久久久影院| 黄色毛片三级朝国网站| 欧美日韩亚洲高清精品| 亚洲久久久国产精品| a级毛片在线看网站| 在线观看三级黄色| 美女cb高潮喷水在线观看| 九九爱精品视频在线观看| 欧美+日韩+精品| 国产一区二区三区av在线| 成人18禁高潮啪啪吃奶动态图 | 中文字幕制服av| 国产精品99久久久久久久久| 男女啪啪激烈高潮av片| 免费久久久久久久精品成人欧美视频 | 水蜜桃什么品种好| 国产精品麻豆人妻色哟哟久久| 亚洲av二区三区四区| 69精品国产乱码久久久| 亚洲精品久久午夜乱码| 亚洲精品中文字幕在线视频| a级片在线免费高清观看视频| 男的添女的下面高潮视频| 一级片'在线观看视频| 亚洲av免费高清在线观看| 亚洲欧美色中文字幕在线| 日本黄大片高清| 国产一区亚洲一区在线观看| 最近手机中文字幕大全| 午夜福利视频在线观看免费| 高清午夜精品一区二区三区| 国产精品国产三级国产av玫瑰| 一级毛片我不卡| 久久久久久久久久久丰满| 久久久国产精品麻豆| 少妇人妻久久综合中文| 国产成人免费无遮挡视频| 久久久久久人妻| 国产高清不卡午夜福利| 久久久久久久久大av| 精品卡一卡二卡四卡免费| 伊人久久国产一区二区| 九九在线视频观看精品| 亚洲伊人久久精品综合| 亚洲综合精品二区| 一个人免费看片子| 亚洲第一区二区三区不卡| 99久久中文字幕三级久久日本| 久久午夜福利片| 国产乱人偷精品视频| 色网站视频免费| 在线观看三级黄色| 简卡轻食公司| 久久毛片免费看一区二区三区| 2022亚洲国产成人精品| 国产综合精华液| 亚洲成人一二三区av| 91精品三级在线观看| 成人国产麻豆网| 最近手机中文字幕大全| 男女无遮挡免费网站观看| 亚洲精品自拍成人| 久久影院123| 亚洲av综合色区一区| 性高湖久久久久久久久免费观看| 精品国产一区二区久久| 亚洲精品国产av成人精品| 欧美一级a爱片免费观看看| 亚洲av欧美aⅴ国产| 欧美国产精品一级二级三级| 人妻系列 视频| 一个人看视频在线观看www免费| 视频区图区小说| 国产精品久久久久成人av| 国产淫语在线视频| 亚洲精品久久久久久婷婷小说| 天堂8中文在线网| 18禁动态无遮挡网站| 黑丝袜美女国产一区| 777米奇影视久久| 久久久久精品性色| 大片免费播放器 马上看| 51国产日韩欧美| 伊人久久精品亚洲午夜| 日韩制服骚丝袜av| 亚洲四区av| 亚洲精品一二三| 观看av在线不卡| 99九九在线精品视频| 亚洲精品久久成人aⅴ小说 | av免费在线看不卡| 欧美精品人与动牲交sv欧美| 中文天堂在线官网| 婷婷色麻豆天堂久久| 久久久久久伊人网av| 中国美白少妇内射xxxbb| 这个男人来自地球电影免费观看 | 午夜日本视频在线| 国产成人av激情在线播放 | 建设人人有责人人尽责人人享有的| 久久婷婷青草| 亚洲精品久久久久久婷婷小说| 一级a做视频免费观看| 亚洲精品中文字幕在线视频| 亚洲国产精品国产精品| 伊人亚洲综合成人网| 高清不卡的av网站| 99久久精品一区二区三区| 一区在线观看完整版| 国产精品久久久久久精品电影小说| 精品一品国产午夜福利视频| 精品久久久精品久久久| 亚洲国产精品国产精品| 日本与韩国留学比较| 99久久精品国产国产毛片| 日本黄色日本黄色录像| 国产国拍精品亚洲av在线观看| 日韩一区二区三区影片| 欧美日韩一区二区视频在线观看视频在线| 青春草亚洲视频在线观看| 国产一区有黄有色的免费视频| 欧美日韩视频精品一区| 少妇人妻精品综合一区二区| 高清午夜精品一区二区三区| 一级二级三级毛片免费看| 亚洲精品成人av观看孕妇| 精品一区二区三卡| 日本av免费视频播放| 国产精品嫩草影院av在线观看| 伊人久久精品亚洲午夜| 又粗又硬又长又爽又黄的视频| 99热6这里只有精品| 日韩熟女老妇一区二区性免费视频| 精品久久久久久久久av| 国产欧美日韩一区二区三区在线 | 久久 成人 亚洲| 国产日韩欧美亚洲二区| 日本黄大片高清| 最近中文字幕高清免费大全6| av黄色大香蕉| 国产熟女午夜一区二区三区 | 天堂中文最新版在线下载| 亚洲精品av麻豆狂野| kizo精华| 日韩中文字幕视频在线看片| 亚洲精品乱码久久久v下载方式| 免费人妻精品一区二区三区视频| 国内精品宾馆在线| 久久国产精品大桥未久av| 国产视频首页在线观看| 亚洲欧美成人精品一区二区| av卡一久久| 三级国产精品欧美在线观看| 啦啦啦啦在线视频资源| 亚洲av.av天堂| 人妻 亚洲 视频| 校园人妻丝袜中文字幕| 中文字幕人妻丝袜制服| 热re99久久精品国产66热6| 九九久久精品国产亚洲av麻豆| 日韩一区二区视频免费看| 亚洲精品久久午夜乱码| 大话2 男鬼变身卡| 婷婷色av中文字幕| 一本色道久久久久久精品综合| 国产不卡av网站在线观看| 久久国产亚洲av麻豆专区| 免费观看在线日韩| 久久精品久久久久久久性| 久久久久久伊人网av| 国产又色又爽无遮挡免| 嫩草影院入口| 久久久亚洲精品成人影院| 中文字幕亚洲精品专区| 久久久国产一区二区| 日韩,欧美,国产一区二区三区| 我要看黄色一级片免费的| 街头女战士在线观看网站| 伊人久久国产一区二区| 国产亚洲最大av| 人人妻人人澡人人爽人人夜夜| 熟女人妻精品中文字幕| 日韩精品有码人妻一区| 日韩精品免费视频一区二区三区 | 中文字幕精品免费在线观看视频 | 亚洲欧洲精品一区二区精品久久久 | 国产免费又黄又爽又色| 亚洲国产精品一区三区| 免费观看av网站的网址| 欧美3d第一页| 亚洲国产欧美在线一区| 不卡视频在线观看欧美| 成年人午夜在线观看视频| 国产精品一国产av| 亚洲av成人精品一区久久| 在线观看美女被高潮喷水网站| 在线天堂最新版资源| 天堂俺去俺来也www色官网| 最近最新中文字幕免费大全7| 蜜桃在线观看..| 一区二区三区免费毛片| 亚洲av中文av极速乱| 亚洲av在线观看美女高潮| 激情五月婷婷亚洲| 99国产综合亚洲精品| 99热这里只有是精品在线观看| 女人精品久久久久毛片| 国产伦理片在线播放av一区| 午夜福利影视在线免费观看| 街头女战士在线观看网站| 午夜影院在线不卡| 91在线精品国自产拍蜜月| 国产免费一级a男人的天堂| 狠狠精品人妻久久久久久综合| 亚洲内射少妇av| 欧美激情极品国产一区二区三区 | 黄色欧美视频在线观看| 久久97久久精品| 人妻夜夜爽99麻豆av| 国产欧美日韩一区二区三区在线 | 国产精品一区二区三区四区免费观看| 日韩亚洲欧美综合| 国产午夜精品久久久久久一区二区三区| 高清在线视频一区二区三区| 亚洲欧洲精品一区二区精品久久久 | 欧美日韩成人在线一区二区| 乱码一卡2卡4卡精品| 中国国产av一级| 高清午夜精品一区二区三区| 亚洲精品中文字幕在线视频| 精品久久久久久久久av| 久久国产精品大桥未久av| 啦啦啦啦在线视频资源| 一边亲一边摸免费视频| 成人免费观看视频高清| 亚洲精品第二区| 七月丁香在线播放| 高清视频免费观看一区二区| 色婷婷久久久亚洲欧美| 亚洲av成人精品一二三区| 免费看不卡的av| 春色校园在线视频观看| 看非洲黑人一级黄片| 午夜视频国产福利| av电影中文网址| 哪个播放器可以免费观看大片| 日韩电影二区| 午夜91福利影院| 国产一区二区三区av在线| 精品视频人人做人人爽| 精品卡一卡二卡四卡免费| 欧美亚洲 丝袜 人妻 在线| av播播在线观看一区| videos熟女内射| 黄色怎么调成土黄色| 美女大奶头黄色视频| 高清在线视频一区二区三区| 日本av手机在线免费观看| 亚洲精品aⅴ在线观看| 国产乱人偷精品视频| 人人妻人人添人人爽欧美一区卜| 91久久精品电影网| 精品亚洲乱码少妇综合久久| 视频中文字幕在线观看|