999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

Linux內(nèi)核的Go語言實現(xiàn)研究

2021-07-06 02:10:20柴艷娜
計算機技術(shù)與發(fā)展 2021年6期
關(guān)鍵詞:語言

柴艷娜

(長安大學(xué) 信息與網(wǎng)絡(luò)管理處,陜西 西安 710064)

1 概 述

計算機是現(xiàn)代日常生活的一種必需品,其高效可靠的運行需要依賴于一套穩(wěn)健無缺陷(bug-free)的操作系統(tǒng)。現(xiàn)代操作系統(tǒng)都會使用內(nèi)核(kernel)來對硬件進行管理,因此可以說內(nèi)核的安全穩(wěn)定決定了人們與計算機相處的體驗。內(nèi)核中的缺陷(bug)將可能使用戶的應(yīng)用程序甚至操作系統(tǒng)本身變得不可靠[1]。

內(nèi)核是用戶和應(yīng)用程序與計算機硬件之間的橋梁,內(nèi)核管理各種系統(tǒng)資源,包括內(nèi)存和硬盤空間,并且處理CPU處理程序的調(diào)度。它也提供對輸入輸出設(shè)備和網(wǎng)絡(luò)的訪問。應(yīng)用程序運行在內(nèi)核之上,通過內(nèi)核的系統(tǒng)調(diào)用從而使用到內(nèi)核的功能。

1.1 現(xiàn)代內(nèi)核的問題

大多數(shù)成熟的操作系統(tǒng)內(nèi)核都是用C語言實現(xiàn)的。C語言因為允許高度控制內(nèi)存使用以及其他如可與匯編語言互操作等低級程序操作特性,成為最受歡迎的內(nèi)核語言[2]。這種高度的自由也會付出一些代價,比如內(nèi)存釋放兩遍的錯誤、數(shù)組越界的錯誤以及死鎖[3]。同時它也不能防止數(shù)據(jù)類型的錯誤解析,保證不了類型的安全性。

隨著計算機多處理器以及多核處理器的增加,如何高效地利用多線程是評價內(nèi)核優(yōu)秀與否的一個有力因素。C語言實現(xiàn)的內(nèi)核不能輕易地全面發(fā)揮多核的性能,因為C語言本身沒有涵蓋現(xiàn)代處理器的特性,C中的線程(thread)對內(nèi)存和CPU來說都是很昂貴的一筆開銷,而線程之間的同步機制則更復(fù)雜,所以內(nèi)核需要大費周章地實現(xiàn)一套機制來充分調(diào)動多核計算機的全部性能[4]。

如果用Java,Go等高級語言來開發(fā)內(nèi)核,則可能會規(guī)避掉很多上述問題,比如許多高級語言提供了數(shù)組越界檢查和內(nèi)存垃圾回收機制。然而,通常來說高級語言開發(fā)的程序會比C語言的慢,有時候由于代碼解釋、自動內(nèi)存管理、垃圾回收等特性,會帶來很大的系統(tǒng)開銷。同時,高級語言很難操作匯編語言,因此可能很難滿足內(nèi)核的底層任務(wù)調(diào)用。

1.2 現(xiàn)有社區(qū)項目

當(dāng)下社區(qū)中有很多用高級語言實現(xiàn)內(nèi)核的嘗試,諸多原因?qū)е铝怂鼈儧]有一個被廣泛采用。

Mirage是一個Linux基金會項目,致力于將Web應(yīng)用變成一個運行在Xen虛擬機下的獨立的專屬精簡內(nèi)核(Unikernel),它包含一個用OCaml開發(fā)的內(nèi)核子系統(tǒng)的早期實現(xiàn)。因為它是為專屬內(nèi)核(單用戶單進程,大多運行于虛擬機中)開發(fā)的,所以不能滿足大多數(shù)普通用戶的需求。另外,也不能在多核上并行,因為它本來就是為單進程運行而設(shè)計的。

Pycorn是一個用Python開發(fā)的操作系統(tǒng),目前只兼容16位ARM微處理器。因為Python是一門解釋型語言,Pycorn實際運行十分慢,性能不是該項目的目標(biāo)。因此它從未被廣泛使用過。

