.net下的初、中、高級問題

以下是轉貼:作者:觀海看雲

 

描述線程與進程的區別?

線程是比進程更小的處理模塊。
進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的併發性。進程和線程的區別在於:

簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.
線程的劃分尺度小於進程,使得多線程程序的併發性高。
另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以併發執行.

 

線程的引入:例如,有一個Web服務器要進程的方式併發地處理來自不同用戶的網頁訪問請求的話,可以創建父進程和多個子進程的方式來進行處理,但是創建一個進程要花費較大的系統開銷和佔用較多的資源。除外,這些不同的用戶子進程在執行的時候涉及到進程上下文切換,上下文切換是一個複雜的過程。所以,爲了減少進程切換和創建的開銷,提高執行效率和節省資源,人們在操作系統中引入了"線程(thread"的概念。

 進程的作用和定義:進程是爲了提高CPU的執行效率,減少因爲程序等待帶來的CPU空轉以及其他計算機軟硬件資源的浪費而提出來的。進程是爲了完成用戶任務所需要的程序的一次執行過程和爲其分配資源的一個基本單位,是一個具有獨立功能的程序段對某個數據集的一次執行活動。

 

線程和進程的區別:

      1、線程是進程的一部分,所以線程有的時候被稱爲是輕權進程或者輕量級進程。

      2、一個沒有線程的進程是可以被看作單線程的,如果一個進程內擁有多個進程,進程的執行過程不是一條線(線程)的,而是多條線(線程)共同完成的。

      3、系統在運行的時候會爲每個進程分配不同的內存區域,但是不會爲線程分配內存(線程所使用的資源是它所屬的進程的資源),線程組只能共享資源。那就是說,出了CPU之外(線程在運行的時候要佔用CPU資源),計算機內部的軟硬件資源的分配與線程無關,線程只能共享它所屬進程的資源。

      4、與進程的控制表PCB相似,線程也有自己的控制表TCB,但是TCB中所保存的線程狀態比PCB表中少多了。

      5、進程是系統所有資源分配時候的一個基本單位,擁有一個完整的虛擬空間地址,並不依賴線程而獨立存在。

          進程與程序的區別:

      程序是一組指令的集合,它是靜態的實體,沒有執行的含義。而進程是一個動態的實體,有自己的生命週期。一般說來,一個進程肯定與一個程序相對應,並且只有一個,但是一個程序可以有多個進程,或者一個進程都沒有。除此之外,進程還有併發性和交往性。簡單地說,進程是程序的一部分,程序運行的時候會產生進程。

 

總結:

      線程是進程的一部分,進程是程序的一部分。

 

 

什麼是Windows服務,它的生命週期與標準的EXE程序有什麼不同

 

Windows Service 是主要用於服務器環境而長期運行的應用程序, 這類程序不需要有用戶界面或者任何模擬輸出。 任何的用戶消息通常都是記錄在Windows 事件日誌裏。Windows Service可以在操作系統啓動的時候開始,一直在後臺運行,當有需要時也可以手動啓動,我們可以通過管理工具裏面的服務進行統一管理。

當系統啓動完畢後,Windows服務並不需要通過登陸頁面後才能啓動,而我們啓動一般的exe文件卻要先登陸Windows後才能啓動它。

 

Windows Service 是一種可隨 Windows 操作系統啓動而啓動的,在後臺運行的,通常不和用戶產生交互的程序。它無法通過雙擊來運行,類似於 Unix 守護進程(daemon processes),當用戶註銷時它也不會停止。

Windows 服務由三部分組成:1.一個服務可執行文件;2.一個服務控制程序(SCP);3.服務控制管理器(SCM),負責在 HKLM/SYSTEM/CurrentControlSet/Services 下創建服務鍵值。用戶可通過 SCP 控制服務的啓動、停止、暫停等,SCP 會通過 SCM 調用服務程序。

Window 標準的exe可執行程序通常有一個用戶界面,Console或GUI,通常由用戶來啓動或停止

 

