20145326蔡馨熤《信息安全系統設計基礎》第13周學習總結

20145326蔡馨熤《信息安全系統設計基礎》第13周學習總結

教材內容總結

網絡編程簡單過了一遍

  • 點分十進制:linux

  • 檢索並打印一個DNS條目git

  • 本機回送地址程序員

  • 多個域名映射爲同一個IP地址web

  • 多個域名映射到多個IP地址編程

併發編程(過多內容再也不贅述)

  • 程序級併發——進程
  • 函數級併發——線程安全

  • 三種基本的構造併發程序的方法:服務器

    • 進程:每一個邏輯控制流是一個進程,由內核進行調度,進程有獨立的虛擬地址空間網絡

    • I/O多路複用:邏輯流被模型化爲狀態機,全部流共享同一個地址空間併發

    • 線程:運行在單一進程上下文中的邏輯流,由內核進行調度,共享同一個虛擬地址空間函數

基於進程的併發編程

  • 構造併發程序最簡單的方法——用進程。經常使用函數以下:fork,exec,waitpid
  • 構造併發服務器:在父進程中接受客戶端鏈接請求,而後建立一個新的子進程來爲每一個新客戶端提供服務。
  • 須要注意的事情:

    • 父進程須要關閉它的已鏈接描述符的拷貝(子進程也須要關閉)

    • 必需要包括一個SIGCHLD處理程序來回收僵死子進程的資源

    • 父子進程之間共享文件表,可是不共享用戶地址空間

  • 獨立地址空間的優勢是防止虛擬存儲器被錯誤覆蓋,缺點是開銷高,共享狀態信息才須要IPC機制

基於I/O多路複用的併發編程

  • I/O多路複用技術使用select函數要求內核掛起進程,只有在一個或多個I/O事件發生後,纔將控制返回給應用程序。
  • select函數處理類型爲fd_set的集合,即描述符集合,並在邏輯上描述爲一個大小爲n的位向量,每一位b[k]對應描述符k,但當且僅當b[k]=1,描述符k才代表是描述符集合的一個元素。

  • 描述符能作的三件事: 一、分配他們 二、將一個此種類型的變量賦值給另外一個變量 三、用FDZERO、FDSET、FDCLR和FDISSET宏指令來修改和檢查它們

  • 當且僅當一個從該描述符讀取一個字節的請求不會阻塞時,描述符k表示準備好能夠讀了
  • 咱們必須在每次調用select時都更新讀集合
  • 事件驅動程序:將邏輯流模型化爲狀態機。
  • 一個狀態機就是一組狀態、輸入事件和轉移,其中轉移就是將狀態和輸入事件映射到狀態。

  • 基於I/O多路複用的併發事件驅動服務器的流程以下:

    • select函數檢測到輸入事件
    • add_client函數建立新狀態機
    • check_clients函數執行狀態轉移(在課本的例題中是回送輸入行),而且完成時刪除該狀態機。

基於線程的併發編程

  • 線程:就是運行在進程上下文中的邏輯流。
  • 線程由內核自動調度。每一個線程都有它本身的線程上下文:
    • 一個惟一的整數線程ID——TID
    • 棧指針
    • 程序計數器
    • 通用目的寄存器
    • 條件碼

進度圖

  • 進度圖是將n個併發線程的執行模型化爲一條n維笛卡爾空間中的軌跡線,原點對應於沒有任何線程完成一條指令的初始狀態。
  • 當n=2時,狀態比較簡單,是比較熟悉的二維座標圖,橫縱座標各表明一個線程,而轉換被表示爲有向邊

  • 轉換規則:

    • 合法的轉換是向右或者向上,即某一個線程中的一條指令完成
    • 兩條指令不能在同一時刻完成,即不容許出現對角線
    • 程序不能反向運行,即不能出現向下或向左