1.3 內(nèi)核子系統(tǒng)

因為實現(xiàn)一個完整的內(nèi)核是一項巨大的工程,所以該文代之以實現(xiàn)一個內(nèi)核子系統(tǒng),即網(wǎng)絡(luò)堆棧子系統(tǒng),來進行相應(yīng)的研究工作。網(wǎng)絡(luò)堆棧(network stack)是任何內(nèi)核必須有的特性,網(wǎng)絡(luò)堆棧的功能和性能可以容易地比較和測試,因此是個比較理想的可用于研究的子系統(tǒng)。

1.4 Go語言

該文用Go語言實現(xiàn)內(nèi)核子系統(tǒng),用于研究用高級語言開發(fā)內(nèi)核的相對優(yōu)勢。之所以選擇Go是因為語言本身自帶的優(yōu)秀的CSP并發(fā)模型(concurrent sequential processes)[4-6]。CSP模型將復(fù)雜任務(wù)解構(gòu)成更小的、更加可管理的子任務(wù)。這些子任務(wù)都能被單個進程所處理,進程之間彼此保持通信,共同完成原始的復(fù)雜任務(wù)。

CSP模型的目標(biāo)是幫助程序員設(shè)計,實現(xiàn)和驗證復(fù)雜的計算機系統(tǒng),這是十分重要的,特別是要設(shè)計一個如內(nèi)核般復(fù)雜的軟件。Go提供了線程安全(thread-safe)方式的CSP模型,Go語言的線程即協(xié)程(go-routines),同步的通信構(gòu)造即通道(channel)[7]。Go語言運行時自動根據(jù)計算機的物理內(nèi)核數(shù)量來管理調(diào)度協(xié)程。CSP模型能讓人很容易地使用計算機所有內(nèi)核,同時改善代碼的可讀性,使得更簡單地進行調(diào)試和減少產(chǎn)生的缺陷。網(wǎng)絡(luò)堆棧很自然地可以被劃分成多個子任務(wù)去運行,可以充分利用Go協(xié)程去動態(tài)調(diào)度高效利用所有可用物理內(nèi)核[8]。

CSP模型只在垃圾回收語言里有可行性,Go提供了必要的垃圾回收。Go是一門強類型語言,能減少一大類錯誤,包括錯誤類型轉(zhuǎn)換,內(nèi)存釋放兩遍,對象釋放后再使用等。Go的延遲聲明(defer statement)允許在函數(shù)結(jié)束時更方便地清理,減少那些疏于管理的資源導(dǎo)致死鎖的可能性。

1.5 研究目標(biāo)

Go和CSP模型的優(yōu)勢可能伴隨著某種代價,比如垃圾回收有性能花銷并導(dǎo)致運行時的短暫暫停。另外,多核的使用,將帶來昂貴的內(nèi)核間通信。該文的目標(biāo)是評估Go帶來的收益是否能蓋過性能損失帶來的劣勢。

2 實 現(xiàn)

該文實現(xiàn)的獨立網(wǎng)絡(luò)堆棧(項目代號NStack)是建立在Tap虛擬網(wǎng)卡的基礎(chǔ)上。為了功能完整,所有基礎(chǔ)網(wǎng)絡(luò)協(xié)議,包括以太網(wǎng)(Ethernet),ARP,IPv4,ICMP,UDP和TCP,都被實現(xiàn)。為確保性能不受影響,延遲(latency)和吞吐量(through-out)會被測試,并與C語言實現(xiàn)的網(wǎng)絡(luò)堆棧進行比較。

2.1 Tap接口

Tap接口即一種虛擬網(wǎng)絡(luò)接口(虛擬網(wǎng)卡),用軟件來模仿實際硬件。NStack會將Tap接口當(dāng)作正常物理接口一樣讀寫[9]。Tap接口會關(guān)聯(lián)一橋接接口,就好像一個路由器作為主機的一個子網(wǎng)接入其中,這樣可以允許NStack能使用它自己的MAC地址和IP地址,連接到外部網(wǎng)絡(luò)。

2.2 協(xié)議實現(xiàn)