Windows服務是運行在windows後臺指定用戶下(默認System)的應用程序,它沒有標準的UI界面,想比標準的EXE程序,Windows服務是在服務開始的時候創建,而在服務結束的時候銷燬,而且可以設置服務是否與操作系統一起啓動,一起關閉。它支持三種方式:1)自動方式 2)手動方式 3)禁用 。自動方式的時候,windows服務將在OS啓動後自動啓動運行,而手動方式則必須手工啓動服務,禁用的情況下服務將不能被啓動。另外標準的EXE默認使用的當前登錄的用戶,而windows服務則默認使用System用戶,這在對系統資源訪問的時候特別需要注意。

 

 

Windows上的單個進程所能訪問的最大內存量是多少?它與系統的最大虛擬內存一樣嗎?這對於系統設計有什麼影響?

 

32 Windows上單個進程所能訪問的最大內存量是4G,單由於操作系統需要給系統核心分配2G的空間,所以一般用戶程序的進程可使用的最大內存爲2G

不一定一樣,32位的操作系統的進程可訪問的最大內存量是4G,這4G包含了虛擬內存,而一個進程可訪問的最大內存量也是4G,所以進程內存訪問量在物理內存大於等於4G的時候跟虛擬內存無關,而當物理內存小於4G時,進程訪問的內存量隨着虛擬內存的增加而增加,直到4G

 

Windows使用一個系統:虛擬尋址系統。該系統把程序可用的內存地址映射到硬件內存中的實際地址上,這些任務完全有Windows後臺管理,其實際結 果是32位處理器上的每個進程都可以使用4GB的內存------無論計算機上有多少硬盤空間(在64位處理器上這個數值會更大)。這個4GB內存實際上 包含了程序的所有部分------包括可執行代碼,代碼加載的所有dll,以及程序運行時使用的所有變量的內容。這個4GB內存稱爲虛擬地址空間,或虛擬 內存。

 

EXE和DLL之間的區別是什麼?

EXE就是可執行文件,你可要雙擊它, 它就可以運行,而DLL是一個動態鏈接庫文件,就是說,它不可以自己運行,它是須要一個程序的其它功能運行的時候,它才能運行,打個比方,如果你的QQ要升級,那QQ裏面有關升級的DLL文件它就會運行.

 

EXE是帶有程序入口(Main)的能被終端用戶直接執行的應用程序,隨着它的啓動系統會產生一個相應的進程。

DLL是動態鏈接庫,不包含程序執行入口,不能被終端用戶直接執行,本身需要附加到現有的進程中才可以運行。

但兩者都是基於PE格式,運行時由磁盤中的映像載入被調用者的內存或者共享空間中執行,包含程序的數據信息,只是EXE還包括程序的代碼信息。

DLL可被多個程序共用,而EXE則不行,只能單獨執行。

 

什麼是強類型,什麼是弱類型?哪種更好些?爲什麼?

 

弱類型語言允許將一塊內存看做多種類型。比如直接將整型變量與字符變量相加。C and C++ 是靜態語言,也是弱類型語言;Perl and PHP 是動態語言,但也是弱類型語言。

強類型語言在沒有強制類型轉化前,不允許兩種不同類型的變量相互操作。Java、C# 和 Python 等都是強類型語言。

使用哪種語言還是要按需而定。編寫簡單小應用,使用弱類型語言可節省很多代碼量,有更高的開發效率。而對於構建大型項目,使用強類型語言可能會比使用弱類型更加規範可靠。

 

強類型是指使用內存中的數據時必須做類型轉化,否則不能使用,弱類型不需要程序轉化,運行時系統自動處理數據直接的類型。

使用強類型的好處:支持智能輸入提示、編譯時檢測出潛在的運行問題、接口中避免數據不一致問題,並且使用強類型可以加快程序的開發速率和程序的運行速度。

 

PID是什麼?在做系統的故障排除時如何使用它?

PID是系統進程的全局唯一標誌符,在排除系統故障時可以根據PID找到對應的進程進而找到對應的程序。

PID = Process Identifier, 是一個全局唯一的用來標識進程的整數。在多任務系統中,可用來診斷系統中發生錯誤的進程。

 

