深刻理解計算機系統

深刻理解計算機系統

計算機系統漫遊

  • 源文件到目標文件的翻譯過程可分爲四個階段, 這四個階段的程序被稱爲預處理器,編譯器,彙編器和連接器,它們一塊兒構成了編譯系統(compilation system)。
    編譯系統
  • 緩衝區溢出是形成大多數網絡和Internet服務器上安全漏洞的主要緣由。
    計算機系統的硬件組成
  • 主存是一個臨時存儲設備,用來存放程序和程序處理的數據。
    • 從物理上來講, 主存是由一組動態隨機存儲器(DRAM)芯片組成。
    • 邏輯上, 主存是一個線性的字節數組,每一個字節都有惟一的地址, 這些地址從零開始。
  • 中央處理器(CPU)的核心是程序計數器(PC),PC都指向主存中的某條機器語言指令(即含有該條指令的地址)。
    • 處理器一直在不斷地執行程序計數器指向的指令, 再更新程序計數器,使其指向下一條指令。
  • 指令集結構描述的是每條機器代碼指令的效果; 而微體系結構描述的是處理器其實是如何實現的。
  • 複製就是開銷, 利用高級緩存減小數據間的拷貝。
    存儲器的高級緩存
  • 操做系統有兩個基本功能:
    • 防止硬件被失控的應用程序濫用;
    • 嚮應用程序提供簡單一致的機制來控制複雜而又一般截然不同的低級硬件設備。
  • 操做系統有幾個抽象概念: 進程, 虛擬存儲器和文件。
    • 文件是對I/O設備的抽象表示;
    • 虛擬存儲器是對主存和磁盤I/O設備的抽象表示;
    • 進程是對處理器,主存和I/O設備的抽象表示。
      • 進程是操做系統對一個正在運行的程序的一種抽象,每一個進行好像獨佔地使用硬件。
      • 一個進程實際上能夠由多個線程的執行單元組成,每一個線程都運行在進程的上下文中,並共享全局的代碼和全局的數據。
      • 每一個進程看到的是一致的存儲器,稱爲虛擬地址空間。
        進程的虛擬地址空間
  • 併發與並行:
    • 併發是指同時有多個活動的系統;
    • 並行是指用併發使一個系統運行得更快。
    • 超線程也叫作同時多線程,容許一個CPU執行多個控制流的技術。 --- 容許一個CPU某些硬件有多個備份,而另外硬件部分只能有一份。(4覈實際上能夠執行8個線程)
  • 抽象是計算機科學中最爲重要的概念之一。

程序結構與執行

  • 浮點數雖然能夠編碼一個較大的數值範圍,可是這種表示只是近似的。
  • Java創造了一套新的數字表示和運算標準。
  • 全部可能地址的集合稱爲虛擬地址空間, 虛擬地址空間(virtual address space)只是展示給機器級程序的概念性映像。
  • typedef提供了一種給數據類型命名的方式。
  • Java只支持有符號數。
    • 在Java中, 單字節數據類型稱爲byte,而不是char,並且沒有long long數據類型。

程序的機器級表示

  • 目標代碼是機器代碼的一種形式,它包含全部指令的二進制表示,可是尚未填入地址的全局值。
  • 機器級程序的格式和行爲,定義爲指令集體系結構(Instruction set architecture, ISA),定義了處理器狀態指令的格式,以及每條指令對狀態的影響。
  • 彙編代碼不區分有符號或無符號整數,不區分各類類型的指針,甚至不區分指針和整數。
  • 程序存儲器用虛擬地址來尋址。在任給定的時刻,只認爲有限的一部分虛擬地址是合法的。
  • 操做系統負責管理虛擬地址空間,將虛擬地址翻譯成實際處理器存儲器中的物理地址。
  • 一條機器指令只執行一個很是基本的操做。
  • 機器世紀之星的程序是一系列指令驚喜編碼的字節序列。
  • 查看目標代碼文件的內容,最有價值的是反彙編(disassembler) --- objdump -d code.o.