NStack會實現(xiàn)數(shù)據(jù)鏈路層,網(wǎng)絡(luò)層和傳輸層的協(xié)議,每一層獨立運行自己的協(xié)議,如圖1所示。分層模型可以增加并行,在高負(fù)載下提供高效服務(wù)[10]。

圖1 網(wǎng)絡(luò)協(xié)議棧

每一個協(xié)議的實現(xiàn)使用了類似的結(jié)構(gòu),包處理器(packet dealer)。IP包處理器如圖2所示。包處理器從低層級讀取數(shù)據(jù)包,并通過通道傳輸。通道以箭頭表示在圖2中。IP包處理器將數(shù)據(jù)包發(fā)給不同的IP reader協(xié)程。IP reader處理完接收到的數(shù)據(jù)包后,將處理結(jié)果轉(zhuǎn)發(fā)給下一層的包處理器。

圖2 IPv4包處理器

(1)以太協(xié)議層允許其他不同層的協(xié)議綁定到特定的以太協(xié)議。比如IPv4實現(xiàn)會綁定到以太協(xié)議2048去接收所有IPv4數(shù)據(jù)包,ARP實現(xiàn)則綁定到以太協(xié)議2054。

(2)地址解析協(xié)議(address resolution protocol,ARP)會被實現(xiàn)用于MAC地址的獲取,數(shù)據(jù)的網(wǎng)絡(luò)傳輸需要物理信息的支持。ARP能讓NStack從目標(biāo)主機的目標(biāo)協(xié)議地址中獲取MAC地址。NStack為每個ARP請求創(chuàng)建一個協(xié)程負(fù)責(zé)處理。處理時協(xié)程會被阻塞直到主ARP包處理器通知其響應(yīng)或者請求超時。

(3)IPv4的設(shè)計如圖2所示,它使用包處理器結(jié)構(gòu),包含多個IP讀取器和分片重組器。所有組件之間的通信都是通過通道進行,如箭頭所示。

當(dāng)IP包大小超過最大傳輸單元(maximum transmission unit,MTU)時,便會出現(xiàn)IP分片,IP包會被拆分成多個分片,每一個分片都包含一些信息用以重組。當(dāng)分片數(shù)據(jù)包到達(dá)目的主機,它們便會被重組成原始IP包。

NStack的分片重組器演示了CSP模型的優(yōu)點。每個分片重組器都囊括了對分片IP數(shù)據(jù)包的處理過程以及相應(yīng)的數(shù)據(jù)。與用全局?jǐn)?shù)據(jù)結(jié)構(gòu)來管理所有分片數(shù)據(jù)包重組的傳統(tǒng)方法相比,為每個報文分片分配一個專屬重組器,這種CSP模型的做法可以大幅降低代碼的復(fù)雜度。輕量級的Go協(xié)程設(shè)計讓數(shù)據(jù)隔離變得可行,垃圾回收又大幅降低內(nèi)存泄漏的可能。

(4)NStack實現(xiàn)了ping及ICMP協(xié)議。ICMP實現(xiàn)也是遵循包處理器結(jié)構(gòu)。ping實現(xiàn)也有其相應(yīng)的包處理器,ping的ICMP包會被ICMP包處理器先行處理,然后再發(fā)給ping的包處理器處理。ping包處理器會將ping請求轉(zhuǎn)發(fā)給一組特別的協(xié)程,用于回復(fù)ping請求。如果NStack已經(jīng)發(fā)送了ping請求,則ping包處理器將會把回應(yīng)轉(zhuǎn)發(fā)給對應(yīng)請求的專屬協(xié)程負(fù)責(zé)。

(5)用戶報文協(xié)議(user datagram protocol,UDP)是個無連接的協(xié)議,因為它相對簡單,NStack便用一個基礎(chǔ)的包處理器將其轉(zhuǎn)發(fā)給對應(yīng)的UDP讀取器。

(6)傳輸控制協(xié)議(transmission control protocol,TCP)是面向連接的傳輸層協(xié)議,它保證了數(shù)據(jù)傳輸?shù)挠行颉R驗門CP是面向連接的,所以它會需要服務(wù)端和客戶端來初始化連接。一旦連接建立成功,便由傳輸控制單元(transmission control block,TCB)進行管理。

