www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 程序喵大人
[導(dǎo)讀]進(jìn)程和線程這兩個(gè)話題是程序員繞不開的,操作系統(tǒng)提供的這兩個(gè)抽象概念實(shí)在是太重要了。 關(guān)于進(jìn)程和線程有一個(gè)極其經(jīng)典的問(wèn)題,那就是進(jìn)程和線程的區(qū)別是什么?相信很多同學(xué)對(duì)答案似懂非懂。

進(jìn)程和線程這兩個(gè)話題是程序員繞不開的,操作系統(tǒng)提供的這兩個(gè)抽象概念實(shí)在是太重要了。
關(guān)于進(jìn)程和線程有一個(gè)極其經(jīng)典的問(wèn)題,那就是進(jìn)程和線程的區(qū)別是什么?相信很多同學(xué)對(duì)答案似懂非懂。

記住了不一定真懂

關(guān)于這個(gè)問(wèn)題有的同學(xué)可能已經(jīng)“背得”滾瓜爛熟了:“進(jìn)程是操作系統(tǒng)分配資源的單位,線程是調(diào)度的基本單位,線程之間共享進(jìn)程資源”。
可是你真的理解了上面最后一句話嗎?到底線程之間共享了哪些進(jìn)程資源,共享資源意味著什么?共享資源這種機(jī)制是如何實(shí)現(xiàn)的?對(duì)此如果你沒(méi)有答案的話,那么這意味著你幾乎很難寫出能正確工作的多線程程序,同時(shí)也意味著這篇文章就是為你準(zhǔn)備的。

逆向思考

查理芒格經(jīng)常說(shuō)這樣一句話:“反過(guò)來(lái)想,總是反過(guò)來(lái)想”,如果你對(duì)線程之間共享了哪些進(jìn)程資源這個(gè)問(wèn)題想不清楚的話那么也可以反過(guò)來(lái)思考,那就是有哪些資源是線程私有的
?

線程私有資源

線程運(yùn)行的本質(zhì)其實(shí)就是函數(shù)的執(zhí)行,函數(shù)的執(zhí)行總會(huì)有一個(gè)源頭,這個(gè)源頭就是所謂的入口函數(shù),CPU從入口函數(shù)開始執(zhí)行從而形成一個(gè)執(zhí)行流,只不過(guò)我們?nèi)藶榈慕o執(zhí)行流起一個(gè)名字,這個(gè)名字就叫線程。
既然線程運(yùn)行的本質(zhì)就是函數(shù)的執(zhí)行,那么函數(shù)執(zhí)行都有哪些信息呢?
在《函數(shù)運(yùn)行時(shí)在內(nèi)存中是什么樣子》這篇文章中我們說(shuō)過(guò),函數(shù)運(yùn)行時(shí)的信息保存在棧幀中,棧幀中保存了函數(shù)的返回值、調(diào)用其它函數(shù)的參數(shù)、該函數(shù)使用的局部變量以及該函數(shù)使用的寄存器信息,如圖所示,假設(shè)函數(shù)A調(diào)用函數(shù)B:

此外,CPU執(zhí)行指令的信息保存在一個(gè)叫做程序計(jì)數(shù)器的寄存器中,通過(guò)這個(gè)寄存器我們就知道接下來(lái)要執(zhí)行哪一條指令。由于操作系統(tǒng)隨時(shí)可以暫停線程的運(yùn)行,因此我們保存以及恢復(fù)程序計(jì)數(shù)器中的值就能知道線程是從哪里暫停的以及該從哪里繼續(xù)運(yùn)行了。
由于線程運(yùn)行的本質(zhì)就是函數(shù)運(yùn)行,函數(shù)運(yùn)行時(shí)信息是保存在棧幀中的,因此每個(gè)線程都有自己獨(dú)立的、私有的棧區(qū)。