彙編中一些語句的說明

  • 以‘.’開頭的行都是指導彙編器和連接器的命令,一般能夠忽略這些行。
  • 有些指令以固定的寄存器做爲源寄存器或目的寄存器。
    整數寄存器
  • 寄存器%ebp和%esp保存着指向程序棧中重要的位置指針。
    • %ebp是幀指針。
    • %esp是棧指針。
  • 存儲器引用(memory),會根據計算出來的地址(一般稱爲有效地址)訪問某個存儲器位置。
    操做數格式
  • 數據傳送指令:
    數據傳送指令
    • 數據的條件轉移是指先計算一個條件操做的兩種結果,而後再根據條件是否知足從而選一個。
  • 算術和邏輯操做:
    • 加載有效地址(load effective address)指令leal其實是movl指令的變形,其實是從寄存器讀數據到寄存器中。
      • 將有效地址寫入到目的操做數。
        算術和邏輯操做
    • 一元操做指只有一個操做數,便是源又是目的。
    • 特殊的算術操做:
      特殊的算術操做.
  • 控制:
    • 除了整數寄存器, CPU還維護着一組單個位的條件碼(condition code)寄存器,它們描述了最近的算術或邏輯操做的屬性。
      • CF(carry flag): 進位標誌,最近的操做使最高位產生了進位,能夠用來檢查無符號操做數的溢出。
      • ZF(zero flag): 零標誌,最近的操做得出的結果爲0.
      • SF(symbol flag): 符號標誌位,最近的操做獲得的結果爲負數。
      • OF(over flag): 溢出標誌,最近的操做致使一個補碼溢出---正溢出或負溢出。
        比較和測試指令
      • CMP指令根據兩個操做數之差來設置條件碼,若是兩個操做數之差相等,這些指令會將零標誌設置爲1.
      • TEST根據兩個操做數的與來設置零標誌和負數標誌。
        set指令
    • 彙編語言入門教程.
    • 跳轉(jump)指令會致使執行切換到程序中一個全新的位置 --- jmp .L1(標號, label)。
      • jmp指令是無條件跳轉,它能夠是直接跳轉,也能夠間接跳轉。
        jmp跳轉指令.
    • 基於條件數據傳送的代碼比基於條件控制轉移的代碼性能要好。
    • 處理器採用很是精密的分支預測邏輯試圖猜想每條跳轉指令是否會執行。
  • 過程:
  • 幾個有用的命令工具:
    • gcc -S 源文件.c --- 將源文件變爲彙編文件。
    • gcc -c 源文件.c --- 將源文件變爲.o的二進制文件。
    • objdump -d 目標文件或二進制可執行文件 --- 進行反彙編。
  • 彙編用條件測試和跳轉組合起來實現循環的效果。
  • 流水線經過重疊連續指令的步驟來得到高性能。
    • 分支預測邏輯試圖猜想每條跳轉指令是否執行, 只要猜想比較可靠(90%以上的成功率),指令流水線中就會充滿着指令。
    • 錯誤預測會致使嚴重的懲罰,大約20~40個時鐘週期的浪費。
  • 當兩個表達式都很容易計算時,才使用條件傳送改進代碼的效率。
  • switch語句的彙編語句會作一個跳轉表放到.text文本段,優化多重分支跳轉的效率。
  • 轉移控制:
    • call Label --- 過程調用。
    • call *Operand --- 過程調用。
    • leave --- 爲返回準備棧。
    • ret --- 從過程調用中返回。
    • call的效果是將返回地址入棧(eip所指的地址入棧)。
  • 程序寄存器組是惟一能被全部過程共享的資源。
    • 寄存器%eax, %edx和%ecx被互粉爲調用者保存寄存器。
    • 寄存器%ebx, %esi, %edi被互粉爲被調用者保存寄存器。(調用前把他們放到棧中, 調用後返回)
    • 必須保持寄存器%ebp和%esp.
  • 每一個調用在棧中都有它本身的私有空間,多個未完成調用的局部變量不會互相影響。
  • leal指令能夠用來產生地址。
  • 結構的全部組成部分都放到存儲器中的一段連續區域,而指向結構的指針就是結構第一個字節的地址。
    • 爲了對齊和訪問結構的字段,編譯器產生的代碼要將結構的地址加上適當的編譯。
    • 聯合繞過了C語言類型系統提供的安全措施。
  • 數據對齊:
    • 要求某種類型對象的地址必須是某個值K(一般是2,4或8)的倍數。
    • 對齊限制是爲了簡化處理器和存儲器系統之間接口的硬件設計。
    • 不一樣的操做系統可能對齊方式也會不同,Linux8字節的double進行4字節對齊,而Windows採起8字節對齊。
    • .align 4表示它後面的數據的起始地址是4的倍數。
    • struct結構體的對齊更爲嚴格,內部成員都要保證對齊。
  • 函數指針的值是該函數機器代碼表示中第一條指令的地址。
  • 對越界的數組元素的寫操做會破壞存儲在棧中的狀態信息。(緩衝區溢出, buffer overflow)
  • 棧隨機化的思想使得棧的位置在程序每次運行時都有變化。
    • 實現方式是在程序開始時,在棧上分配一段0~n字節之間的隨機大小的空間。
    • 地址空間佈局隨機化(Address-Space Layout Randomization):程序代碼,庫代碼,棧,全局變量,堆數據都會被加載到不一樣的區域。
  • gcc版本中加入了一種棧保護者機制(stack protector), 用來檢測緩衝區越界.
    • 在棧幀中任何緩衝區與棧狀態之間存儲一個特殊的金絲雀(canary)值, 也稱爲哨兵值(guard value).
    • 最新的NX(No-eXecute)技術支持棧可讀可寫但不可執行。
  • callq指令將一個64位返回地址存儲在棧上。
    • 許多函數再也不須要棧幀,只有那些不能將全部的局部變量都放到寄存器中的函數才須要在棧上分配空間。
    • 函數最多能夠訪問超過當前棧幀值的128個字節的棧上存儲空間。
      • 一些信息存儲在棧上而不需修改棧指針。
    • 最多有6個參數可用寄存器進行傳參。
  • Java的目標代碼是一種特殊的二進制表示,稱爲Java字節代碼, 這種代碼能夠看做是虛擬機的機器級程序。
    • 用軟件解釋器處理字節代碼,模擬虛擬機的行爲。