NStack里TCP也是使用標(biāo)準(zhǔn)的包處理器結(jié)構(gòu)管理源端口和目的端口,每個TCB里都有2個長期運行的協(xié)程。一個處理接收到的數(shù)據(jù)包,另一個則等待和發(fā)送數(shù)據(jù),也會負(fù)責(zé)創(chuàng)建額外的協(xié)程管理數(shù)據(jù)包的重發(fā),這2個協(xié)程便代表著半雙工TCP連接。TCB內(nèi)部也會用到通道來同步和管理所有創(chuàng)建的協(xié)程。比如,處理接收數(shù)據(jù)包的協(xié)程發(fā)現(xiàn)收到一個確認(rèn)數(shù)據(jù)包時,便會用通道通知數(shù)據(jù)包重傳協(xié)程。

2.3 測 試

NStack會與Tapip進行性能比較。Tapip是一個由C語言開發(fā)的多線程網(wǎng)絡(luò)堆棧。這個比較允許評估用高級語言開發(fā)網(wǎng)絡(luò)堆棧的優(yōu)點和缺點。兩個網(wǎng)絡(luò)堆棧都實現(xiàn)了相似的協(xié)議,都在用戶空間(user space)操作,都使用tap虛擬接口。測試機器是Ubuntu 14.04/Linux 3.13.0,16 GB內(nèi)存,Intel Xeon Quad Core Dual Socket處理器。

2.3.1 延 遲

為測試延遲,將取50次ping響應(yīng)時間的平均值作比較。測試環(huán)境的一臺Linux虛擬機將運行兩個網(wǎng)絡(luò)堆棧,ping請求從該虛擬機發(fā)出。為判斷堆棧在負(fù)載增加情況下的性能,多個ping會被同時并發(fā)發(fā)送。從1個增加到1 000個并發(fā)ping“連接”來模擬網(wǎng)絡(luò)堆棧可能接受的負(fù)載。為保證對兩個網(wǎng)絡(luò)堆棧公平,其他的變量都將保持不變,包括每個ping“連接”發(fā)送的ping請求數(shù),ICMP接受緩沖區(qū)大小以及ping請求數(shù)據(jù)包大小。

2.3.2 吞吐量

第二個將要評估的性能指標(biāo)便是吞吐量。一個堆棧的吞吐量是在給定時間內(nèi),能發(fā)送或接收的數(shù)據(jù)量大小[11]。以下步驟將用以測量兩個堆棧的吞吐量:

(1)初始化一個TCP服務(wù)端。

(2)初始化一個TCP客戶端,連接會在local網(wǎng)絡(luò)(localhost)中建立,以排除tap虛擬網(wǎng)卡導(dǎo)致的開銷。

(3)客戶端發(fā)送4 KB數(shù)據(jù)給服務(wù)端。

(4)計算堆棧完成上述過程的總時間,該時間和發(fā)送的數(shù)據(jù)量將用來計算吞吐量。

為測量堆棧的相對擴展能力,將會逐步增加客戶端數(shù)來測量性能[12]。最大測試到100個并發(fā)客戶端。有許多預(yù)防措施將用于保證吞吐量的準(zhǔn)確測量,比如所有可比較的緩沖區(qū)大小都一致[13]。在Tapip中,每個客戶端和服務(wù)端連接都運行在各自線程里,NStack類似,但是用的是Go的協(xié)程而不是線程。另外,也會確保所有連接完成且連接的負(fù)載被完整傳輸之后再停止運行網(wǎng)絡(luò)堆棧[14-15]。

3 結(jié)果分析

NStack的代碼與Tapip比較類似,但是從結(jié)果來看,性能上,包括延遲和吞吐量,NStack相比之下出色得多。

3.1 準(zhǔn)確性

