注意:客戶端和服務器都是進程。html
網絡是一種I/O設備程序員
從網絡上接收到的數據從適配器通過I/O和存儲器總線拷貝到存儲器,典型地是經過DMA(直接存儲器存取方式)傳送。編程
網絡是一個按照地理遠近組成的層次系統數組
最底層:LAN(局域網),最流行的是以太網,瀏覽器
以太網段安全
互聯網重要特性:由採用不一樣技術,互不兼容的局域網和廣域網組成,並能使其相互通訊。其中不一樣網絡相互通訊的解決辦法是一層運行在每臺主機和路由器上的協議軟件,消除不一樣網絡的差別。ruby
協議提供的兩種基本能力服務器
世界範圍的主機集合網絡
特性:多線程
Web 客戶端和服務器之間的交互用的是一個基於文本的應用級協議,叫作 HTTP (Hypertext Transfer Protocol,超文本傳輸協議). HTTP 是一個簡單的協議。一個 Web 客戶端(即瀏覽器) 打開一個到服務器的因特網鏈接,而且請求某些內容。服務器響應所請求的內容,而後關閉鏈接。瀏覽器讀取這些內容,並把它顯示在屏幕上。
Web內容能夠用一種叫作 HTML(Hypertext Markup Language,超文本標記語言)的語言來編寫。一個 HTML 程序(頁)包含指令(標記),它們告訴瀏覽器如何顯示這頁中的各類文本和圖形對象。
Web 服務器以兩種不一樣的方式向客戶端提供內容:
取一個磁盤文件,並將它的內容返回給客戶端。磁盤文件稱爲靜態內容 (static content), 而返回文件給客戶端的過程稱爲服務靜態內容 (serving static content)。
運行一個可執行文件,並將它的輸出返回給客戶端。運行時可執行文件產生的輸出稱爲態內容 (dynamic content),而運行程序並返回它的輸出到客戶端的過程稱爲服務動態內容 (serving dynamic content)。
併發(concurrency ) ,出如今計算機系統的許多不一樣層面上。
訪問慢速I/O設備。
與人交互。
經過推遲工做以下降延遲。
服務多個網絡客戶端。
在多核機器上進行並行計算
一個構造併發服務器的天然方法就是,在父進程中接受客戶端鏈接請求,而後建立一個新的子進程來爲每一個新客戶端提供服務。
一般服務器會運行很長的時間,因此咱們必需要包括一個 SIGCHLD 處理程序,來回收僵死 (zombie) 子進程的資源。由於當 SIGCHLD 處理程序執行時, SIGCHLD 信號是阻塞的,而 Unix 信號是不排隊的,因此 SIGCHLD 處理程序必須準備好回收多個僵死子進程的資源。
父子進程必須關閉它們各自的 connfd 拷貝。這對父進程而言尤其重要,它必須關閉它的已鏈接描述 符,以免存儲器泄漏。
由於套接字的文件表表項中的引用計數,直到父子進程的 connfd 都關閉了,到客戶端的鏈接纔會終止。
第一步:服務器接受客戶端的鏈接請求 第二步:服務器派生一個子進程爲這個客戶端服務 第三步:服務器接受另外一個鏈接請求 第四步:服務器派生另外一個子進程爲新的客戶端服務
在父、子進程間共享狀態信息,進程有一個很是清晰的模型:共享文件表,可是不共享用戶地址空間。
4.進程有獨立的地址空間既是優勢也是缺點。
優勢:一個進程不可能不當心覆蓋另外一個進程的虛擬存儲器,這就消除了許多使人迷惑的錯誤。
缺點:獨立的地址空間使得進程共享狀態信息變得更加困難。爲了共享信息,它們必須使用顯式的IPC(進程間通訊)機制。基於進程的設計的另外一個缺點是,它們每每比較慢,由於進程控制和 IPC 的開銷很高。
I/O 多路複用(I/O multiplexing) 技術。基本的思路就是使用 select 函數,要求內核掛起進程,只有在一個或多個I/O事件發生後,纔將控制返回給應用程序。
I/O 多路複用能夠用作併發事件驅動 (event-driven) 程序的基礎,在事件驅動程序中,流是由於某種事件而前進的。
將邏輯流模型化爲狀態機。不嚴格地說,一個狀態機 (state machine) 就是一組狀態 (state)、輸入事件(input event) 和轉移他(transition),其中轉移就是將狀態和輸入事件映射到狀態。每一個轉移都將一個(輸入狀態,輸入事件)對映射到一個輸出狀態。自循環(self-loop) 是同一輸入和輸出狀態之間的轉移。節 點表示狀態,有向弧表示轉移,而弧上的標號表示輸入事件。一個狀態機從某種初始狀態開始執行。每一個輸入事件都會引起一個從當前狀態到下一狀態的轉移。
服務器使用I/O多路複用,藉助 select 函數檢測輸入事件的發生。
服務器調用 select 函數來 檢測兩種不一樣類型的輸人事件:
(1)來自一個新客戶端的鏈接請求到達
(2) 一個己存在的客戶 端的己鏈接描述符準備好能夠讀了。
事件驅動設計的優勢:
它比基於進程的設計給了程序員更多的對程序行爲的控制。
線程(thread) 就是運行在進程上下文中的邏輯流。
每一個線程都有它本身的線程上下文 (thread context),包括一個惟一的整數線程 (Thread ID, TID)、棧、棧指針、程序計數器、通用目的寄存器和條件碼。全部的運行在一個進程裏的線程共享該進程的整個虛擬地址空間。
基於線程的邏輯流結合了基於進程和基於 I/O 多路複用的流的特性。同進程同樣,線程由內核自動調度,而且內核經過一個整數 ID 來識別線程。同基於 I/O 多路複用的流同樣,多個線程 運行在單一進程的上下文中,所以共享這個進程虛擬地址空間的整個內容,包括它的代碼、數據、堆、共享庫和打開的文件。
每一個進程開始生命週期時都是單一線程,這個線程稱爲主線程 (main thread)。在某一時刻,主線程建立一個對等線程 (peer thread),從這個時間點開始,兩個線程就併發地運行。最後,由於主線程執行一個慢速系統調用。或者由於它被系統的間隔計時器中斷, 控制就會經過上下文切換傳遞到對等線程。對等線程會執行一段時間,而後控制傳遞迴主線程,依次類推。
- 線程的上下文切換要比進程的上下文切換快得多。 - 不是按照嚴格的父子層次來組織的。 - 和一個進程相關的線程組成一個對等(線程)池 (pool),獨立於其餘線程建立的線程。 - 主線程和其餘線程的區別僅在於它老是進程中第一個運行的線程。 - 對等 (線程)池概念的主要影響是,一個線程能夠殺死它的任何對等線程,或者等待它的任意對等線程終止。 - 每一個對等線程都能讀寫相同的共享數據。
Posix 線程 (Pthreads) 是在 C 程序中處理線程的一個標準接口。Pthreads 定義了大約 60 個函數,容許程序建立、殺死和回收線程,與對等線程安全地共享數據,還能夠通知對等線程系統狀態的變化。
線程的代碼和本地數據被封裝在一個線程例程(thread routine) 中。若是想傳遞多個參數給錢程例程,那麼你應該將參數放 到一個結構中,並傳遞一個指向該結構的指針。想要線程例程返回多個參數,你能夠返回一個指向一個結構的指針。
pthread_create 函數建立一個新的線程,並帶着一個輸入變量arg,在新線程的上下文中運行線程例程f。能用attr參數來改變新建立線程的默認屬性。
當 pthread_create 返回時,參數 tid包含新建立線程的ID。新線程能夠經過調用 pthread_self 函數來得到它本身的線程 ID.
當頂層的線程例程返回時,線程會隱式地終止。
經過調用 pthread_exit 函數,線程會顯式地終止。若是主線程調用 pthread_exit , 它會等待全部其餘對等線程終止,而後再終止主線程和整個進程,返回值爲 thread_return。
線程經過調用 pthread_join 函數等待其餘線程終止。
在任何一個時間點上,線程是可結合的 (joinable) 或者是分離的 (detached)。一個可結合的線程可以被其餘線程收回其資源和殺死。在被其餘線程回收以前,它的存儲器資源(例如棧)是沒有被釋放的。相反,一個分離的線程是不能被其餘線程回收或殺死的。它的存儲器資源在它終止時由系統自動釋放。
默認狀況下,線程被建立成可結合的。爲了不存儲器泄漏,每一個可結合線程都應該要麼被其餘線程顯式地收回,要麼經過調用 pthread_detach 函數被分離。
pthread_detach 函數分離可結合線程 tid. 線程可以經過以 pthread_self()爲參數的 pthread_detach 調用來分離它們本身。
pthread_once 函數容許你初始化與線程例程相關的狀態。
調用 pthread_ create 時,如何將已鏈接描述符傳遞給對等線程。最明顯的方法就是傳遞一個指向這個描述符的指針。
對等線程間接引用這個指針,並將它賦值給一個局部變量。
1.線程存儲器模型
1.線程安全
2.可重入性
參考資料:1.20135317韓玉琪的博客:http://www.cnblogs.com/hyq20135317/p/5022152.html
2.《深刻理解計算機系統》第十一章和十二章