處理器體系結構

  • 一個處理器支持的指令和指令的字節級編碼稱爲它的指令集體系結構(Instruction-Set Architecture, ISA).
  • 經過同時處理多條指令的不一樣部分,處理器能夠得到更好的性能(流水線工做模式)。
  • 硬件和操做系統軟件聯合起來將虛擬地址翻譯成實際地址(物理地址)。
  • RISC指令集和CISC指令集:
    RISC指令集和CISC指令集.
  • 控制邏輯是設計微處理器最難的部分。
  • 一條指令能夠劃分爲幾個部分:
    • 取地址(fetch): 從存儲器讀取指令字節,地址爲程序計數器(PC)的值。
    • 譯碼(decode): 譯碼階段從寄存器文件讀入最多兩個操做數。
    • 執行(execute): 算術邏輯單元要麼執行指令指明的操做,計算存儲器引用的有效地址,要麼增長或減小棧指針。
    • 訪存(memory): 訪問階段能夠將數據寫入存儲器,或者從存儲其讀出數據。
    • 寫回(write back): 寫回階段最多能夠寫兩個結果到寄存器文件。
    • 更新PC(PC update):將PC設置成下一條指令的地址。
      SEQ的硬件結構.
      流水線結構.
  • 流水線冒險:
    • 數據相關:下一條指令會用到這一條指令的結果。 --- 數據冒險。
      • 用暫停來避免數據冒險,處理器暫停一條或多條指令,直到冒險條件不知足。(加入nop指令)
      • 用轉發避免數據冒險,從一個流水線階段傳到較早階段。(旁路)。
      • 用暫停(加載互鎖)和轉發結合起來,避免加載/使用數據冒險。
    • 控制相關: 一條指令要肯定下一條指令的位置。--- 控制冒險。
      • 預測錯誤的分支。
  • 從處理器角度來看,將用暫停來處理短期的告訴緩存不命中和用異常來處理長時間的缺頁結合起來,能估計到存儲器訪問時因爲存儲器層次結構引發的全部不可預測性。

優化程序性能

  • 每元素的週期數做爲一種表示程序性能並指導咱們改進代碼的方法。
  • 消除循環的低效率。
  • 減小過程調用。
  • 理解現代處理器。
    • 超標量的意思是每一個時鐘週期執行多個操做。
  • 循環展開: 增長每次迭代計算的元素數量,減小循環的迭代次數。
  • 提升並行性。

性能提升技術

  • 高級設計:
    • 爲遇到的問題選擇適當的算法和數據結構。
  • 基本編碼原則:
    • 避免限制優化的因素,這樣編譯器能產生高效的代碼。
    • 消除連續的函數調用,將計算移到循環外,考慮妥協模塊性以得到更大的效率。
    • 消除沒必要要的存儲器引用,引入臨時變量來保存中間結構,只有在最後值計算出來時,纔將結果放到數組或全局變量中。
    • 用功能的風格重寫條件操做,使得編譯器採用條件數據傳送。