NStack和Tapip都能準(zhǔn)確地運行協(xié)議,這可以通過分別測試兩個協(xié)議棧與一臺Linux終端的連接來進行判斷。測試中發(fā)現(xiàn)Tapip有內(nèi)存泄漏的情況。這是因為Tapip會開辟緩存區(qū)存儲數(shù)據(jù)包,在某些情況下這些緩存區(qū)不會被釋放或者重復(fù)釋放。當(dāng)緩存區(qū)被重復(fù)釋放時,Tapip會崩潰或者導(dǎo)致異常行為。當(dāng)緩存區(qū)不會被釋放時,Tapip會不斷侵占內(nèi)存,直至系統(tǒng)崩潰。Go則由于有內(nèi)置的垃圾回收,可以很好地避免這種情況的發(fā)生。

3.2 代碼比較

雖然很難量化地評估編寫Go語言相比較C語言的優(yōu)點,但是從一些代碼片段的比較還是可以看出高級語言的某些優(yōu)勢。以下以IP報文分片重組的處理代碼舉例說明。

(1)當(dāng)新的IP分片到達(dá)時,需要初始化分片重組器。Tapip則會使用全局結(jié)構(gòu)體存儲所有待重組的數(shù)據(jù),C代碼如下所示:

struct fragment *frag;

frag=xmalloc(sizeof(*frag));

list_add(& frag->frag_list, & frag_head);

list_init(& frag->frag_pkb);

return frag;

NStack會給每個待重組的包新建一個Go協(xié)程,Go語言代碼如下:

ipr.fragBuf[bufID]=make(chan []byte, FRAG_ASSEM_BUF_SZ)

quit:=make(chan bool, 1)

done:=make(chan bool, 1)

didQuit:=make(chan bool, 1)

go ipr.fragAssembler( /* ... */ )

go ipr.killFragAssembler( /* ... */ )

(2)當(dāng)添加分片到重組隊列時,Tapip的C語言代碼如下:

int insert_frag(/* ... */) {

/*一些額外的分片處理 */

list_add(& pkb->pk_list, pos);

return 0;

frag_drop: free_pkb(pkb); return -1;

}

Go語言代碼則如下:

ipr.fragBuf[bufID] <- b

Go可以用協(xié)程處理IP報文分片,因此它可以簡單地將分片轉(zhuǎn)發(fā)給對應(yīng)的協(xié)程處理,同時可以緊接著處理后續(xù)數(shù)據(jù)包。此舉會改進NStack代碼的模塊性、可讀性和并發(fā)性。

(3)分片處理完成時的C語言代碼片段如下:

if (complete_frag(frag))

pkb=reass_frag(frag);

else pkb=NULL;

return pkb;

struct pkbuf *reass_frag(

struct fragment *frag) {

/* more processing */

delete_frag(frag);

return pkb;

}

Go語言代碼片段如下:

ipr.incomingPackets <- append(

fullPacketHdr ,payload ...)

done <- true

經(jīng)過對比,可以凸顯出Go語言以及CSP模型的優(yōu)勢。Tapip必需按順序處理數(shù)據(jù)包,在前一個數(shù)據(jù)包未處理完時,下一個數(shù)據(jù)包只能在緩沖區(qū)中等待。這會帶來一些問題,比如這便需要C語言的IP實現(xiàn)去跟蹤所有正在進行的分片重組的狀態(tài),這樣不可避免地會使用全局變量和結(jié)構(gòu)體來記錄共享信息,并且會讓線程同步變得困難。NStack與之相反,它會對接收到的每個分片IP包創(chuàng)建一個獨立的分片重組器協(xié)程,每個協(xié)程各自負(fù)責(zé)獨立的分片組裝成IP片段。分片重組器處理重組完數(shù)據(jù)包后,它便簡單地將重組片段發(fā)回后續(xù)的IP數(shù)據(jù)包處理過程。IP數(shù)據(jù)包這個主處理過程與分片重組器是獨立的協(xié)程,因此可以實現(xiàn)完全的并行和并發(fā),代碼也更簡潔可讀。

(4)在清理分片時,C語言的Tapip需要顯性地釋放每一個內(nèi)存緩存區(qū),代碼如下:

struct pkbuf *pkb;

list_del(& frag->frag_list);