同時(shí)函數(shù)運(yùn)行時(shí)需要額外的寄存器來(lái)保存一些信息,像部分局部變量之類,這些寄存器也是線程私有的,一個(gè)線程不可能訪問(wèn)到另一個(gè)線程的這類寄存器信息。
從上面的討論中我們知道,到目前為止,所屬線程的棧區(qū)、程序計(jì)數(shù)器、棧指針以及函數(shù)運(yùn)行使用的寄存器是線程私有的。
以上這些信息有一個(gè)統(tǒng)一的名字,就是線程上下文,thread context。
我們也說(shuō)過(guò)操作系統(tǒng)調(diào)度線程需要隨時(shí)中斷線程的運(yùn)行并且需要線程被暫停后可以繼續(xù)運(yùn)行,操作系統(tǒng)之所以能實(shí)現(xiàn)這一點(diǎn),依靠的就是線程上下文信息。
現(xiàn)在你應(yīng)該知道哪些是線程私有的了吧。
除此之外,剩下的都是線程間共享資源。
那么剩下的還有什么呢?還有圖中的這些。

這其實(shí)就是進(jìn)程地址空間的樣子,也就是說(shuō)線程共享進(jìn)程地址空間中除線程上下文信息中的所有內(nèi)容,意思就是說(shuō)線程可以直接讀取這些內(nèi)容。
接下來(lái)我們分別來(lái)看一下這些區(qū)域。
?

代碼區(qū)

進(jìn)程地址空間中的代碼區(qū),這里保存的是什么呢?從名字中有的同學(xué)可能已經(jīng)猜到了,沒(méi)錯(cuò),這里保存的就是我們寫的代碼,更準(zhǔn)確的是編譯后的可執(zhí)行機(jī)器指令。
那么這些機(jī)器指令又是從哪里來(lái)的呢?答案是從可執(zhí)行文件中加載到內(nèi)存的,可執(zhí)行程序中的代碼區(qū)就是用來(lái)初始化進(jìn)程地址空間中的代碼區(qū)的。

線程之間共享代碼區(qū),這就意味著程序中的任何一個(gè)函數(shù)都可以放到線程中去執(zhí)行,不存在某個(gè)函數(shù)只能被特定線程執(zhí)行的情況。
?

?數(shù)據(jù)區(qū)

進(jìn)程地址空間中的數(shù)據(jù)區(qū),這里存放的就是所謂的全局變量。
什么是全局變量?所謂全局變量就是那些你定義在函數(shù)之外的變量,在C語(yǔ)言中就像這樣:
    
char c; // 全局變量
void func() { }
其中字符c就是全局變量,存放在進(jìn)程地址空間中的數(shù)據(jù)區(qū)。

在程序員運(yùn)行期間,也就是run time,數(shù)據(jù)區(qū)中的全局變量有且僅有一個(gè)實(shí)例,所有的線程都可以訪問(wèn)到該全局變量
值得注意的是,在C語(yǔ)言中還有一類特殊的“全局變量”,那就是用static關(guān)鍵詞修飾過(guò)的變量,就像這樣:
    
void func(){ static int a = 10; }
注意到, 雖然變量a定義在函數(shù)內(nèi)部,但變量a依然具有全局變量的特性 ,也就是說(shuō)變量a放在了進(jìn)程地址空間的數(shù)據(jù)區(qū)域, 即使函數(shù)執(zhí)行完后該變量依然存在 ,而普通的局部變量隨著函數(shù)調(diào)用結(jié)束和函數(shù)棧幀一起被回收掉了,但這里的變量a不會(huì)被回收,因?yàn)槠浔环诺搅藬?shù)據(jù)區(qū)。
這樣的變量對(duì)每個(gè)線程來(lái)說(shuō)也是可見(jiàn)的,也就是說(shuō)每個(gè)線程都可以訪問(wèn)到該變量。
?

堆區(qū)

堆區(qū)是程序員比較熟悉的,我們?cè)贑/C++中用malloc或者new出來(lái)的數(shù)據(jù)就存放在這個(gè)區(qū)域,很顯然,只要知道變量的地址,也就是指針,任何一個(gè)線程都可以訪問(wèn)指針指向的數(shù)據(jù),因此堆區(qū)也是線程共享的屬于進(jìn)程的資源。

?

棧區(qū)