一個程序的執行歷史被模型化爲狀態空間中的一條軌跡線。

  • 線程循環代碼的分解:

    • H:在循環頭部的指令塊
    • L:加載共享變量cnt到線程i中寄存器%eax的指令。
    • U:更新(增長)%eax的指令
    • S:將%eax的更新值存回到共享變量cnt的指令
    • T:循環尾部的指令塊
  • 幾個概念:

    • 臨界區:對於線程i,操做共享變量cnt內容的指令L,U,S構成了一個關於共享變量cnt的臨界區。
    • 不安全區:兩個臨界區的交集造成的狀態
    • 安全軌跡線:繞開不安全區的軌跡線

實踐過程

關於countwithmutex.c

  • 首次編譯時按照以前的方法編譯,報錯。根據錯誤提示,發現pthread庫不是linux系統默認的庫,所以pthread_creat建立線程時,在編譯中要加上-lpthread參數。修正後順利編譯。

  • 代碼中涉及到的函數:
pthread_creat:建立線程,若成功則返回0,若失敗則返回出錯編號。第一個參數爲指向線程標識符的指針,建立成功時指向的內存單元被設置爲新建立線程的線程ID;第二個參數設置線程屬性;第三個參數是線程運行函數的起始地址;最後一個參數是運行函數的參數

pthread_join:用來等待一個線程的結束。當函數返回時,被等待線程的資源被收回。

pthreadmutexlock:線程調用該函數讓互斥鎖上鎖。成功鎖定時返回0,其餘任何返回值都表示出現了錯誤。

pthreadmutexunlock:與pthreadmutexlock成對存在。釋放互斥鎖。

 

  • 程序首先定義了一個宏PTHREADMUTEXINITIALIZER來靜態初始化互斥鎖。先建立tidA線程後運行doit函數,利用互斥鎖鎖定資源,進行計數,執行完畢後解鎖。後建立tidB,與tidA交替執行。因爲定義的NLOOP值爲5000,因此程序最後的輸出值爲10000.程序的最後還須要分別回收tidA和tidB的資源。

關於count.c

  • 這個代碼用於與countwithmutex.c進行對比,差異在於本代碼doit函數的for循環中沒有引入互斥鎖,只進行了單純的計數,建立兩個線程共享同一變量都實現加一操做。運行結果以下。

每次運行的結果都不同。是由於隨機的覆蓋嗎?

關於condvar.c

  • 這個代碼演示的是生產者生產和消費者消費交替進行的過程。是線程間同步的一種狀況。

  • 主函數中用srand(time(NULL))設置當前的時間值爲種子,在後面的producer和consumer函數中調用rand()函數產生隨機數。 

 

關於cp_t.c

• mmap函數

 

void* mmap(void* start,sizet length,int prot,int flags,int fd,offt offset); 

將一個文件或者其餘對象映射進內存。文件被映射到多個頁上,若是文件的大小不是全部頁的大小之和,最後一個頁不被使用的空間將會清零。mmap在用戶空間映射調用系統中做用很大。 - 成功執行時,mmap()返回被映射區的指針,munmap()返回0.失敗時,mmap()返回MAP_FAILED,munmap返回-1.

  • lseek函數
  • •offt lseek(int fd,offt offset,int whence); 

     

  • fd表示要操做的文件描述符,offset是相對於whence(基準)的偏移量,whence能夠是SEEK_SET(文件指針開始),SEEKCUR(文件指針當前位置),SEEKEND(文件指針尾)
  • lseek主要做用是移動文件讀寫指針,返回文件讀寫指針距文件開頭的字節大小,若出錯則返回-1.

  • 運行以下

關於createthread.c

  • 程序主要演示了建立線程函數pthread_create()函數的使用,用來打印進程和線程的ID

  • 主函數中先利用pthreadcreate()函數建立一個線程,接着調用printids函數(打印標識符的函數)打印主線程號,最後線程函數thrfn中打印出新建的線程號。

關於semphore.c

  • seminit函數
  • seminit(sem_t *sem, int pshared, umsigned int value);

     

  • 函數初始化一個定位在sem的匿名信號量;pshared參數爲0指明信號量是由進程內線程共享,若爲非0值則信號量在進程之間共享;value參數指定信號量的初始值。
  • sem_init()成功時返回0;錯誤時返回-1,並把errno設置爲合適的值。
  • semdestroy()函數用於銷燬由sem指向的匿名信號量。只有經過seminit()初始化的信號量才應該使用該函數銷燬。函數成功時返回0,錯誤時返回-1,並把errno設置爲合適的值。

  • 這個函數和以前的condvar.c同樣都是展現生產者和消費者交替工做的過程。區別是本程序實現生產或消費的過程是利用semwait()和sempost(),它們的做用分別是從信號量的值減去一個「1」和從信號量的值加上一個「1」