while (!list_empty(& frag->frag_pkb)) {

pkb=frag_head_pkb(frag);

list_del(& pkb->pk_list);

free_pkb(pkb);

}

free(frag);

而Go語言只需跟蹤通道即可:

delete(ipr.fragBuf, bufID)

Go語言的簡潔友好可讀由此可見一斑。

3.3 延 遲

1個ping請求時,Tapip的0.074 ms優(yōu)于NStack的0.234 ms,但是隨著并發(fā)請求的增加,當(dāng)1 000個ping請求時,NStack的延遲為0.717 ms,差不多比Tapip的3.279 ms好5倍。NStack在連接數(shù)為600時,開始領(lǐng)先于Tapip。NStack延遲的增加是線性的,而Tapip是指數(shù)型的。NStack的延遲趨勢是優(yōu)于Tapip的,因為在請求數(shù)很少時,兩者之間延遲的差距很小,可以忽略不計,但是在大量并發(fā)ping時,差異就明顯變大,如圖3所示。

圖3 并發(fā)延遲性測試結(jié)果

基于圖3的結(jié)果,可以得出Tapip能非常快地處理小量級的數(shù)據(jù)包,而對于大量的數(shù)據(jù)包涌入時,則顯得處理乏力,性能極差。相對應(yīng)的,NStack會用相對較長的時間來處理每個數(shù)據(jù)包,但是因為其在每個協(xié)議實現(xiàn)中良好的并發(fā)控制,在負(fù)載大量增加的情況下,幾乎不影響其處理性能。表現(xiàn)出來便是結(jié)果中,Tapip雖然開始性能優(yōu)秀,但延遲卻隨著并發(fā)量的增長,迅速增大上升,而NStack則小幅平緩的增加。Tapip陡峭的增長趨勢凸顯了其底層架構(gòu)的問題,即在所有的協(xié)議層處理完一個數(shù)據(jù)包后,再處理下一個數(shù)據(jù)包,這種做法不是一個高效的方法,因為這會導(dǎo)致擴展或并發(fā)難以實現(xiàn)。

3.4 吞吐量

測試結(jié)果如圖4所示,1個并發(fā)連接時,NStack的吞吐量達(dá)到7.3 Mbit/s,而Tapip的只有4.6 Mbit/s。當(dāng)100個并發(fā)連接時,NStack達(dá)到了284.9 Mbit/s,而Tapip則只有195 Mbit/s。并且,NStack的吞吐量增加速度比Tapip快得多。這表明NStack可以繼續(xù)在更大量的并發(fā)情況下擴展吞吐量而Tapip則很可能處理不了這種負(fù)載。

圖4 并發(fā)吞吐量測試結(jié)果

結(jié)果有力地驗證了NStack的架構(gòu)。在Tapip里,所有的傳輸控制塊(transmission control block,TCB)都是由單個線程管理的;相應(yīng)的,在NStack中,每個TCB由兩個線程進行管理,分別負(fù)責(zé)一半的上下行連接,因而NStack可以更高效地在有限的CPU核數(shù)上多路復(fù)用大量的連接,可以達(dá)到更大的吞吐量。在小量并發(fā)連接時,NStack也工作地更高效,因為它把TCB的處理工作拆分為兩個Go協(xié)程,而Tapip則自始至終都是一個線程執(zhí)行處理任務(wù)。

4 結(jié)束語

操作系統(tǒng)內(nèi)核對于管理計算機系統(tǒng)資源而言是十分重要的核心組件,如何在兼顧性能的前提下,引入高級語言進行開發(fā),降低低級語言開發(fā)內(nèi)核帶來的復(fù)雜性和安全隱患是該文的初衷。該文以內(nèi)核的網(wǎng)絡(luò)堆棧子系統(tǒng)為出發(fā)點,用Go語言實現(xiàn)NStack,研究高級語言開發(fā)內(nèi)核的可行性和便利性。NStack和對比實驗的C語言開發(fā)的Tapip都是基于tap接口,都實現(xiàn)了相類似的協(xié)議,比如IPv4,ARP,UDP和TCP。在延遲性和吞吐量的對比實驗中,可以發(fā)現(xiàn)NStack有優(yōu)秀的性能表現(xiàn),在延遲性測試中,當(dāng)并發(fā)數(shù)大于600時,NStack取得更低的延時;在吞吐量的測試中,NStack的并行化讓其在所有的測試場景中都取得了優(yōu)于Tapip的吞吐量。