唉,等等!剛不是說(shuō)棧區(qū)是線程私有資源嗎,怎么這會(huì)兒又說(shuō)起棧區(qū)了?
確實(shí),從線程這個(gè)抽象的概念上來(lái)說(shuō),棧區(qū)是線程私有的,然而從實(shí)際的實(shí)現(xiàn)上看,棧區(qū)屬于線程私有這一規(guī)則并沒(méi)有嚴(yán)格遵守,這句話是什么意思?
通常來(lái)說(shuō),注意這里的用詞是通常,通常來(lái)說(shuō)棧區(qū)是線程私有,既然有通常就有不通常的時(shí)候。
不通常是因?yàn)椴幌襁M(jìn)程地址空間之間的嚴(yán)格隔離,線程的棧區(qū)沒(méi)有嚴(yán)格的隔離機(jī)制來(lái)保護(hù),因此如果一個(gè)線程能拿到來(lái)自另一個(gè)線程棧幀上的指針,那么該線程就可以改變另一個(gè)線程的棧區(qū),也就是說(shuō)這些線程可以任意修改本屬于另一個(gè)線程棧區(qū)中的變量。

這從某種程度上給了程序員極大的便利,但同時(shí),這也會(huì)導(dǎo)致極其難以排查到的bug。
試想一下你的程序運(yùn)行的好好的,結(jié)果某個(gè)時(shí)刻突然出問(wèn)題,定位到出問(wèn)題代碼行后根本就排查不到原因,你當(dāng)然是排查不到問(wèn)題原因的,因?yàn)槟愕某绦虮緛?lái)就沒(méi)有任何問(wèn)題,是別人的問(wèn)題導(dǎo)致你的函數(shù)棧幀數(shù)據(jù)被寫壞從而產(chǎn)生bug,這樣的問(wèn)題通常很難排查到原因,需要對(duì)整體的項(xiàng)目代碼非常熟悉,常用的一些debug工具這時(shí)可能已經(jīng)沒(méi)有多大作用了。
說(shuō)了這么多,那么同學(xué)可能會(huì)問(wèn),一個(gè)線程是怎樣修改本屬于其它線程的數(shù)據(jù)呢?
接下來(lái)我們用一個(gè)代碼示例講解一下。
?

修改線程私有數(shù)據(jù)

不要擔(dān)心,以下代碼足夠簡(jiǎn)單:
void thread(void* var) { int* p = (int*)var; *p = 2;}
int main() {????int?a?=?1; pthread_t tid; pthread_create(&tid, NULL, thread, (void*)&a); return 0;}
這段代碼是什么意思呢?
首先我們?cè)谥骶€程的棧區(qū)定義了一個(gè)局部變量,也就是 int a= 1這行代碼,現(xiàn)在我們已經(jīng)知道了,局部變量a屬于主線程私有數(shù)據(jù),但是,接下來(lái)我們創(chuàng)建了另外一個(gè)線程。
在新創(chuàng)建的這個(gè)線程中,我們將變量a的地址以參數(shù)的形式傳給了新創(chuàng)建的線程,然后我來(lái)看一下thread函數(shù)。
在新創(chuàng)建的線程中,我們獲取到了變量a的指針,然后將其修改為了2,也就是這行代碼,我們?cè)谛聞?chuàng)建的線程中修改了本屬于主線程的私有數(shù)據(jù)。

現(xiàn)在你應(yīng)該看明白了吧,盡管棧區(qū)是線程的私有數(shù)據(jù),但由于棧區(qū)沒(méi)有添加任何保護(hù)機(jī)制,一個(gè)線程的棧區(qū)對(duì)其它線程是可以見(jiàn)的,也就是說(shuō)我們可以修改屬于任何一個(gè)線程的棧區(qū)。
就像我們上文說(shuō)得到的,這給程序員帶來(lái)了極大便利的同時(shí)也帶來(lái)了無(wú)盡的麻煩,試想上面這段代碼,如果確實(shí)是項(xiàng)目需要那么這樣寫代碼無(wú)可厚非,但如果上述新創(chuàng)建線程是因bug修改了屬于其它線程的私有數(shù)據(jù)的話,那么產(chǎn)生問(wèn)題就很難定位了,因?yàn)閎ug可能距離問(wèn)題暴露的這行代碼已經(jīng)很遠(yuǎn)了,這樣的問(wèn)題通常難以排查。
?