存儲器層次結構

  • 隨機訪問存儲器(Random-Access Memory, RAM), 分爲靜態和動態的, 靜態RAM比動態RAM更快。
    • 動態RAM有干擾將不會恢復。
  • 固態硬盤(Solid State Disk, SSD)是由一個或多個閃存芯片和閃存翻譯層組成。
  • 一個編寫良好的計算機程序經常具備良好的局部性(locality): 時間局部性和空間局部性。
    • 局部性原理: 傾向於引用鄰近於其餘最近引用過的數據項的數據項,或者最近引用過的數據項自己。
    • 被引用過一次的存儲器可能在不遠的未來會再被屢次引用。
    • 在存儲器一個位置上被引用了一次,那麼在不遠的未來可能會引用附近的一個存儲器位置。
      存儲器層次結構
    • 冷不命中: 一般是短暫的事件,不會在反覆訪問訪問存儲器使得緩存暖身以後的穩定狀態中出現。
  • 高速緩存友好的代碼:
    • 對局部變量的反覆引用是好的。(利用時間局部性)
    • 步長爲1的引用模式是好的。(利用空間局部性)
    • 一旦從存儲器中讀入了一個數據對象,就儘量多地使用它,從而使程序中的時間局部性最大。
      存儲器山
    • 存儲器系統性能是一座時間和空間局部性的山,這座山的上升高度差異能夠超過一個數量級。
    • 利用時間局部性, 使得頻繁使用的字從L1中取出。
    • 利用空間局部性, 使得儘量多的字從一個L1高速緩存中訪問到。

連接

  • 連接器程序ld,將main.o和swap.o以及一些必要的系統目標文件組合起來,建立一個可執行目標文件。
    • 可重定向目標文件。
    • 可執行目標文件。
    • 共享目標文件。
    • 編譯器和彙編器生成可重定位目標文件(包括共享目標文件)。
    • 連接器生成可執行目標文件。
  • 可重定位目標文件:
    • .text:已編譯程序的機器代碼。
    • .rodata:只讀數據,switch語句中的跳轉表。
    • .data:已初始化的全局C變量。
    • .bss: 未初始化的全局C變量。不佔實際空間,僅僅是個佔位符。
    • .symtab: 一個符號表, 它存放在程序中定義和引用的函數和全局變量的信息。但不包含局部變量的信息。
    • .rel.text: 一個.text節中位置的列表,當連接器把這個目標文件和其餘文件結合時, 須要修改這些位置。
    • .rel.data: 被模塊引用或定義的任何全局變量的重定位信息。
    • .debug: 一個調試符號表,全局變量及類型定義,定義和引用的全局變量,以及原始的C源文件。
    • .line: 原始C源文件中的行號和.text節中機器指令之間的映射。(-g)
    • .strtab: 一個字符串表,其內容包括.symtab和.debug節中的符號表,以及節頭部中的節名字。
  • static全局變量在.data或.bss中分配空間,並在符號表中穿件一個有惟一名字的本地連接器符號。
    • 'cpp'在Unix系統中是c預處理器。
    • cc1是C編譯器。
    • as是C彙編器。
    • ld是連接器。
      靜態連接.
  • 函數和已初始化的全局變量是強符號,未初始化的全局變量是弱符號。
    • 不容許有多個強符號。
    • 若是有一個強符號和多個弱符號, 那麼選擇強符號。
    • 若是有多個弱符號,那麼衝這些弱符號中任意選擇一個。
    • 連接器一般不會代表它檢測到多個x的定義。
    • 遇到多重定義的全局符號時,輸出一條警告信息。
  • 把全部相關的目標模塊打包成一個單獨的文件,稱爲靜態庫(static library),它能夠用做連接器的輸入。
    • 使用AR工具能夠建立靜態庫。
      與靜態庫連接
  • 可執行文件的連續片(chunk)被映射到連續的存儲器段。
    • 段頭部表(segment header table)描述了這種映射關係。
      可執行目標文件.
    • 經過調用留在存儲器中稱爲加載器(loader)的操做系統代碼來運行它。
      • 經過execve函數來調用加載器, 加載器將可執行目標文件中的代碼和數據從磁盤拷貝到存儲器中,而後經過跳轉到程序的第一條指令和入口點(entry point --- 符號表_start的地址)來運行程序。
        Linux運行時存儲器映像.
      • 當shell運行一個程序時,父外殼進程生成一個子進程,它是父進程的一個複製品, 子進程經過execve系統調用啓動加載器;加載器刪除子進程現有的虛擬存儲器段,並穿件一組新的代碼、數據、堆和棧段,而後初始化爲可執行文件的內容,最後跳轉到_start地址調用main函數執行。
      • 操做系統利用頁面調度機制自動將頁面從磁盤傳遞到存儲器。
  • 共享庫(shared library)是一個目標模塊, 在運行時,能夠加載到任意的存儲器地址,並和另外一個存儲器中的程序鏈接起來,以.so後綴表示。
    • 一個共享庫中的.text段的一個副本能夠被不一樣的長在運行的進程共享。
      動態連接庫
    • 共享庫的一個主要目的是容許多個正在運行的進程共享存儲器中相同的庫代碼,於是節約寶貴的存儲器資源。
    • 位置無關碼(Position-Independent Code, PIC), GCC的-fPIC產生位置無關碼。
      • 數據段使用一個全局偏移量表(Global Offset Table, GOT)。
      • 不須要連接器修改庫代碼就能夠在任何地址加載和執行的代碼。
  • Java有一個本地接口能夠調用本地的C和C++函數。

