客戶端和服務端是進程
html
命名機制 傳送機制
TCP是一個構建在IP之上的複雜協議,提供了進程間可靠地全雙工鏈接
linux
對inet-aton的調用傳遞的是指向結構的指針,而對inet_ntoa的調用傳遞的是結構自己git
某些合法域名沒有映射到任何IP地址程序員
套接字地址:(地址:端口)
web
sin_family成員是AF_INET sin_port成員是一個16位端口 sin_addr成員是32位的IP地址
客戶端和服務端使用socket函數來建立一個套接字描述符編程
創建和服務器的鏈接。數組
將socket和connect函數包裝而成。客戶端能夠用它來和服務器創建鏈接。瀏覽器
告訴內核將my_addr中的服務器套接字地址和套接字描述符sockfd聯繫起來安全
將sockfd從一個主動套接字轉化爲一個監聽套接字服務器
均被服務器用於和客戶端創建鏈接。
socket、bind和listen函數結合。用於服務器建立一個監聽描述符。
Web內容能夠用一種叫作 HTML(Hypertext Markup Language,超文本標記語言)的語言來編寫。一個 HTML 程序(頁)包含指令(標記),它們告訴瀏覽器如何顯示這頁中的各類文本和圖形對象。
每條由Web服務器返回的內容都是和他管理的某個文件相關聯的。這些文件每個都有一個惟一的名字,叫作:URL
進程 I/O多路複用 線程
第一步:服務器接受客戶端的鏈接請求 第二步:服務器派生一個子進程爲這個客戶端服務 第三步:服務器接受另外一個鏈接請求 第四步:服務器派生另外一個子進程爲新的客戶端服務
最後,知道父子進程的connfd都關閉了,到客戶端的鏈接纔會終止
優勢:一個進程不可能不當心覆蓋另外一個進程的虛擬存儲器 缺點:獨立的地址空間使得進程共享信息變得更加困難;IPC機制每每比較慢
分配 將一個此種類型的變量賦值給另外一個變量 用FD_ZERO、FD_SET等宏指令來修改和檢查它們
狀態:等待描述符dk準備好可讀 輸入事件:描述符dk準備好能夠讀了 轉移:從描述符dk讀一個文本行
check_clients:爲準備好的客戶端鏈接服務
缺點:編碼複雜
每一個對等線程都能讀寫相同共享數據
現成的代碼和本地數據被封裝在一個線程例程中
新線程能夠經過調用pthread_self函數來得到它本身的線程ID
另外一個對等線程經過調用pthread_cancle函數來終止當前線程
與wait函數不一樣,pthread_join函數只能等待一個指定的線程終止
pthreaddetach 函數分離可結合線程 tid. 線程可以經過以 pthreadself()爲參數的 pthread_detach 調用來分離它們本身。
once_control變量是一個全局或者靜態變量
調用 pthread_ create 時,如何將已鏈接描述符傳遞給對等線程。最明顯的方法就是傳遞一個指向這個描述符的指針。 對等線程間接引用這個指針,並將它賦值給一個局部變量。
若是一個線程以某種方式獲得一個指向其餘線程棧的指針,那麼它就能夠讀寫這個棧的任何部分
本地靜態變量:本地靜態變量是定義在函數內部有static屬性的變量
msgs這樣的本地自動變量也能被共享
合法的轉換是向右或者向上,即某一個線程中的一條指令完成 兩條指令不能在同一時刻完成,即不容許出現對角線 程序不能反向運行,即不能出現向下或向左 而一個程序的執行歷史被模型化爲狀態空間中的一條軌跡線。 線程循環代碼的分解: H:在循環頭部的指令塊 L:加載共享變量cnt到線程i中寄存器%eax的指令。 U:更新(增長)%eax的指令 S:將%eax的更新值存回到共享變量cnt的指令 T:循環尾部的指令塊
安全軌跡線:繞開不安全區的軌跡線
P(s):若是s是非零的,那麼P將s-1,而且當即返回;若是s爲零,那麼就掛起這個線程,直到s變爲非零 V(s):V操做將s+1
信號量不變性:一個正在運行的程序毫不能進入這樣一種狀態,也就是一個正確初始化了的信號量有一個負值。
計數信號量:一個唄用做一組可用資源的計數器的信號量
pthread_creat:建立線程,若成功則返回0,若失敗則返回出錯編號。第一個參數爲指向線程標識符的指針,建立成功時指向的內存單元被設置爲新建立線程的線程ID;第二個參數設置線程屬性;第三個參數是線程運行函數的起始地址;最後一個參數是運行函數的參數 pthread_join:用來等待一個線程的結束。當函數返回時,被等待線程的資源被收回。 pthread_mutex_lock:線程調用該函數讓互斥鎖上鎖。成功鎖定時返回0,其餘任何返回值都表示出現了錯誤。 pthread_mutex_unlock:與pthread_mutex_lock成對存在。釋放互斥鎖。
主函數中用srand(time(NULL))
設置當前的時間值爲種子,在後面的producer和consumer函數中調用rand()函數產生隨機數。
mmap函數 `void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);` 將一個文件或者其餘對象映射進內存。文件被映射到多個頁上,若是文件的大小不是全部頁的大小之和,最後一個頁不被使用的空間將會清零。mmap在用戶空間映射調用系統中做用很大。 成功執行時,mmap()返回被映射區的指針,munmap()返回0.失敗時,mmap()返回MAP_FAILED,munmap返回-1.
lseek函數 off_t lseek(int fd,off_t offset,int whence); fd表示要操做的文件描述符,offset是相對於whence(基準)的偏移量,whence能夠是SEEK_SET(文件指針開始),SEEK_CUR(文件指針當前位置),SEEK_END(文件指針尾) lseek主要做用是移動文件讀寫指針,返回文件讀寫指針距文件開頭的字節大小,若出錯則返回-1.
運行結果
主函數中先利用pthread_create()函數建立一個線程,接着調用printids函數(打印標識符的函數)打印主線程號,最後線程函數thr_fn中打印出新建的線程號
-lm
,能夠成功編譯,運行結果提示了段錯誤。1)訪問系統數據區,尤爲是往 系統保護的內存地址寫數據 最多見就是給一個指針以0地址 2)內存越界(數組越界,變量類型不一致等 3)訪問到不屬於你的內存區域
閱讀代碼後仍沒找到錯誤,問題還沒有解決。
sem_init函數 sem_init(sem_t *sem, int pshared, umsigned int value); 函數初始化一個定位在sem的匿名信號量;pshared參數爲0指明信號量是由進程內線程共享,若爲非0值則信號量在進程之間共享;value參數指定信號量的初始值。 sem_init()成功時返回0;錯誤時返回-1,並把errno設置爲合適的值。 sem_destroy()函數用於銷燬由sem指向的匿名信號量。只有經過sem_init()初始化的信號量才應該使用該函數銷燬。函數成功時返回0,錯誤時返回-1,並把errno設置爲合適的值。 這個函數和以前的condvar.c同樣都是展現生產者和消費者交替工做的過程。區別是本程序實現生產或消費的過程是利用sem_wait()和sem_post(),它們的做用分別是從信號量的值減去一個「1」和從信號量的值加上一個「1」
運行結果截圖
代碼運行結果以下
修改後代碼運行以下
代碼運行結果以下
根據代碼,先單獨執行print_msg("hello");——輸出5個hello,後輸出5個帶換行的world
因爲定義中NUM=5,因此輸出的count爲1——5
twordcount4.c運行以下
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 200/200 | 2/2 | 20/20 | |
第二週 | 200/400 | 2/4 | 18/38 | |
第三週 | 100/500 | 1/5 | 10/48 | |
第四周 | 250/750 | 1/6 | 10/58 | |
第五週 | 100/850 | 1/7 | 10/68 | |
第六週 | 100/950 | 1/8 | 12/80 | |
第七週 | 200/1150 | 1/9 | 12/92 | |
第八週 | 124/1274 | 2/11 | 10/102 | |
第九周 | 205/1479 | 2/13 | 5/107 | |
第十週 | 646/2125 | 2/15 | 9/116 | |
第十一週 | 421/2546 | 2/17 | 12/128 | |
第十二週 | 752/3298 | 3/10 | 11/139 | |
第十三週 | 1001/4299 | 1/21 | 12/151 |