動(dòng)態(tài)鏈接庫(kù)

進(jìn)程地址空間中除了以上討論的這些實(shí)際上還有其它內(nèi)容,還有什么呢?
這就要從可執(zhí)行程序說(shuō)起了。
什么是可執(zhí)行程序呢?在Windows中就是我們熟悉的exe文件,在Linux世界中就是ELF文件,這些可以被操作系統(tǒng)直接運(yùn)行的程序就是我們所說(shuō)的可執(zhí)行程序。
那么可執(zhí)行程序是怎么來(lái)的呢?
有的同學(xué)可能會(huì)說(shuō),廢話,不就是編譯器生成的嗎?
實(shí)際上這個(gè)答案只答對(duì)了一半。
假設(shè)我們的項(xiàng)目比較簡(jiǎn)單只有幾個(gè)源碼文件,編譯器是怎么把這幾個(gè)源代碼文件轉(zhuǎn)換為最終的一個(gè)可執(zhí)行程序呢?
原來(lái),編譯器在將可執(zhí)行程序翻譯成機(jī)器指令后,接下來(lái)還有一個(gè)重要的步驟,這就是鏈接,鏈接完成后生成的才是可執(zhí)行程序。
完成鏈接這一過(guò)程的就是鏈接器。

其中鏈接器可以有兩種鏈接方式,這就是靜態(tài)鏈接動(dòng)態(tài)鏈接
靜態(tài)鏈接的意思是說(shuō)把所有的機(jī)器指令一股腦全部打包到可執(zhí)行程序中,動(dòng)態(tài)鏈接的意思是我們不把動(dòng)態(tài)鏈接的部分打包到可執(zhí)行程序,而是在可執(zhí)行程序運(yùn)行起來(lái)后去內(nèi)存中找動(dòng)態(tài)鏈接的那部分代碼,這就是所謂的靜態(tài)鏈接和動(dòng)態(tài)鏈接。
動(dòng)態(tài)鏈接一個(gè)顯而易見(jiàn)的好處就是可執(zhí)行程序的大小會(huì)很小,就像我們?cè)赪indows下看一個(gè)exe文件可能很小,那么該exe很可能是動(dòng)態(tài)鏈接的方式生成的
而動(dòng)態(tài)鏈接的部分生成的庫(kù)就是我們熟悉的動(dòng)態(tài)鏈接庫(kù),在Windows下是以DLL結(jié)尾的文件,在Linux下是以so結(jié)尾的文件。
說(shuō)了這么多,這和線程共享資源有什么關(guān)系呢?
原來(lái)如果一個(gè)程序是動(dòng)態(tài)鏈接生成的,那么其地址空間中有一部分包含的就是動(dòng)態(tài)鏈接庫(kù),否則程序就運(yùn)行不起來(lái)了,這一部分的地址空間也是被所有線程所共享的。

也就是說(shuō)進(jìn)程中的所有線程都可以使用動(dòng)態(tài)鏈接庫(kù)中的代碼。
以上其實(shí)是關(guān)于鏈接這一主題的極簡(jiǎn)介紹,關(guān)于鏈接這一話題的詳細(xì)討論可以參考《徹底理解鏈接器》系列文章。
?

文件

最后,如果程序在運(yùn)行過(guò)程中打開了一些文件,那么進(jìn)程地址空間中還保存有打開的文件信息,進(jìn)程打開的文件也可以被所有的線程使用,這也屬于線程間的共享資源。

?

?One More Thing:TLS