關於share.c

  • 代碼運行結果以下

關於threadexit.c

  • 運行以下:

關於hello_multi.c

  • 程序中的print_msg()函數中:在printf後的fflush(stdout);說明要馬上將要輸出的內容輸出,每輸出一次停1秒,並循環5次。

關於hello_multi1.c

  • 運行結果只輸出hello99

關於hello_single.c

  • 根據代碼,先單獨執行print_msg("hello");——輸出5個hello,後輸出5個帶換行的world

關於incprint.c

  • 因爲定義中NUM=5,因此輸出的count爲1到5。

twordcount1&twordcount2

  • 用法:./twordcount1 [文件1] [文件2]
  • 用來統計文件1及文件2兩個文件的總字數
  • 運行結果:

twordcount3

  • 用法:./twordcount3 [文件1] [文件2]
  • 分別對文件一、文件2兩個文件進行字數統計,並把兩個文件的字數加起來統計兩個文件的總字數
  • 運行結果:

twordcount4

  • 用法:./twordcount4 [文件1] [文件2]
  • 分別運行代碼,根據鎖的狀況分別統計字數,再把兩個文件的字數加起來統計兩個文件的總字數
  • 運行結果:

代碼託管

代碼託管連接

心得體會

  • 本週在學習完教材上的內容後,我把老師給的代碼逐一進行實踐,在運行代碼的過程當中,因爲程序中調用的一些函數都是比較生疏的,須要一個一個的去理解其中每一個參數的含義和函數的返回值,因此整個過程耗費了我大量的時間,不過收穫仍是很大的。最初看代碼的時候,只能根據程序運行的結果來大體的猜想每一句代碼的含義,不過在結合課本的知識後,對其又有了進一步的深入體會。

  • 不知不覺已經上了婁老師兩個學期的課了,從最開始徹底排斥反抗這種教學模式,到最後將這些學習方式變爲本身的習慣。我如今靜靜一想,才明白婁老師的良苦用心。 以寫博客的方式來記錄本身的學習過程,不只鍛鍊了文筆還理清了思緒,說得長遠一點,實際上是在積累本身的人生財富!不必定只有學計算機相關知識,才能發博客,看完一本書的感想或者記錄平時的心情,博客園都是一個很好的平臺。平時有什麼問題也能夠在園子裏提問,博客園裏面藏龍臥虎! 咱們還要學會使用git託管,雖然最開始在下載方面或者使用方面比較麻煩,但萬事開頭難,一旦上手,受益不淺!好比之後電腦出現「數據流失」的話,就不用懼怕了。再好比幾我的要作項目的話,學會git共享代碼,也會省事兒不少!學會用Markdown來編寫文檔,實際上是強調了一種規範意識! 有的人也許會說,我之後要當公務員,跟程序員沒半毛錢關係。 這句話是極其愚昧的,或者說這個同窗沒有領會到婁老師教學的精髓,婁老師一直強調的是什麼,不是要咱們學多少知識,由於知識是學不完的,也是會忘記的,婁老師要的是咱們培養一種學習方法,培養一種學習習慣,培養一種思惟方式,這纔是會伴隨咱們一輩子的財富~

學習進度條

  代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時  
第一週 0/0 1/2 20/20  
第二週 58/58 1/3 20/40  
第三週 150/208 1/4 22/62  
第五週 150/358 1/5 21/83  
第六週 136/494 1/6 25/108  
第七週 115/609 2/8 24/132  
第八週 0/609 2/10 22/154  
第九周 109/718 3/13 20/174  
第十週 472/1190 1/14 21/195  

第十一週

1883/3073 3/17 21/216  
第十二週 0/3073 2/19 20/236  
第十三週 1023/4096 1/20 21/257
相關文章
相關標籤/搜索