《深刻理解計算機系統》速讀筆記

問題一 條件碼

條件碼寄存器中保存着單個位的條件碼,由CPU維護,如:
CF:進位標誌
ZF:零標誌
SF:符號標誌
OF:溢出標誌緩存

有幾類指令可以修改條件碼:
算術指令:既改變操做數,也有可能改變條件碼。
CMP指令:右操做數減左操做數,只可能改變條件碼。
TEST指令:兩操做數相與,只可能改變條件碼。服務器

條件碼寄存器不能直接讀取,有三種方法:
set指令:根據條件碼,設置一個字節。
jump指令:根據條件碼進行跳轉,即控制的條件轉移。
cmov條件傳送指令:根據條件碼決定是否進行mov操做。網絡

問題二 RIO包

  • RIO,全稱 Robust I/O,即健壯的IO包。它提供了與系統I/O相似的函數接口,在讀取操做時,RIO包加入了讀緩衝區,必定程度上增長了程序的讀取效率。
  • RIO函數提供了帶緩衝的讀操做,與無緩衝的寫操做
  • RIO幫助咱們處理了可修復的錯誤類型:EINTR。考慮read和write在阻塞時被某個信號中斷,在中斷前它們還未讀取/寫入任何字節,則這兩個系統調用便會返回-1表示錯誤,並將errno置爲EINTR。這個錯誤是能夠修復的,而且應該是對用戶透明的,用戶無需在乎read 和 write有沒有被中斷,他們只須要直到read 和 write成功讀取/寫入了多少字節,因此在RIO的rio_read()和rio_write()中便對中斷進行了處理。
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
 
ssize_t rio_readn(int fd, void *usrbuf, size_t n)
{
    size_t nleft = n;
    ssize_t nread;
    char *bufp = usrbuf;
 
    while (nleft > 0)
    {
        if ((nread = read(fd, bufp, nleft)) < 0)
        {
            if (errno == EINTR)
            {
                nread = 0;
            }
            else
            {
                return -1;
            }
        }
        else if (nread == 0)
        {
            break;
        }
 
        nleft -= nread;
        bufp += nread;
    }
 
    return (n-nleft);
}
 
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
{
    size_t nleft = n;
    ssize_t nwritten;
    char *bufp = usrbuf;
 
    while (nleft > 0)
    {
        if ((nwritten = write(fd, bufp, nleft)) <= 0)
        {
            if (errno == EINTR)
            {
                nwritten = 0;
            }
            else
            {
                return -1;
            }
        }
 
        nleft -= nwritten;
        bufp += nwritten;
    }
 
    return n;
}

問題三 套接字接口

應用層經過傳輸層進行數據通訊時,TCP和UDP會遇到同時爲多個應用程序進程提供併發服務的問題。多個TCP鏈接或多個應用程序進程可能須要 經過同一個TCP協議端口傳輸數據。爲了區別不一樣的應用程序進程和鏈接,許多計算機操做系統爲應用程序與TCP/IP協議交互提供了稱爲套接字 (Socket)的接口,區分不一樣應用程序進程間的網絡通訊和鏈接。
生成套接字,主要有3個參數:通訊的目的IP地址、使用的傳輸 層協議(TCP或UDP)和使用的端口號。Socket原意是「插座」。經過將這3個參數結合起來,與一個「插座」Socket綁定,應用層就能夠和傳輸 層經過套接字接口,區分來自不一樣應用程序進程或網絡鏈接的通訊,實現數據傳輸的併發服務。數據結構

加載套接字庫,建立套接字(WSAStartup()/socket());
綁定套接字到一個IP地址和一個端口上(bind());
將套接字設置爲監聽模式等待鏈接請求(listen());
請求到來後,接受鏈接請求,返回一個新的對應於這次鏈接的套接字(accept());
用返回的套接字和客戶端進行通訊(send()/recv());
關閉套接字,關閉加載的套接字庫(closesocket()/WSACleanup());
加載套接字庫,建立套接字(WSAStartup()/socket());
向服務器發出鏈接請求(connect())
關閉套接字,關閉加載的套接字庫(closesocket()/WSACleanup());

問題四 信息=位+上下文

位:位是數據存儲的最小單位,位又稱爲比特(bit),8位=1字節(8bit=1Byte),每一個字節表示程序中的某些文本字符。每一位的狀態只能是0或1:1bit=0或者1bit=1。字母用一個字節表示進行表示和存儲,而一個漢字是兩個字節表示和存儲。 程序的生命週期是從一個源程序(或者說是源文件)開始的。源程序實際上就是一個由值0和1組成的位序列。

 上下文(context)理解:併發

1.簡單的說就是跟當前主題有關的全部內容
2.說到程序的上下文,就是當前這段程序之上和之下的程序段。由於有些變量、函數不必定都定義在一塊兒,並且一個程序段不是一行就能寫完,之間有有不少的聯繫。就像看英語閱讀或者小說等都須要先後理解的。
3.「設備上下文」(the device context):是一種包含有關某個設備(如顯示器或打印機)的繪製屬性信息的Windows數據結構。全部繪製調用都經過設備上下文對象進行,這些對象封裝了用於繪製線條、形狀和文本的 Windows API。設備上下文容許在 Windows 中進行與設備無關的繪製。設備上下文可用於繪製到屏幕、打印機或者圖元文件.

問題五 測量程序運行時間的方法

  • 方法一:經過間隔計數(timer)
    • 缺點:精度不夠高,不能用於程序運行持續時間小於100ms的測量。
    • 優勢:準確性不是十分依賴於系統負載,而且在執行時間大於1s的程序上,與理論值之間的偏差很低。
    • 調用庫函數times來讀進程的計時器,時間測量值是以時鐘滴答爲單位表示的,times返回的是從系統啓動開始通過的時鐘滴答總數。
  • 方法二:週期計數器(counter)
    • 缺點:只能用匯編語言讀取,不能保證通用性,在系統負載很大的狀況下,將極大的影響準確性
    • 優勢:精度高,而且由於獲得的是程序執行期間所通過的時鐘週期數,因此可大體估算出在不一樣硬件平臺上程序的執行時間。
    • 爲了給計時測量提供更高的準確度,不少處理器還包含一個運行在時鐘週期級別的計時器,它是一個特殊的寄存器,每一個時鐘週期它都會自動加1。
    • 因爲基於counter的測量方法受影響的因素較多,主要是上下文切換和高速緩存操做的影響,因此高精度計時必須設法消除上述兩種因素的影響,
  • 方法三:基於gettimeofday函數的測量
    socket

    • gettimeofday是一個庫函數,包含在time.h中。它的功能是查詢系統時鐘,以肯定當前的日期和時間。它相似於週期計時,除了測量時間是以秒爲單位,而不是時鐘週期爲單位的。
    • 在使用gettimeofday()函數時,第二個參數通常都爲空,由於咱們通常都只是爲了得到當前時間,而不用得到timezone的數值。
相關文章
相關標籤/搜索