實驗表明,Go語言帶來的簡潔和模塊化可以提供優(yōu)于C語言的幫助,用Go開發(fā)內(nèi)核子系統(tǒng)可以改善代碼的可讀性和可靠性,結(jié)構(gòu)模塊清晰,良好的并發(fā)能力和穩(wěn)定性,同時又對內(nèi)核整體性能沒有產(chǎn)生重大不良影響。結(jié)果表明,對于內(nèi)核開發(fā)來說,Go語言可以是一個重要的C語言替代者。

猜你喜歡
語言
詩之新,以語言創(chuàng)造為基
中華詩詞(2023年8期)2023-02-06 08:51:28
語言是刀
文苑(2020年4期)2020-05-30 12:35:30
讓語言描寫搖曳多姿
多向度交往對語言磨蝕的補正之道
累積動態(tài)分析下的同聲傳譯語言壓縮
日常語言與播音語言
新聞傳播(2016年10期)2016-09-26 12:15:04
語言技能退化與語言瀕危
我有我語言
論語言的“得體”
語文知識(2014年10期)2014-02-28 22:00:56
Only Words慎用你的語言
主站蜘蛛池模板: 丰满人妻久久中文字幕| 在线视频亚洲色图| 亚洲欧美国产五月天综合| 久久精品一卡日本电影| 欧美a在线看| 热久久这里是精品6免费观看| 四虎亚洲精品| 亚洲精品爱草草视频在线| 国产迷奸在线看| 亚洲欧美不卡中文字幕| 亚洲av日韩av制服丝袜| 久久黄色一级片| 日韩精品一区二区三区免费在线观看| 色婷婷色丁香| 国产96在线 | 久久亚洲日本不卡一区二区| 91无码人妻精品一区二区蜜桃| 国产亚洲高清在线精品99| 97亚洲色综久久精品| 亚洲成在线观看| 91福利一区二区三区| 日本不卡在线播放| 亚洲视频无码| 国产毛片高清一级国语| 久久永久精品免费视频| 亚洲无码在线午夜电影| 亚洲无码免费黄色网址| 毛片免费视频| 国产成年女人特黄特色毛片免| 91亚洲视频下载| 新SSS无码手机在线观看| 国产在线专区| 国产欧美日韩精品第二区| 国产成人精品午夜视频'| 日韩国产另类| 亚洲av片在线免费观看| 欧美激情综合| 亚洲人成网站18禁动漫无码| 亚洲成人精品久久| 欧美激情综合一区二区| 色亚洲成人| 婷婷综合色| 国产精品高清国产三级囯产AV| 蜜臀av性久久久久蜜臀aⅴ麻豆| 狠狠色综合网| 国产肉感大码AV无码| 四虎影视8848永久精品| 亚洲色无码专线精品观看| 久久www视频| 久久黄色免费电影| 在线欧美日韩国产| 中文毛片无遮挡播放免费| 日韩精品亚洲精品第一页| 欧美日一级片| 美女扒开下面流白浆在线试听 | 亚洲欧洲日产国码无码av喷潮| 中文无码精品A∨在线观看不卡 | 一级毛片免费高清视频| 精品成人一区二区三区电影| 国产理论一区| 97综合久久| 国产三区二区| 国产高清在线观看91精品| 久久综合一个色综合网| 国产精品女熟高潮视频| 伊人久久精品无码麻豆精品| 国产喷水视频| 国产精品久久久久久搜索| 亚洲最新网址| 亚洲天堂成人| 欧美日韩国产在线观看一区二区三区 | 国产在线98福利播放视频免费| 国产成人三级| 亚洲a免费| 国产精品手机在线观看你懂的 | 日本a级免费| 成人福利在线视频| 国国产a国产片免费麻豆| 免费中文字幕在在线不卡 | 国产白浆视频| 成人国产一区二区三区| 日韩欧美综合在线制服|