單個TCP/IP端口上能夠偵聽多少個進程?

可能只有一個。如果你需要創建另一個TCP/IP監聽,你必須建立另一個不同的端口

 

什麼是GAC?它解決了什麼問題?

Gloal Assembly Cache,全局應用程序集緩存。它解決了幾個程序共享某一個程序集的問題。不必再將那個被共享的程序集拷貝到應用程序目錄了,其實這道理很簡單,.net應用程序在加載的時候,會首先查看全局應用程序集緩存,如果有就可以直接使用,沒有再到應用程序目錄進行查找。

 

 

每一個CLR(Common Language Runtime)所在的計算機都有一個全局程序集緩存(Global Assembly Cache,GAC)。部署在GAC上的程序集必須有一個強名稱。一種由.net framework sdk提供的名叫 "Global Assembly Cache tool" (Gacutil.exe)的開發工具,可以把程序集部署到GAC上。GAC存儲專門指定的程序集以供計算機上多個應用程序共享。它也爲我們提供了克服"DLL地獄"的問題。

百度百科上的解釋:

GAC全稱是Global Assembly Cache
作用是可以存放一些有很多程序都要用 到的公共Assembly,例如System.Data、System.Windows.Forms等等。這樣,很多程序就可以從GAC裏面取得 Assembly,而不需要再把所有要用到的Assembly都拷貝到應用程序的執行目錄下面。舉例而言,如果沒有GAC,那麼勢必每個WinForm程 序的目錄下就都要從C:/WINDOWS/Microsoft.NET/Framework/v1.0.3705下面拷貝一份 System.Windows.Forms.dll,這樣顯然不如都從GAC裏面取用方便,也有利於Assembly的升級和版本控制。

   除了系統默認放置在GAC中的Assembly如System.Windows.Forms以外,我們也可以添加自己的Assembly:
   1)創建一個strong-name的Assembly,例如ToolbarComponent.dll
   2)運行gacutil -i ToolbarComponent.dll,把這個Assembly添加到GAC
   3)在程序中動態裝載:
   System.Reflection.Assembly ass=Assembly.Load("ToolbarComponent, Version=1.0.934.20434, Culture=neutral, PublicKeyToken=65f45658c8d4927f");
   MessageBox.Show("Is the assembly loaded from GAC? "+ass.GlobalAssemblyCache);
   在 上面的程序中,ToolbarComponent就是從GAC裝載而不是從程序的運行目錄下的dll文件中裝載,程序目錄下不需要放置 ToolbarComponent.dll程序也能正常運行。另外,Assembly.Load()中的參數可以通過"gacutil -l"查到。

   另外,上面提到了GAC中的Assembly必須是strong-name的。創建strong-name的Assembly的步驟大致如下:
   a) 在命令行運行“sn -k keyPair.snk”創建一個密鑰文件。這裏的sn.exe也是.NET附帶的一個工具。
   b) 在VS.NET裏面修改“AssemblyInfo.cs”文件:
   [assembly: AssemblyDelaySign(false)]    
   [assembly: AssemblyKeyFile("..//..//keyPair.snk")]    
   c) 編譯項目,就能得到一個strong-name的Assembly。

   MSDN中有一些對GAC的介紹,您可以參考:
   1)《Assembly Cache Viewer (Shfusion.dll)》
   2)《Global Assembly Cache》

   .NET Framework中附帶了一些和GAC有關的工具,其中包括:
   1)Gacutil.exe,一個命令行的工具,用於在GAC中瀏覽、添加、刪除Assembly
   2)Ngen.exe,也是一個命令行的工具,用於在GAC中創建Native Image
   3)mscorcfg.msc,一個MMC終端,可以圖形化完成Gacutil.exe的主要功能。

 

 

 

  • 闡述面向接口、面向對象、面向方面編程的區別
        面向接口更關注的是概念,它的原則是先定義好行爲規範,再根據行爲規範創建實現,嚴格的來說,面向接口應該是面向對象中的一部分吧,因爲面向對象也強調的是本末倒

    置原則,也就是實現依賴於抽象,而抽象不依賴於具體實現,更具比較的應該是面向接口與面向抽象對象,我的體會是面向接口更加靈活,但實現時候,稍微有些代碼冗餘,而面

    向抽象可以結合面向接口,先定義接口,再定義抽象類,在抽象類中處理一些公共邏輯,再實現具體實現類。面向對象是對複雜問題的分解。面向方面的編程是一種新概念,它解

    決了很多面向對象無法解決的問題,比如面向對象技術只能對業務相關的代碼模塊化,而無法對和業務無關的代碼模塊化。而面向方面正是解決這一問題的方案,它的關鍵思想是"

    將應用程序中的商業邏輯與對其提供支持的通用服務進行分離"。

    什麼是Interface?它與Class有什麼區別?
        接口(Interface)是用來定義行爲規範的,不會有具體實現,而抽象類除定義行爲規範外,可以有部分實現,但一個類能實現多個接口,但只能繼承一個父類 
    接口是是一種契約,定義了繼承它的類必須聲明接口中的方法。
    接口和類的區別:
    接口只有方法、屬性、事件和索引符,並且也只能包含這四種成員;類除了這四種成員之外還可以別的成員(如字段)。
    接口不能實例化,接口只包括成員的簽名;而類可以實例化(abstract類除外)。
    接口沒有構造函數,類有構造函數。
    接口不能進行運算符的重載,類可以進行運算符重載。
    接口的成員沒有任何修飾符,其成員總是公共的,而類的成員則可以有修飾符
    派生於接口的類必須實現接口中所有成員的執行方式,而從類派生的則不然。

    什麼是反射?
        程序集包含模塊,而模塊又包括類型,類型下有成員,反射就是管理程序集,模塊,類型的對象,它能夠動態的創建類型的實例,設置現有對象的類型或者獲取現有對象的類

    型,能調用類型的方法和訪問類型的字段屬性。它是在運行時創建和使用類型實例

    關於什麼事反射,我找了好些資料,有些人說了好多。比如:http://blog.csdn.net/shuilv2000/archive/2009/10/26/4728991.aspx,說了好多,不過個人還是覺得上面的概括更

    好理解。
               

    使用ASMX的XML Web服務與使用SOAP的.NET Remoting的區別?
        Web 服務基礎結構通過將 SOAP 消息映射到方法調用,爲 Web 服務提供了簡單的 API。通過提供一種非常簡單的編程模型(基於將 SOAP 消息交換映射到方法調用),它實現

    了此機制。ASP.NET Web 服務的客戶端不需要了解用於創建它們的平臺、對象模型或編程語言。而服務也不需要了解向它們發送消息的客戶端。唯一的要求是:雙方都要認可正在

    創建和使用的 SOAP 消息的格式,該格式是由使用 WSDL 和 XML 架構 (XSD) 表示的 Web 服務合約定義來定義的。 
        . NET Remoting 爲分佈式對象提供了一個基礎結構。它使用既靈活又可擴展的管線向遠程進程提供 .NET 的完全對象語義。ASP.NET Web 服務基於消息傳遞提供非常簡單的編

    程模型,而 .NET Remoting 提供較爲複雜的功能,包括支持通過值或引用傳遞對象、回調,以及多對象激活和生命週期管理策略等。要使用 .NET Remoting,客戶端需要了解所有

    這些詳細信息,簡而言之,需要使用 .NET 建立客戶端。.NET Remoting 管線還支持 SOAP 消息,但必須注意這並沒有改變其對客戶端的要求。如果 Remoting 端點提供 .NET 專

    用的對象語義,不管是否通過 SOAP,客戶端必須理解它們。

    Web服務客戶端不需要了解服務創建的平臺、對象模型和編程語言,而.NET Remoting需要了解這些信息,而且客戶端需要用.NET Framework開發
    Web 服務通過XML傳遞消息,.NET Remoting可以通過值或引用傳遞對象、回調,以及多對象激活和生命週期管理策略等
    Web服務使用的消息機制,而Remoting採用的RPC. Web Service能用於不同平臺,不同語言,Remoting只適用於.Net。效率上Remoting高於Xml Web Service

    類型系統是由XMLSchema表示的嗎?CLS是XMLSchema表示的嗎?
        這個不清楚,在網上找了哈,也沒看到對這方面的介紹。希望高手指點。

    從概念上闡述前期綁定(early-binding)和後期綁定(late-binding)的區別?
        前期綁定是指在編譯時就綁定了變量的類型或者方法的實體,而後期綁定是在運行時根據不同的需要綁定不同的類型或者方法實體。所以前期綁定如果失敗,會在編譯時報編

    譯錯誤,而後期綁定失敗只有在運行時的時候才發生

    調用Assembly.Load算靜態引用還是動態引用?
        動態
        關於Assembly.Load這位老兄講得比較基礎:http://hi.baidu.com/zhanghaooy/blog/item/b12aba0e62313cc07bcbe1b2.html

    Assembly.Load()方法,Assembly.LoadFrom()方法,Assembly.LoadFile()方法的區別!
         1.Assembly.Load()
             這個方法通過程序集的長名稱(包括程序集名,版本信息,語言文化,公鑰標記)來加載程序集的,會加載此程序集引用的其他程序集,一般情況下都應該優先使用 這

    個方法,他的執行效率比LoadFrom要高很多,而且不會造成重複加載的問題(原因在第2點上說明)
             使用這個方法的時候, CLR會應用一定的策略來查找程序集,實際上CLR按如下的順序來定位程序集:
    ⑴如果程序集有強名稱,在首先在全局程序集緩(GAC)中查找程序集。         
    ⑵如果程序集的強名稱沒有正確指定或GAC中找不到,那麼通過配置文件中的<codebase>元素指定的URL來查找
    ⑶如果沒有指定強名稱或是在GAC中找不到,CLR會探測特定的文件夾:
         假設你的應用程序目錄是C:/AppDir,<probing>元素中的privatePath指定了一個路徑Path1,你要定位的程序集是AssemblyName.dll則CLR將按照如下順序定位程序集
              C:/AppDir/AssemblyName.dll
              C:/AppDir/AssemblyName/AssemblyName.dll
              C:/AppDir/Path1/AssemblyName.dll
              C:/AppDir/Path1/AssemblyName/AssemblyName.dll
    如果以上方法不能找到程序集,會發生編譯錯誤,如果是動態加載程序集,會在運行時拋出異常!
         2,Assembly.LoadFrom()
              這個方法從指定的路徑來加載程序集,實際上這個方法被調用的時候,CLR會打開這個文件,獲取其中的程序集版本,語言文化,公鑰標記等信息,把他們傳遞給 Load

    方法,接着,Load方法採用上面的策略來查找程序集。如果找到了程序集,會和LoadFrom方法中指定的路徑做比較,如果路徑相同,該程序集 會被認爲是應用程序的一部分,如果

    路徑不同或Load方法沒有找到程序集,那該程序集只是被作爲一個“數據文件”來加載,不會被認爲是應用程序的一部分。 這就是在第1點中提到的Load方法比LoadFrom方法的執

    行效率高的原因。另外,由於可能把程序集作爲“數據文件”來加載,所以使用 LoadFrom從不同路徑加載相同程序集的時候會導致重複加載。當然這個方法會加載此程序集引用的

    其他程序集。
         3,Assembly.LoadFile()
              這個方法是從指定的文件來加載程序集,和上面方法的不同之處是這個方法不會加載此程序集引用的其他程序集!
         結論:一般大家應該優先選擇Load方法來加載程序集,如果遇到需要使用LoadFrom方法的時候,最好改變設計而用Load方法來代替!

    Assembly.LoadFile 與 Assembly.LoadFrom的區別
    1、Assembly.LoadFile只載入相應的dll文件,比如Assembly.LoadFile("abc.dll"),則載入abc.dll,假如abc.dll中引用了def.dll的話,def.dll並不會被載入。
    Assembly.LoadFrom則不一樣,它會載入dll文件及其引用的其他dll,比如上面的例子,def.dll也會被載入。
    2、用Assembly.LoadFrom載入一個Assembly時,會先檢查前面是否已經載入過相同名字的Assembly,比如abc.dll有兩個版本(版本1在目錄1下,版本2放在目錄2下),程序一開始時

    載入了版本1,當使用Assembly.LoadFrom("2//abc.dll")載入版本2時,不能載入,而是返回版本1。Assembly.LoadFile的話則不會做這樣的檢查,比如上面的例子換成

    Assembly.LoadFile的話,則能正確載入版本2。
     

    何時使用Assembly.LoadFrom?何時使用Assembly.LoadFile?
        呵呵,這個比較有意思,相比LoadFile,LoadFrom則顯得不地道,因爲它娶媳婦的時候,是讓人家穿上嫁妝,坐上馬車,還得帶着人家的妹妹來,用它加載的是程序集,這就要

    求同時將此程序集所依賴的程序集加載進來。而LoadFile就地道的多,它是加載程序集文件的內容,只將傳入參數的文件加載,不考慮程序集依賴,但如果有相同實現,但位置不

    同的文件用LoadFrom是不能同時加載進來的,而LoadFile卻可以。由於LoadFile加載的是文件,所以調用它之後,可能因爲缺少必要的依賴造成無法被執行。

    什麼叫Assembly Qualified Name?它是一個文件名嗎?它有什麼不同?
        它不是一個文件名,相比文件名,Assembly Qualified Name(程序集限定名稱),更能確定一個程序集,它包含文件名,但同時包含版本,公鑰,和區域。因爲同樣一個名稱

    的文件可能有不同的版本和區域,此時單獨靠文件名稱,可能會造成不能確定程序集的正確性。

    Assembly.Load("foo.dll"); 這句話是否正確?
    正確

    做強簽名的assembly與不做強簽名的assembly有什麼不同?
    強簽名的程序集可以做成com,而不做強簽名的就不行,同樣強簽名程序集可以安裝到GAC中,而不做強簽名的確不能。

    DateTime是否可以爲null?
    不能,因爲其爲Struct類型,而結構屬於值類型,值類型不能爲null,只有引用類型才能被賦值null

    什麼叫JIT?什麼是NGEN?它們分別有什麼限制和好處?
    Just In Time 及時編譯,它是在程序第一次運行的時候才進行編譯,而NGEN是所謂的pre-jit,就是說在運行前事先就將生成程序集的本機鏡像,並保存到全局緩存中,適用NGEN

    可以提高程序集的加載和執行速度,因爲它可以從本機映像中還原數代碼和數據結構,而不必像jit那樣動態生成它們。感覺和緩存的道理大同小異,也就是傳說中的預編譯。

    .NET CLR中一代的垃圾收集器是如何管理對象的生命週期的?什麼叫非確定性終結?

     
    Finalize()和Dispose()之間的區別?
    Finalize()用於釋放非託管資源,Dispose()用於釋放託管資源

    using() 語法有用嗎?什麼是IDisposable?它是如何實現確定性終結的。
    有用,實現了IDisposiable的類在using中創建,using結束後會自定調用該對象的Dispose方法,釋放資源。簡單的說調用IDisposable的Dispose方法能移除這個對象所使用資源的

    引用,從而達到讓垃圾收集器回收資源的目的。
     
    tasklist /m "mscor*" 這句命令是幹嘛的?
    列出所有使用了以" mscor"作爲開頭的dll或者exe的進程和模塊信息

    in-proc和out-of-proc的區別
    in-proc是進程內,進程內能共享代碼和數據塊,out-of-proc是進程外,進程外的互操作需要用進程間通訊來實現。

    .NET裏的哪一項技術能夠實現out-of-proc通訊?
    .Net Remoting技術或者WCF技術

    當你在ASP.NET中運行一個組件時,它在Windows XP, Windows 2000, Windows 2003上分別跑在哪個進程裏面?
    Xp : aspnet_Wp.exe
    Windows 2000 : inetinfo.exe
    Windows 2003 : w3wp.exe  

     觀海看雲:http://www.cnblogs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章