入門
- 包含了正確的頭文件只能編譯通過,沒鏈接正確的庫鏈接會報錯圣拄。
- 一些常用的庫gcc會自動鏈接庇谆。
- 庫的缺省路徑/lib /usr/lib /usr/local/lib
- 不知道某個函數(shù)在那個庫可以nm -o /lib *.so | grep 函數(shù)名
- man sin 會列出包含的頭文件和鏈接的庫名。man 2 sin 2表示系統(tǒng)調(diào)用岩四,3表示c庫函數(shù)
- 一旦子進程被創(chuàng)建哥攘,父子進程一起從fork處被創(chuàng)建剖煌。創(chuàng)建子進程為了爭奪資源。
- 重定向用dup2函數(shù)
- kill -l查看信號種類
- pthread_mutex不跨進程逝淹,ipc中的信號量跨進程,但linux不支持無名信號量茉兰。信號燈的主要用途是保護臨界資源规脸。多進程訪問共享內(nèi)存熊咽,用信號量同步。
- alarm(5)5秒后向自己發(fā)送SIGALARM信號被因,缺省處理是結(jié)束進程梨与,不自定義就會結(jié)束進程文狱。通過對信號集加減信號如贷,確定信號屏蔽字。在信號處理程序被調(diào)用時,操作系統(tǒng)建立的新信號屏蔽字包括正在被遞送的信號楣富,如果此時這個信號再次發(fā)生伴榔,將阻塞到前一個處理完,多次發(fā)生不排隊只處理一次塘安。 sa_mask會被加到信號屏蔽字中兼犯。
- netstat -an|grep A |grep ESTABLISHED | grep B,查看ip為A的服務(wù)器是否在端口B建立了連接
- 由于我們的連接都是常連接砸脊,故可以按照客戶端與服務(wù)器端建立的連接端口進行判斷凌埂。
- IP協(xié)議是網(wǎng)絡(luò)層協(xié)議瞳抓,主要發(fā)送數(shù)據(jù)包伏恐。UDP基于IP協(xié)議脐湾,用在傳輸層。TCP協(xié)議建立在IP協(xié)議之上愁铺,可靠的茵乱、按順序發(fā)送的孟岛。
- TCP連接三次握手:客戶機向服務(wù)器發(fā)包渠羞。服務(wù)器給客戶機回包次询。客戶機收到包送巡,向服務(wù)器發(fā)送確認信息完成連接骗爆。服務(wù)器收到確認信息也完成連接。
- ioctl可以控制所有文件描述符的情況煮寡。
- 循環(huán)服務(wù)器:UDP服務(wù)器洲押,UDP是非面向連接的圆凰,沒有一個客戶機可以老是占著服務(wù)器。
- TCP循環(huán)服務(wù)器一次只能處理一個挑童,close后才能處理下一個站叼。
- TCP并發(fā)服務(wù)器:fork子進程來處理尽楔。創(chuàng)建子進程消耗資源阔馋。
- 并發(fā)服務(wù)器:多路IO復用娇掏。
- 當我們創(chuàng)建一個正常的TCP套接字的時候婴梧,我們只處理內(nèi)容塞蹭,不負責TCP頭部和ip頭部,自己創(chuàng)建頭部使用setsockopt竟坛。
- 網(wǎng)絡(luò)程序一般是多進程加上多線程担汤。
- g++參數(shù)-pg產(chǎn)生gprof性能信息崭歧,gprof好像是g++自帶的
- (gdb)make使你能不退出gdb就能產(chǎn)生就重新產(chǎn)生可執(zhí)行文件 率碾, shell 不退出gdb就執(zhí)行shell
- file a.out可以在gdb模式下載入程序所宰。
- 服務(wù)器端:socket->bind->listen【建立監(jiān)聽隊列仔粥,監(jiān)聽socket】->【返回連接socket】accept【從監(jiān)聽隊列取請求躯泰,成功時返回新的socket华糖,與傳入的第一參數(shù)不同诵竭,標識被接受的這個連接】
- 客戶端:socket->connect
進階
- linux中代替數(shù)據(jù)庫管理文件可能會出現(xiàn)文件數(shù)超過linux可管理數(shù)的問題兼搏。
- tcpip協(xié)議族:上層協(xié)議使用下層協(xié)議提供的服務(wù)。
- 應(yīng)用層的東西最后需要在內(nèi)核中實現(xiàn)呵燕,會需要應(yīng)用空間和內(nèi)核空間的切換。
- IP數(shù)據(jù)太長要分片夜矗。IP協(xié)議的核心是數(shù)據(jù)報路由。路由表罢荡、跳轉(zhuǎn)惭缰、自動更新漱受。
- socket含義ip:port昂羡。稱其為socket地址摔踱。
- 字節(jié)序是按字節(jié)考慮的虐先,和位無關(guān)。cpu累加器一次裝載4字節(jié)(32位機)派敷。
- 網(wǎng)絡(luò)上傳的一定是大端字節(jié)序蛹批,各主機按自身情況轉(zhuǎn)化。java虛擬機采用大端字節(jié)序膀息。
- 不同輸入調(diào)用兩次函數(shù)般眉,如果發(fā)現(xiàn)后面結(jié)果覆蓋前面結(jié)果,說明函數(shù)不可重入潜支。函數(shù)內(nèi)部如果用靜態(tài)變量存儲結(jié)果甸赃,就不可重入。
- 將一個地址和socket綁定稱為給socket命名冗酿。0-1023端口普通用戶不能使用裁替,有默認用途襟沮。
- accept只是從監(jiān)聽隊列中取出連接遭商,不論連接處于何種狀態(tài)丛忆。connect(fd,..)一旦連接建立成功,fd就唯一標識了這個連接根穷,客戶端就可以讀寫fd和服務(wù)器通信圈澈。
- 對socket執(zhí)行close只減少連接數(shù)啥么,fork會使引用數(shù)加1。無論如何都要終止連接用shutdown。
- read和write同樣適用于socket。用于TCP數(shù)據(jù)流的是send recv。UDP數(shù)據(jù)是recvfrom sendto。
- 沒有進程讀管道的時候【例如close(fd[0])了】還往管道寫數(shù)據(jù)將引發(fā)SIGPIPE舟扎。
- 把STDOUT_FILENO關(guān)閉,dup(連接socket)染服,這時dup返回最小可用描述符1【返回的文件描述符和原有描述符指向相同文件】痒钝,此時printf回返回給客戶端蚕甥,而不是打印在屏上爱沟。
- sendfile將真實文件傳給socket蜂大。splice用于在兩個文件描述符間移動數(shù)據(jù)踢星,零拷貝,用于socket和管道之間互相定向。tee用于兩個管道之間復制數(shù)據(jù)遥椿。
- IO處理單元是一個專門的接入服務(wù)器碴裙,它實現(xiàn)負載均衡。請求隊列是系統(tǒng)內(nèi)部各單元之間通信方式的抽象娃肿,一般實現(xiàn)為池晒杈。
- 阻塞和非阻塞是對文件描述符而言的撰豺。非阻塞IO一般和IO通知機制一起使用,如IO復用或SIGIO信號稼钩。IO復用本身是阻塞的,提高效率是因為同時監(jiān)聽多個事件塔沃。
- 同步就是協(xié)同步調(diào),按預(yù)定的先后次序進行運行蛀柴。處理客戶連接就是讀寫描述符螃概,就是IO,所以IO單元被定義為接入服務(wù)器鸽疾。
- 并發(fā)不適用于計算密集型豺鼻,因為任務(wù)切換會降低效率儒飒,適用于IO密集型,如經(jīng)常讀寫文件欠啤、訪問數(shù)據(jù)庫。
- 池就是預(yù)先靜態(tài)分配資源铃慷,到時可以快速使用。避免了對內(nèi)核的頻繁訪問馋缅。提升性能方法:池扒腕、避免數(shù)據(jù)復制、上下文切換【線程數(shù)大于cpu數(shù)時】和鎖股囊。
- 讀寫鎖可以減少鎖的粒度適用于讀多寫少的情況袜匿。
- epoll需要使用一個額外的描述符維護事件表。 EPOLLONESHOT確保只有一個線程處理某個socket稚疹。
- sigaction結(jié)構(gòu)體中的sa_mask設(shè)置信號掩碼,確切的說是在進程原有信號掩碼的基礎(chǔ)上增加信號掩碼祭务,以指定哪些信號不能發(fā)送給本進程内狗。
- sigset_t 每個元素的每個位表示一個信號,所以相同的信號只能表示一次义锥。
- 子進程有和父進程相同的信號掩碼柳沙,但掛起信號集【發(fā)送但是被阻塞的信號】為空,就是說阻塞的信號是不可能發(fā)給子進程的拌倍。
- 應(yīng)用程序使用信號集sigset_t前赂鲤,應(yīng)調(diào)用sigemptyset或sigfillset一次,否則信號集初始狀態(tài)不清楚柱恤。
- 最小時間堆可以達到定時器的效果数初。
- waitpid用NOHANG就是非阻塞的了。socketpair創(chuàng)建全雙工管道的系統(tǒng)調(diào)用梗顺。
- 對信號量的操作成為P(傳遞泡孩,進入臨界區(qū))V(釋放,退出臨界區(qū))寺谤。最簡單的二進制信號量仑鸥,只有0和1.用一個普通變量模擬是不行的吮播,因為檢測和減1無法原子完成。
- linux上的線程使用clone系統(tǒng)調(diào)用創(chuàng)建的進程模擬的眼俊。
- 目前可以實現(xiàn)跨進程的線程同步
- 被pthread_cancel的線程可以決定是否允許被取消以及如何取消意狠。
- 銷毀一個已經(jīng)加鎖的互斥量將導致不可知的后果〈郑互斥量屬性設(shè)置中可以設(shè)置跨進程共享互斥量环戈。pthread_mutexattr_setpshared()
- 加鎖-》pthread_cond_wait暗含解鎖,確保能檢測到條件變量的任何變化获列。
- 有些函數(shù)不可重入主要是因為內(nèi)部使用了靜態(tài)變量谷市。
- 多線程程序中的一個線程調(diào)用fork,只復制調(diào)fork的那個線程击孩∑扔疲互斥量的狀態(tài)也繼承,此時容易出現(xiàn)死鎖巩梢。
- 所有線程共享信號處理函數(shù)创泄,共享進程的信號。所以需要專門線程處理所有信號括蝠。
- 進程池:典型的是3-10個鞠抑。線程池中的線程數(shù)量應(yīng)該和cpu數(shù)量差不多。通信【通信:傳遞數(shù)據(jù)】父子進程間可以使用管道忌警,多線程間使用一個全局數(shù)據(jù)即可搁拙。
- pthread_create當線程函數(shù)是類的成員函數(shù)時,必須為靜態(tài)函數(shù)【確保沒對象時也可以使用】法绵,由于靜態(tài)成員函數(shù)只能訪問靜態(tài)成員箕速,要訪問動態(tài)成員需要函數(shù)內(nèi)部用單例或?qū)㈩惖膶ο笞鳛閰?shù)傳給函數(shù)。
- SA_RESTART被信號中斷的系統(tǒng)調(diào)用再信號處理結(jié)束后繼續(xù)執(zhí)行朋譬。
- 將線程池或進程池中個數(shù)減少為1盐茎,便于調(diào)試邏輯。然后逐步增加數(shù)量徙赢,看同步字柠。
- 進程類[i].fd 通過給不同i的fd傳遞數(shù)據(jù),調(diào)用不同的進程工作狡赐。m_sub_process[i].pid=fork()【fork了maxnum次】窑业。
- 線程池:線程函數(shù)一起都啟動,啟動后進入while(!stop)循環(huán)阴汇,不斷的鎖隊列数冬,取任務(wù)。
POSIX線程
- 只有互斥量的主人能夠解鎖它。
- 線程的堆棧受限拐纱。
- 線程結(jié)束方式要么從線程函數(shù)return铜异,要么調(diào)用pthread_exit,進入終止態(tài)秸架,直到被分離或被連接揍庄。創(chuàng)建不需要連接的線程應(yīng)該使用detachstate屬性建立線程使其自動分離。
- pthread_join會阻塞調(diào)用者东抹,直到被join的線程結(jié)束蚂子,join返回被連接的線程也分離,所以只能被join一次缭黔,下一次就錯誤了食茎。
- 使用條件變量時必須保證如果有線程等待,則該線程等待后必然會收到信號(if/while)
- 條件變量可以使線程處于等待狀態(tài)而不消耗資源馏谨。條件變量必須跟一個互斥變量一起使用别渔,因為條件變量就是共享的全局數(shù)據(jù)?惧互?【條件和鎖結(jié)合共同保護共享數(shù)據(jù)】status = pthread_cond_wait(&alarm_cond, &alarm_mutex);
- 沒有條件變量哎媚,程序員可用使用輪詢某個變量來實現(xiàn)停等-通知同步,但是非常消耗系統(tǒng)資源喊儡。
- 如果確定線程不需要被Join, 則申明為Detached可以節(jié)省系統(tǒng)資源
- pthread_self獲得自身的ID拨与,只能通過ID操作線程。main是主線程艾猜,主線程停止所有線程也停止买喧,main中調(diào)用pthread_exit,這樣進程就必須等待所有線程結(jié)束才能終止匆赃。
- 通過向pthread_t(ID)=pthread_create傳遞線程函數(shù)地址和函數(shù)參數(shù)來創(chuàng)建線程岗喉。注意當前線程從pthread_create返回前,新創(chuàng)建的線程可能已經(jīng)運行完畢了炸庞。
- 舀水桶類似一個互斥量:桶用來保護“舀水”臨界區(qū)【訪問臨界資源(共享數(shù)據(jù)?)的那段程序是臨界區(qū)】荚斯〔壕樱或者將桶理解為:用來確保一次只能由一個人舀水的不變量。
- 在訪問共享數(shù)據(jù)的代碼段周圍加鎖互斥量事期,則一次只能有一個線程進入該代碼段滥壕。
- pthread_mutex_t表示互斥量,不能拷貝兽泣,可以拷貝指針绎橘。
- 當調(diào)用pthread_mutex_lock時,如果互斥量已經(jīng)被鎖住,線程將被阻塞称鳞。調(diào)用pthread_mutex_trylock時不會阻塞涮较,會返回EBASY,可以做其他的事情去冈止。
- 互斥量的本質(zhì)是串行執(zhí)行狂票。
- 解決死鎖的兩種方法:一,規(guī)定加鎖順序熙暴;二闺属,trylock如果不行回退,解鎖所有已加鎖的互斥量
- sched_yield()將處理器交給另一個等待處理的線程周霉,如果沒有等待處理的線程掂器。立即返回。sleep()可以確保其他線程有機會運行俱箱。
- 按照相反的順序解鎖国瓮,有助于減少線程做回退操作的可能。因為同一個線程函數(shù)中加鎖順序是一樣的匠楚。對于不同的線程函數(shù)順序應(yīng)該不重要
- 線程運行于解鎖和阻塞之間時巍膘,其他線程才能改變共享數(shù)據(jù)狀態(tài)。此時共享狀態(tài)的改變芋簿,本線程是無法知道的峡懈。->需要條件變量。隊列滿与斤,隊列空肪康,滿空就是條件變量。
- 動態(tài)初始化的條件變量需要pthread_cond_destroy來釋放撩穿。靜態(tài)初始化的不必釋放磷支。釋放前確保其他線程不使用他。
- 在阻塞線程之前食寡,條件變量等待操作pthread_cond_wait將解鎖互斥量雾狈,重新返回線程之前,會再次鎖住互斥量抵皱。子線程只在pthread_cond_wait等待的短時間內(nèi)可以加鎖善榛,修改共享數(shù)據(jù),然后解鎖呻畸。
- pthread_cond_timedwait的意思就是我在這里等time時間移盆,如果時間內(nèi)條件變量變了,或者不變伤为,我都要跳出while(謂詞)的循環(huán)咒循,按情況處理。
- pthread_cond_wait和pthread_cond_signal必須同時發(fā)生才能成功。
- 互斥量:條件變量是 一對多的關(guān)系
- 當線程調(diào)用pthread_create時叙甸,她所能看到的內(nèi)存值也是它建立的線程能看到的颖医,之后的線程不一定能看到。
- 線程解鎖互斥量時所看到的的數(shù)據(jù)蚁署,也能被后來直接鎖住相同互斥量的線程看到便脊。解鎖后寫入的數(shù)據(jù),不必被其他線程看見(因為那不是用來同步的數(shù)據(jù)光戈,沒必要所有人看見哪痰,同步就應(yīng)該加鎖)。
- 線程終止久妆,取消晌杰,從啟動函數(shù)返回,pthread_exit時看到的數(shù)據(jù)筷弦,能夠被連接該線程的其他線程看到肋演。終止后寫入的數(shù)據(jù)不會被看到。
- 線程發(fā)信號或廣播時看到的內(nèi)存數(shù)據(jù)烂琴,可以被喚醒線程看到爹殊。之后寫入的不會。
- 線程分配的堆棧和堆空間是私有的奸绷,除非傳給其他線程指針梗夸。register(寄存器變量)和auto變量(大部分變量默認auto)(static變量的生命期長)中的數(shù)據(jù)可隨時讀取,像在同步程序中一樣
- 兩個處理器將各自的高速緩存中的數(shù)據(jù)寫入主存的順序是不一定的号醉,即使寫到相應(yīng)高速緩存的順序有先后之分反症。同一線程寫數(shù)據(jù)也未必按照順序刷新進內(nèi)存,這使得其他線程讀取結(jié)果不對畔派。
- 鎖住互斥量->內(nèi)存屏障->內(nèi)存屏障->解鎖互斥量
- 使用線程的方式:流水線铅碍、工作組(工作線程在數(shù)據(jù)的不同部分操作)、C/S线椰。
- pthread_attr_setdetachstate (&_attr, PTHREAD_CREATE_DETACHED);說明在創(chuàng)建線程后胞谈,我們不在需要使用線程ID。
- 不變量(Invariant):程序所做的一些假設(shè)憨愉,特別是指變量之間的關(guān)系呜魄。判定條件(Predicates):描述不變量狀態(tài)的邏輯表達式。
- pthread_kill(thdid, SIGTERM)給特定線程發(fā)信號