異常控制流

  • 異常是異常控制流的一種形式,它一部分是由硬件實現的,一部分是由操做系統實現的。
    異常剖析
  • 異常能夠分爲四類:
    • 中斷(interrupt). --- 來自I/O設備的信號,是異步的。
    • 陷阱(trap). --- 有意的異常, 同步的。
    • 故障(fault). --- 潛在可恢復的錯誤, 是同步的。
    • 終止(abort). --- 不可恢復的錯誤, 是同步的。
  • 異常是容許操做系統提供進程(一個執行中程序的實例)的概念所須要的基本構造塊。
  • 進程提供應用程序的關鍵抽象:
    • 一個獨立的邏輯控制流,它提供一個假象,好像咱們的程序獨佔地使用處理器。
    • 一個私有的地址空間, 它提供一個假象, 好像咱們的程序獨佔地使用存儲器系統。
  • 一個程序爲每一個函數提供本身的私有空間,不能被其餘進程寫。
    • 地址空間底部是保留給用戶程序的,包括一般的文本、數據、堆和棧。
    • 對32位Linux系統進程來講,代碼段從0x08048000開始;
    • 對64位Linux系統進程來講,代碼段從0x00400000開始。
    • 地址空間頂部保留給內核(內核執行指令時的代碼、數據和棧)。
      進程地址空間.
  • 限制應用能夠執行的指令以及它能夠訪問的地址空間範圍。
    • 控制寄存器中的一個位模式來提供這種功能。
      • 該寄存器描述了進程當前享有的特權。
      • 內核模式,超級用戶模式。
      • 用戶模式, 不容許用戶模式的進程直接引用地址空間中內核區的代碼和數據。 --- 必須經過系統調用。
        • 進程從用戶模式變爲內核模式的惟一方法是經過諸如中斷、故障、陷入系統調用等異常。
        • proc/文件系統,將許多內核數據結構的內容輸出爲一個用戶程序能夠讀的文本文件的層次結構。
  • 上下文是指內核從新啓動一個被搶佔的進程所需的狀態。
    • 通用目的寄存器,浮點寄存器,程序計數器,用戶棧,狀態棧和各類內核數據結構(頁表,進程表,文件表)。
      上下文切換.
  • 一個終止了但還未被回收的進程稱爲僵死進程(zombie)。
    信號.
    • 一個待處理的信號最多隻能被處理一次,發送類型爲k的信號,內核會設置pending的第k位,接收則清除pending的第k位。
  • 進程組:
    • 每一個進程都有一個進程組,進程組是由一個正整數進程組ID來標識的。
    • getgrp返回當前進程的進程組ID。
    • 一個進程默認和它的父進程同屬於一個進程組。
    • 進程組的做用
  • 非本地跳轉經過setjmp和longjmp函數來提供。
  • 操做進程的工具:
    • strace: 打印進程調用每一個系統調用的軌跡。
    • ps: 列出當前系統中的進程(包括僵死進程)。
    • top: 打印關於當前進程資源使用的信息。
    • pmap: 顯示進程的存儲器映射。
  • 中斷會污染高速緩存。

