一個應用是由一個服務器進程和一個或多個客戶端進程組成html
服務器進程 -> 管理某種資源 -> 經過操做這種資源來爲它的客戶端提供某種服務git
基本操做:事務web
一個客戶端-服務器事務由四步組成:編程
當一個客戶端須要服務時,向服務器發送一個請求,發起一個事務。瀏覽器
服務器收到請求後,解釋它,並以適當的方式操做它的資源。安全
服務器給客戶端發送一個相應,並等待下一個請求。服務器
客戶端收到響應並處理它。網絡
客戶端和服務器都是進程併發
對主機而言,網絡是一種I/O設備:從網絡上接收到的數據從適配器通過I/O和存儲器總線拷貝到存儲器,典型地是經過DMA(直接存儲器存取方式)傳送。socket
物理上,網絡是一個按照地理遠近組成的層次系統:最低層是LAN(局域網),最流行的局域網技術是以太網。
以太網段包括一些電纜和集線器。每根電纜都有相同的最大位帶寬,集線器不加分辯地將一個端口上收到的每一個位複製到其餘全部的端口上,所以每臺主機都能看到每一個位。
每一個以太網適配器都有一個全球惟一的48位地址,存儲在適配器的非易失性存儲器上。
一臺主機能夠發送一段位:幀,到這個網段內其它任何主機。每一個幀包括一些固定數量的頭部位(標識此幀的源和目的地址及幀長)和數據位(有效載荷)。每一個主機都能看到這個幀,可是隻有目的主機能讀取。
使用電纜和網橋,多個以太網段能夠鏈接成較大的局域網,稱爲橋接以太網。這些電纜的帶寬能夠是不一樣的。
TCP/IP協議族
因特網的客戶端和服務器混合使用套接字接口函數和UnixI/O函數進行通訊
把因特網看作一個世界範圍的主機集合,知足如下特性:
主機集合被映射爲一組32位的IP地址
這組IP地址被映射爲一組稱爲因特網域名的標識符
因特網主機上的進程可以經過鏈接和任何其餘主機上的進程
函數:
socket函數 connect函數 open_clientfd函數 bind函數 listen函數 open_listenfd函數 accept函數
Web客戶端和服務器之間的交互用的是一個基於文本的應用級協議,叫作 HTTP (Hypertext Transfer Protocol,超文本傳輸協議). HTTP 是一個簡單的協議。一個 Web 客戶端(即瀏覽器) 打開一個到服務器的因特網鏈接,而且請求某些內容。服務器響應所請求的內容,而後關閉鏈接。瀏覽器讀取這些內容,並把它顯示在屏幕上。
Web內容能夠用一種叫作 HTML(Hypertext Markup Language,超文本標記語言)的語言來編寫。一個 HTML 程序(頁)包含指令(標記),它們告訴瀏覽器如何顯示這頁中的各類文本和圖形對象。
Web 服務器以兩種不一樣的方式向客戶端提供內容:
取一個磁盤文件,並將它的內容返回給客戶端。磁盤文件稱爲靜態內容 (static content), 而返回文件給客戶端的過程稱爲服務靜態內容 (serving static content)。
運行一個可執行文件,並將它的輸出返回給客戶端。運行時可執行文件產生的輸出稱爲態內容 (dynamic content),而運行程序並返回它的輸出到客戶端的過程稱爲服務動態內容 (serving dynamic content)。
併發:邏輯控制流在時間上重疊
併發程序:使用應用級併發的應用程序稱爲併發程序。
三種基本的構造併發程序的方法:
進程,用內核來調用和維護,有獨立的虛擬地址空間,顯式的進程間通訊機制。
I/O多路複用,應用程序在一個進程的上下文中顯式的調度控制流。邏輯流被模型化爲狀態機。
線程,運行在一個單一進程上下文中的邏輯流。由內核進行調度,共享同一個虛擬地址空間。
構造併發服務器的天然方法就是,在父進程中接受客戶端鏈接請求,而後建立一個新的子進程來爲每一個新客戶端提供服務。
由於父子進程中的已鏈接描述符都指向同一個文件表表項,因此父進程關閉它的已鏈接描述符的拷貝是相當重要的,並且由此引發的存儲器泄露將最終消耗盡可用的存儲器,使系統崩潰。
線程:運行在進程上下文中的邏輯流。
線程有本身的線程上下文,包括一個惟一的整數線程ID、棧、棧指針、程序計數器、通用目的寄存器和條件碼。全部運行在一個進程裏的線程共享該進程的整個虛擬地址空間。
寫順序程序只有一條邏輯流,寫併發程序有多條併發流,並行程序是一個運行在多個處理器上的併發程序。並行程序的集合是併發程序集合的真子集。
輸出生產者和消費者交替進行,消費者等待生產者產出產品後纔打印,不然消費者阻塞等待生產者生產。
主函數代碼以下:
運行結果以下:
此代碼中,使用srand來根據當前時間重置隨機數,用rand產生隨機數。
用pthread_mutex_lock來將線程上鎖,pthread_mutex_unlock解鎖。當consumer等待條件變量的條件成立時,用pthread_cond_wait使consumer掛起。pthread_cond_signal的做用是發送一個信號給另一個正在處於阻塞等待狀態的線程,使其脫離阻塞狀態。
代碼以下:
運行結果以下:
在運行count的時候,每次運行的結果都不同,有的超過5000,是由於代碼中沒有加入互斥鎖,兩個線程共享同一變量,輸出的結果相互覆蓋。
countwithmudex在count代碼的基礎上加了互斥鎖,因此避免了訪問衝突的問題。
所以,兩個線程一共會輸出10000
這個代碼用來打印進程和線程ID:
int pthread_create(pthread_t restrict tidp,const pthread_attr_t restrict_attr,void(start_rtn)(void),void restrict arg);
若成功則返回0,不然返回出錯編號
restrict tidp爲指向線程標識符的指針。 restrict_attr用來設置線程屬性。 (start_rtn)(void)是線程運行函數的起始地址。 restrict arg是運行函數的參數。
#include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <semaphore.h> #define NUM 5 int queue[NUM]; sem_t blank_number, product_number; void *producer ( void * arg ) { static int p = 0; for ( ;; ) { sem_wait( &blank_number ); queue[p] = rand() % 1000; printf("Product %d \n", queue[p]); p = (p+1) % NUM; sleep ( rand() % 5); sem_post( &product_number ); } } void *consumer ( void * arg ) { static int c = 0; for( ;; ) { sem_wait( &product_number ); printf("Consume %d\n", queue[c]); c = (c+1) % NUM; sleep( rand() % 5 ); sem_post( &blank_number ); } } int main(int argc, char *argv[] ) { pthread_t pid, cid; sem_init( &blank_number, 0, NUM ); sem_init( &product_number, 0, 0); pthread_create( &pid, NULL, producer, NULL); pthread_create( &cid, NULL, consumer, NULL); pthread_join( pid, NULL ); pthread_join( cid, NULL ); sem_destroy( &blank_number ); sem_destroy( &product_number ); return 0; }
這個代碼與condvar類似,只是semphore中使用的是sem_wait和sem_post,condvar中使用互斥鎖。
函數sem_post( sem_t *sem )用來增長信號量的值。當有線程阻塞在這個信號量上時,調用這個函數會使其中的一個線程不在阻塞,選擇機制一樣是由線程的調度策略決定的。
函數sem_wait( sem_t sem )被用來阻塞當前線程直到信號量sem的值大於0,解除阻塞後將sem的值減一,代表公共資源經使用後減小。
代碼中定義了3個函數,thr_fn 1,thr_fn 2和thr_fn 3。這三個函數也對應着線程終止的三個方法:從線程函數return、調用pthread_exit終止本身、調用pthread_cancel終止同一進程中的另外一個線程。此代碼目的是獲取線程的終止狀態。
一、有關exec系列函數,下面說法正確的是() A.能夠用char[][] 來傳遞argv B.進程調用了exec系列函數後,pid會變 C.進程調用了exec系列函數後,代碼會改變。 D.system()和exec系列等價。 E.exec系列函數中帶e的要傳入環境變量參數 F.exec系列函數中帶v的要傳入環境變量參數
正確答案: C E 。不能用char[][] 來傳遞argv,結尾的0(null)沒法處理;system=fork+exec+wait;
二、關於代碼 int main(){} 說法正確的是() A.返回值是0 B.返回值不肯定 C.會調用exit(0) D.返回值大於0 E.上面代碼運行完,在命令行中運行echo $? 的值是0
正確答案: A C E 。
main中不調用exit,會補上exit(0)
三、x86-64中指令長度是()字節 A.1 B.2 C.4 D.1-4 E.1-8 F.1-15 G.1-16 H.以上都不對
正確答案:F
- [20155320](http://www.cnblogs.com/ljq1997/) - 結對照片 - 結對學習內容 - 教材第11、二章的內容 - 對代碼的練習
學習了兩章的內容,由於以前劉念老師課上學到的知識距離老師要求的還頗有距離,因此又從新看了一遍。
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 0/0 | 1/1 | 10/20 | |
第二週 | 57/100 | 1/1 | 20/30 | |
第三週 | 100/100 | 1/1 | 30/30 | |
第四周 | 233/200 | 1/1 | 20/20 | |
第五週 | 267/200 | 1/1 | 20/20 | |
第六週 | 220/2000 | 3/1 | 40/20 | |
第七週 | 362/300 | 1/1 | 30/30 | |
第八週 | 3000/300 | 3/1 | 45/30 |
嘗試一下記錄「計劃學習時間」和「實際學習時間」,到期末看看能不能改進本身的計劃能力。這個工做學習中很重要,也頗有用。
耗時估計的公式
:Y=X+X/N ,Y=X-X/N,訓練次數多了,X、Y就接近了。
計劃學習時間:30小時
實際學習時間:45小時
改進狀況:
(有空多看看現代軟件工程 課件
軟件工程師能力自我評價表)