本文就這些了嗎?
實(shí)際上關(guān)于線程私有數(shù)據(jù)還有一項(xiàng)沒(méi)有詳細(xì)講解,因?yàn)樵僦v下去本篇就撐爆了,而且本篇已經(jīng)講解的部分足夠用了,剩下的這一點(diǎn)僅僅作為補(bǔ)充,也就是選學(xué)部分,如果你對(duì)此不感興趣的話完全可以跳過(guò),沒(méi)有問(wèn)題。
關(guān)于線程私有數(shù)據(jù)還有一項(xiàng)技術(shù),那就是線程局部存儲(chǔ),Thread Local Storage,TLS。
這是什么意思呢?
其實(shí)從名字上也可以看出,所謂線程局部存儲(chǔ),是指存放在該區(qū)域中的變量有兩個(gè)含義:
  • 存放在該區(qū)域中的變量是全局變量,所有線程都可以訪問(wèn)

  • 雖然看上去所有線程訪問(wèn)的都是同一個(gè)變量,但該全局變量獨(dú)屬于一個(gè)線程,一個(gè)線程對(duì)此變量的修改對(duì)其他線程不可見(jiàn)。

說(shuō)了這么多還是沒(méi)懂有沒(méi)有?沒(méi)關(guān)系,接下來(lái)看完這兩段代碼還不懂你來(lái)打我。
我們先來(lái)看第一段代碼,不用擔(dān)心,這段代碼非常非常的簡(jiǎn)單:
int a = 1; // 全局變量
void print_a() { cout<}
void run() { ++a; print_a();}
void main() { thread t1(run); t1.join();
thread t2(run); t2.join();}
怎么樣,這段代碼足夠簡(jiǎn)單吧,上述代碼是用C++11寫的,我來(lái)講解下這段代碼是什么意思。
  • 首先我們創(chuàng)建了一個(gè)全局變量a,初始值為1
  • 其次我們創(chuàng)建了兩個(gè)線程,每個(gè)線程對(duì)變量a加1
  • 線程的join函數(shù)表示該線程運(yùn)行完畢后才繼續(xù)運(yùn)行接下來(lái)的代碼
那么這段代碼的運(yùn)行起來(lái)會(huì)打印什么呢?
全局變量a的初始值為1,第一個(gè)線程加1后a變?yōu)?,因此會(huì)打印2;第二個(gè)線程再次加1后a變?yōu)?,因此會(huì)打印3,讓我們來(lái)看一下運(yùn)行結(jié)果:
23
看來(lái)我們分析的沒(méi)錯(cuò),全局變量在兩個(gè)線程分別加1后最終變?yōu)?。
接下來(lái)我們對(duì)變量a的定義稍作修改,其它代碼不做改動(dòng):
__thread int a = 1; // 線程局部存儲(chǔ)
我們看到全局變量a前面加了一個(gè)__thread關(guān)鍵詞用來(lái)修飾,也就是說(shuō)我們告訴編譯器把變量a放在線程局部存儲(chǔ)中,那這會(huì)對(duì)程序帶來(lái)哪些改變呢?
簡(jiǎn)單運(yùn)行一下就知道了:
22
和你想的一樣嗎?有的同學(xué)可能會(huì)大吃一驚,為什么我們明明對(duì)變量a加了兩次,但第二次運(yùn)行為什么還是打印2而不是3呢?
想一想這是為什么。
原來(lái),這就是線程局部存儲(chǔ)的作用所在,線程t1對(duì)變量a的修改不會(huì)影響到線程t2,線程t1在將變量a加到1后變?yōu)?,但對(duì)于線程t2來(lái)說(shuō)此時(shí)變量a依然是1,因此加1后依然是2。
因此,線程局部存儲(chǔ)可以讓你使用一個(gè)獨(dú)屬于線程的全局變量。也就是說(shuō),雖然該變量可以被所有線程訪問(wèn),但該變量在每個(gè)線程中都有一個(gè)副本,一個(gè)線程對(duì)改變量的修改不會(huì)影響到其它線程。

?

總結(jié)

怎么樣,沒(méi)想到教科書上一句簡(jiǎn)單的“線程共享進(jìn)程資源”背后竟然會(huì)有這么多的知識(shí)點(diǎn)吧,教科書上的知識(shí)看似容易,但,并不簡(jiǎn)單。
希望本篇能對(duì)大家理解進(jìn)程、線程能有多幫助。

往期推薦







免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