1、TCP和UDP的區別:
1)TCP提供連線導向的傳輸,通訊前要先建立串連(三向交握機制);UDP提供不需連線的傳輸,通訊前不需要建立串連。
2)TCP提供可靠的傳輸(有序,無差錯,不丟失,不重複);UDP提供不可靠的傳輸。
3)TCP面向位元組流的傳輸,因此它能將資訊分割成組,並在接收端將其重組;UDP是面向資料報的傳輸,沒有分組開銷。
4)TCP提供擁塞控制和流量控制機制;UDP不提供擁塞控制和流量控制機制。
2、流量控制和擁塞控制的實現機制:
1)TCP採用大小可變的滑動視窗機制實現流量控制功能。視窗的大小是位元組。在TCP報文段首部的視窗欄位寫入的數值就是當前給對方設定發送視窗的資料的上限。
在資料轉送過程中,TCP提供了一種基於滑動視窗協議的流量控制機制,用接收端接收能力(緩衝區的容量)的大小來控制發送端發送的資料量。
2)採用滑動視窗機制還可對網路進行擁塞控制,將網路中的分組(TCP報文段作為其資料部分)數量維持在一定的數量之下,當超過該數值時,網路的效能會急劇惡化。傳輸層的擁塞控制有慢開始(Slow-Start)、擁塞避免(Congestion Avoidance)、快重傳(Fast Retransmit)和快恢複(Fast Recovery)四種演算法。
擁塞: 大量資料報湧入同一交換節點(如路由器),導致該節點資源耗盡而必須丟棄後面到達的資料報時,就是擁塞。
3、重傳機制:
TCP每發送一個報文段,就設定一次定時器。只要定時器設定的重發時間到而還沒有收到確認,就要重發這一報文段。
TCP環境
報文往返時間不定、有很大差別
A、B在一個區域網路絡,往返時延很小
A、C在一個互連網內,往返時延很大
因此,A很難確定一個固定的、與B、C通訊都適用的定時器時間
TCP採用了一種自適應演算法。這種演算法記錄每一個報文段發出的時間,以及收到相應的確認報文段的時間。這兩個時間之差就是報文段的往返時延。將各個報文段的往返時延樣本加權平均,就得出報文段的平均往返時延T。
4、滑動視窗機制:
TCP 採用大小可變的滑動視窗進行流量控制。視窗大小的單位是位元組。
在 TCP 報文段首部的視窗欄位寫入的數值就是當前給對方設定的發送視窗數值的上限。發送視窗在串連建立時由雙方商定。但在通訊的過程中,接收端可根據自己的資源情況,隨時動態地調整對方的發送視窗上限值(可增大或減小)。
5、多線程如何同步:
臨界區、互斥區、事件、訊號量四種方式
臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)的區別
1)、臨界區:通過對多線程的序列化來訪問公用資源或一段代碼,速度快,適合控制資料訪問。在任意時刻只允許一個線程對共用資源進行訪問,如果有多個線程試圖訪問公用資源,那麼在有一個線程進入後,其他試圖訪問公用資源的線程將被掛起,並一直等到進入臨界區的線程離開,臨界區在被釋放後,其他線程才可以搶佔。
2)、互斥量:採用互斥對象機制。 只有擁有互斥對象的線程才有訪問公用資源的許可權,因為互斥對象只有一個,所以能保證公用資源不會同時被多個線程訪問。互斥不僅能實現同一應用程式的公用資源安全共用,還能實現不同應用程式的公用資源安全共用 .互斥量比臨界區複雜。因為使用互斥不僅僅能夠在同一應用程式不同線程中實現資源的安全共用,而且可以在不同應用程式的線程之間實現對資源的安全共用。
3)、訊號量:它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目 .訊號量對象對線程的同步方式與前面幾種方法不同,訊號允許多個線程同時使用共用資源,這與作業系統中的PV操作相同。它指出了同時訪問共用資源的線程最大數目。它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目。
PV操作及訊號量的概念都是由荷蘭科學家E.W.Dijkstra提出的。訊號量S是一個整數,S大於等於零時代表可供並發進程使用的資源實體數,但S小於零時則表示正在等待使用共用資源的進程數。
P操作申請資源:
(1)S減1;
(2)若S減1後仍大於等於零,則進程繼續執行;
(3)若S減1後小於零,則該進程被阻塞後進入與該訊號相對應的隊列中,然後轉入進程調度。
V操作 釋放資源:
(1)S加1;
(2)若相加結果大於零,則進程繼續執行;
(3)若相加結果小於等於零,則從該訊號的等待隊列中喚醒一個等待進程,然後再返回原進程繼續執行或轉入進程調度。
4)、事 件: 通過通知操作的方式來保持線程的同步,還可以方便實現對多個線程的優先順序比較的操作 .
總結:
1) 互斥量與臨界區的作用非常相似,但互斥量是可以命名的,也就是說它可以跨越進程使用。所以建立互斥量需要的資源更多,所以如果只為了在進程內部是用的話使用臨界區會帶來速度上的優勢並能夠減少資源佔用量。因為互斥量是跨進程的互斥量一旦被建立,就可以通過名字開啟它。
2) 互斥量(Mutex),號誌(Semaphore),事件(Event)都可以被跨越進程使用來進行同步資料操作,而其他的對象與資料同步操作無關,但對於進程和線程來講,如果進程和線程在運行狀態則為無訊號狀態,在退出後為有訊號狀態。所以可以使用WaitForSingleObject來等待進程和線程退出。
3) 通過互斥量可以指定資源被獨佔的方式使用,但如果有下面一種情況通過互斥量就無法處理,比如現在一位使用者購買了一份三個並發訪問許可的資料庫系統,可以根據使用者購買的訪問許可數量來決定有多少個線程/進程能同時進行資料庫操作,這時候如果利用互斥量就沒有辦法完成這個要求,號誌對象可以說是一種資源計數器。
6、進程和線程的區別:
答:線程是指進程內的一個執行單元,也是進程內的可調度實體。與進程的區別:
(1)調度:線程作為調度和分配的基本單位,進程作為擁有資源的基本單位。
(2)並發性:不僅進程之間可以並發執行,同一個進程的多個線程之間也可並發執行。
(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但可以訪問隸屬於進程的資源.
(4)系統開銷:在建立或撤消進程時,由於系統都要為之分配和回收資源,導致系統的開銷明顯大於建立或撤消線程時的開銷。
7、進程間通訊的方式有哪些,各有什麼優缺點:
1)管道:管道是一種半雙工的通訊方式,資料只能單向流動,而且只能在具有親緣關係的進程之間使用。進程的親緣關係通常是指父子進程關係。
2)有名管道(FIFO):有名管道也是半雙工的通訊方式,但是允許在沒有親緣關係的進程之間使用,管道是先進先出的通訊方式。
3)訊號量:訊號量是一個計數器,可以用來控制多個進程對共用資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共用資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
4)訊息佇列:訊息佇列是有訊息的鏈表,存放在核心中並由訊息佇列標識符標識。訊息佇列克服了訊號傳遞資訊少、管道只能承載無格式位元組流以及緩衝區大小受限等缺點。
5)訊號 ( sinal ) :訊號是一種比較複雜的通訊方式,用於通知接收進程某個事件已經發生。
6)共用記憶體( shared memory ) :共用記憶體就是映射一段能被其他進程所訪問的記憶體,這段共用記憶體由一個進程建立,但多個進程都可以訪問。共用記憶體是最快的 IPC 方式,它是針對其他處理序間通訊方式運行效率低而專門設計的。它往往與其他通訊機制,如訊號量,配合使用,來實現進程間的同步和通訊。
7)通訊端( socket ) :通訊端也是一種處理序間通訊機制,與其他通訊機制不同的是,它可用於不同機器間的進程通訊。
8、tcp串連建立的時候3次握手的具體過程,以及每一步原因:
(1) 第一步:源主機A的TCP向主機B發出串連請求報文段,其首部中的SYN(同步)標誌位應置為1,表示想與目標主機B進行通訊,並發送一個同步序號X(例:SEQ=100)進行同步,表明在後面傳送資料時的第一個資料位元組的序號是X+1(即101)。SYN同步報文會指明用戶端使用的連接埠以及TCP串連的初始序號。
(2) 第二步:目標主機B的TCP收到串連請求報文段後,如同意,則發回確認。在確認報中應將ACK位和SYN位置1,表示用戶端的請求被接受。確認號應為X+1(圖中為101),同時也為自己選擇一個序號Y。
(3) 第三步:源主機A的TCP收到目標主機B的確認後要向目標主機B給出確認,其ACK置1,確認號為Y+1,而自己的序號為X+1。TCP的標準規定,SYN置1的報文段要消耗掉一個序號。
運行客戶進程的源主機A的TCP通知上層應用進程,串連已經建立。當源主機A向目標主機B發送第一個資料報文段時,其序號仍為X+1,因為前一個確認報文段並不消耗序號。
當運行服務進程的目標主機B的TCP收到源主機A的確認後,也通知其上層應用進程,串連已經建立。至此建立了一個全雙工系統的串連。
9、tcp中斷連線的具體過程,其中每一步是為什麼那麼做:
1)第一步:源主機A的應用進程先向其TCP發出串連釋放請求,並且不再發送資料。TCP通知對方要釋放從A到B這個方向的串連,將發往主機B的TCP報文段首部的終止位元FIN置1,其序號X等於前面已傳送過的資料的最後一個位元組的序號加1。
2)第二步:目標主機B的TCP收到釋放串連通知後即發出確認,其序號為Y,確認號為X+1,同時通知高層應用進程,這樣,從A到B的串連就釋放了,串連處於半關閉狀態,相當於主機A向主機B說:“我已經沒有資料要發送了。但如果還發送資料,我仍接收。”此後,主機B不再接收主機A發來的資料。但若主機B還有一些資料要發送主機A,則可以繼續發送。主機A只要正確收到資料,仍應向主機B發送確認。
3)第三步:若主機B不再向主機A發送資料,其應用進程就通知TCP釋放串連。主機B發出的串連釋放報文段必須將終止位元FIN和確認位元ACK置1,並使其序號仍為Y,但還必須重複上次已發送過的ACK=X+1。
4) 第四步:主機A必須對此發出確認,將ACK置1,ACK=Y+1,而自己的序號是X+1。這樣才把從B到A的反方向的串連釋放掉。主機A的TCP再向其應用進程報告,整個串連已經全部釋放。
10、tcp建立串連和中斷連線的各種過程中的狀態轉換細節:
用戶端:主動開啟SYN_SENT—>ESTABLISHED—>主動關閉FIN_WAIT_1—>FIN_WAIT_2—>TIME_WAIT
伺服器端:LISTEN(被動開啟)—>SYN_RCVD—>ESTABLISHED—>CLOSE_WAIT(被動關閉)—>LAST_ACK—>CLOSED
11、epool與select的區別:
問題的引出,當需要讀兩個以上的I/O的時候,如果使用阻塞式的I/O,那麼可能長時間的阻塞在一個描述符上面,另外的描述符雖然有資料但是不能讀出來,這樣即時性不能滿足要求,大概的解決方案有以下幾種:
1.使用多進程或者多線程,但是這種方法會造成程式的複雜,而且對與進程與線程的建立維護也需要很多的開銷。(Apache伺服器是用的子進程的方式,優點可以隔離使用者)
2.用一個進程,但是使用非阻塞的I/O讀取資料,當一個I/O不可讀的時候立刻返回,檢查下一個是否可讀,這種形式的迴圈為輪詢(polling),這種方法比較浪費CPU時間,因為大多數時間是不可讀,但是仍花費時間不斷反覆執行read系統調用。
3.非同步I/O(asynchronous I/O),當一個描述符準備好的時候用一個訊號告訴進程,但是由於訊號個數有限,多個描述符時不適用。
4.一種較好的方式為I/O多路轉接(I/O multiplexing)(貌似也翻譯多工),先構造一張有關描述符的列表(epoll中為隊列),然後調用一個函數,直到這些描述符中的一個準備好時才返回,返回時告訴進程哪些I/O就緒。select和epoll這兩個機制都是多路I/O機制的解決方案,select為POSIX標準中的,而epoll為Linux所特有的。
區別(epoll相對select優點)主要有三:
1.select的控制代碼數目受限,在linux/posix_types.h標頭檔有這樣的聲明:#define __FD_SETSIZE 1024 表示select最多同時監聽1024個fd。而epoll沒有,它的限制是最大的開啟檔案控制代碼數目。
2.epoll的最大好處是不會隨著FD的數目增長而降低效率,在selec中採用輪詢處理,其中的資料結構類似一個數組的資料結構,而epoll是維護一個隊列,直接看隊列是不是空就可以了。epoll只會對”活躍”的socket進行操作—這是因為在核心實現中epoll是根據每個fd上面的callback函數實現的。那麼,只有”活躍”的socket才會主動的去調用 callback函數(把這個控制代碼排入佇列),其他idle狀態控制代碼則不會,在這點上,epoll實現了一個”偽”AIO。但是如果絕大部分的I/O都是“活躍的”,每個I/O連接埠使用率很高的話,epoll效率不一定比select高(可能是要維護隊列複雜)。
3.使用mmap加速核心與使用者空間的訊息傳遞。無論是select,poll還是epoll都需要核心把FD訊息通知給使用者空間,如何避免不必要的記憶體拷貝就很重要,在這點上,epoll是通過核心於使用者空間mmap同一塊記憶體實現的。
12、epool中et和lt的區別與實現原理:
epoll有2種工作方式:LT和ET。
LT(level triggered)是預設的工作方式,並且同時支援block和no-block socket.在這種做法中,核心告訴你一個檔案描述符是否就緒了,然後你可以對這個就緒的fd進行IO操作。如果你不作任何操作,核心還是會繼續通知你 的,所以,這種模式編程出錯誤可能性要小一點。傳統的select/poll都是這種模型的代表.
ET (edge-triggered)是高速工作方式,只支援no-block socket。在這種模式下,當描述符從未就緒變為就緒時,核心通過epoll告訴你。然後它會假設你知道檔案描述符已經就緒,並且不會再為那個檔案描述 符發送更多的就緒通知,直到你做了某些操作導致那個檔案描述符不再為就緒狀態了(比如,你在發送,接收或者接收請求,或者發送接收的資料少於一定量時導致 了一個EWOULDBLOCK 錯誤)。但是請注意,如果一直不對這個fd作IO操作(從而導致它再次變成未就緒),核心不會發送更多的通知(only once),不過在TCP協議中,ET模式的加速效用仍需要更多的benchmark確認。
epoll只有epoll_create,epoll_ctl,epoll_wait 3個系統調用。
13、寫一個server程式需要注意哪些問題:
14、ThreadLocal與其它同步機制的比較:
Threadlocal和其他所有的同步機制都是為瞭解決多線程中的對同一變數的存取違規,在普通的同步機制中,是通過對對象加鎖來實現多個線程對同一變數的安全訪問的。這時該變數是多個線程共用的,使用這種同步機制需要很細緻的分析在什麼時候對變數進行讀寫,什麼時候需要鎖定某個對象,什麼時候釋放該對象的索等等。所有這些都是因為多個線程共用了該資源造成的。Threadlocal就從另一個角度來解決多線程的並發訪問,Threadlocal會為每一個線程維護一個和該線程綁定的變數副本,從而隔離了多個線程的資料共用,每一個線程都擁有自己的變數副本,從而也就沒有必要對該變數進行同步了。ThreadLocal提供了安全執行緒的共用對象,在編寫多線程代碼時,可以把不安全的變數封裝進ThreadLocal。
總結:當然ThreadLocal並不能替代同步機制,兩者面向的問題領域不同。同步機制是為了同步多個線程對相同資源的並發訪問,是為了多個線程之間進行通訊的有效方式;而ThreadLocal是隔離多個線程的資料共用,從根本上就不在多個線程之間共用資源(變數),這樣當然不需要對多個線程進行同步了。所以,如果你需要進行多個線程之間進行通訊,則使用同步機制;如果需要隔離多個線程之間的共用衝突,可以使用ThreadLocal,這將極大地簡化你的程式,使程式更加易讀、簡潔。
15、記憶體池、進程池、線程池:
自訂記憶體池的思想通過這個”池”字表露無疑,應用程式可以通過系統的記憶體配置調用預先一次性申請適當大小的記憶體作為一個記憶體池,之後應用程式自己對記憶體的分配和釋放則可以通過這個記憶體池來完成。只有當記憶體池大小需要動態擴充時,才需要再調用系統的記憶體配置函數,其他時間對記憶體的一切操作都在應用程式的掌控之中。 應用程式自訂的記憶體池根據不同的適用情境又有不同的類型。 從安全執行緒的角度來分,記憶體池可以分為單線程記憶體池和多線程記憶體池。單線程記憶體池整個生命週期只被一個線程使用,因而不需要考慮互斥訪問的問題;多線程記憶體池有可能被多個線程共用,因此則需要在每次分配和釋放記憶體時加鎖。相對而言,單線程記憶體池效能更高,而多線程記憶體池適用範圍更廣。
從記憶體池可分配記憶體單元大小來分,可以分為固定記憶體池和可變記憶體池。所謂固定記憶體池是指應用程式每次從記憶體池中分配出來的記憶體單元大小事先已經確定,是固定不變的;而可變記憶體池則每次分配的記憶體單元大小可以按需變化,應用範圍更廣,而效能比固定記憶體池要低。