虛擬存儲器

  • 一個系統中海的進程是與其餘進程共享CPU和主存資源的。
  • 虛擬存儲器(VM)是硬件異常,硬件地址翻譯、主存、磁盤文件和內核軟件的完美交互,爲每一個進程提供了一致的私有地址空間。
  • 虛擬存儲器提供三個重要的能力:
    • 它將主存當作是一個存儲在磁盤上的地址空間的高速緩存,在主存中只保存活動區域,根據須要在磁盤和主存之間來回傳送數據。
    • 爲每一個進程提供了一致的地址空間,從而簡化了存儲器管理。
    • 保護每一個進程的地址空間不被其它進程破壞。
      虛擬尋址.
      • CPU經過生成一個虛擬地址(virtual address, VA)來訪問主存。
      • 把虛擬地址轉換爲物理地址的任務叫作地址翻譯(address translation).
      • CPU芯片上叫作存儲器管理單元(Memory Management Unit, MMU)的專用硬件, 利用存放在主存中的查詢表來動態翻譯虛擬地址, 該表由操做系統管理。
  • 地址空間(address space)是一個非負整數地址的有序集合。
  • 主存中的每一個字節都有一個選自虛擬地址空間的虛擬地址和一個選自物理地址空間的物理地址。
  • 虛擬存儲器(VM)被組織爲一個由存放在磁盤上的N個連續的字節大小的單元組成的數組。
    • 每字節都有一個惟一的虛擬地址,這個惟一的虛擬地址是做爲到數組的索引。
    • 磁盤上數組的內容被緩存在主存中。
    • VM系統經過將虛擬存儲器分割爲大小固定的虛擬頁(Virtual Page, VP). 物理存儲器分割爲物理頁(Physiscal Page, PP).
      • 任何虛擬頁均可以放置在任何物理頁中。
  • 存放在物理存儲器中的頁表(page table)數據結構,將虛擬也映射到物理頁。
    缺頁
  • 許多虛擬頁面能夠映射到統一個共享物理頁面上。
    vm進程地址空間
  • 帶許可位的頁表:
    頁面級的存儲器保護.
  • 使用頁表的地址翻譯:
    頁表的地址翻譯.
  • 翻譯後備緩衝器(Translation Lookaside Buffer, TLB)是一個小的、虛擬尋址的緩存,其中每一行都保存着一個由單個PTE(頁表項)組成的塊。
    二級頁表結構
    k級頁表結構.
    i7存儲器系統.
    linux組織虛擬存儲器結構.
  • 內部碎片的數量只取決於之前強求的模式和分配器的實現方式。
    • 內部碎片實在一個已分配塊比有效載荷大時發生的。

系統級I/O

  • linux文件:
    打開文件的內核數據結構.
    文件共享.
    子進程繼承父進程的打開文件.
    • I/O重定向: 容許用戶將磁盤文件和標準輸入輸出聯繫起來。

網絡編程

  • 因特網.
  • 套接字接口.
  • Web服務器,Web客戶端和服務器之間的交互用的是一個基於文本的應用級協議,叫作HTTP(Hypertext Transfer Protocol, 超文本傳輸協議)。
    • 磁盤文件稱爲靜態內容。
    • 運行可執行文件產生的輸出稱爲動態內容。
    • HTTP事務, 使用Unix的TELNET程序來和因特網上的任何Web服務器執行事務。
    • HTTP請求,一個請求行(request line), 後面跟隨零個或更多個請求報頭,再跟隨一個空的文本行來終止報頭列表。
    • HTTP支持許多不一樣的方法: 包括GET,POST,OPTIONS,HEAD,PUT,DELETE和TRACE。
      • GET方法指導服務器生成和返回URI(Uniform Resource Identifier, 統一資源標識符)標識的內容。
  • 基於線程化的併發服務器:
    線程併發.
  • 可重複性:
    • 有一類重要的線程安全函數,叫作可重入函數(reentrant function), 當被多個線程調用時,不會引用任何共享數據。
    • 可重入函數不須要同步操做。
    • 若是全部的函數參數都是值傳遞,而且全部的數據引用都是本地的自動棧變量(沒有引用靜態或全局變量),那麼這個函數就是顯式可重入的。
相關文章
相關標籤/搜索