切記預編譯和編譯與處理是兩個不一樣的概念(網上不少人都把這兩個混爲一談,包括百度百科)node
預編譯就是將一些經常使用的、被反覆使用的並且幾乎不改變的代碼進行提早編譯放到一個文件中,這樣即便程序中其餘部分進行了修改,在編譯時也不須要對預編譯好部分進行從新編譯,大大提升了編譯時的效率。linux
一般有兩種狀況須要預編譯。面試
第一種狀況就是,程序中經常使用的模塊,好比某些通用的函數,這些函數會被重複使用,並且代碼穩定,幾乎不怎麼被修改,這時候咱們就能夠將這些模塊進行預編譯並生成函數庫。chrome
第二種狀況是,對於程序中多個模塊都須要包含的頭文件,咱們能夠將他們放到一塊兒,而後進行預編譯,也就是「預編譯頭」技術,VS中的stdafx.h就是處理這種狀況的。瀏覽器
庫的概念?服務器
庫是寫好的現有的,成熟的,能夠複用的代碼。現實中每一個程序都要依賴不少基礎的底層庫。
網絡
動態庫與靜態庫的概念多線程
先回顧一下編譯過程:socket
靜態庫在連接階段,會將彙編生成的目標文件.o與引用到的庫一塊兒連接打包到可執行文件中,對應的連接方式稱爲靜態連接。試想一下,靜態庫與彙編生成的目標文件(.o文件)一塊兒連接爲可執行文件,那麼靜態庫一定跟.o文件格式類似。其實一個靜態庫能夠函數
簡單當作是一組目標文件(.o/.obj文件)的歸檔集合,即不少目標文件通過壓縮打包後造成的一個文件。靜態庫特色總結:
一、靜態庫對函數庫的連接是放在編譯時期完成的。
二、程序在運行時與函數庫再無瓜葛,移植方便。
三、浪費空間和資源,由於全部相關的目標文件與牽涉到的函數庫被連接合成一個可執行文件。
除了上面提到的浪費空間和資源的弊端,使用靜態庫還有另外一個問題:對程序的更新、部署和發佈頁會帶來麻煩。若是靜態庫libtest.a更新了,全部使用它的應用程序都須要從新編譯、發佈給用戶。
使用動態庫正好能夠有效解決靜態庫的這些問題:動態庫在程序編譯時並不會被鏈接到目標代碼中,而是在程序運行是才被載入。不一樣的應用程序若是調用相同的庫,那麼在內存裏只須要有一份該共享庫的實例,規避了空間浪費問題。動態庫在程序運行是才被載入,也解決了靜態庫對程序的更新、部署和發佈頁會帶來麻煩。用戶只須要更新動態庫便可,增量更新。
gcc中靜態庫使用ar命令,實際上就是打包編譯好的.o文件
而動態庫使用gcc中的-shared選項。
volatile修飾的變量,告訴編譯器在讀取該變量值的時候,不要進行優化,而是直接讀取變量的值。
應用:
一、 並行設備的硬件寄存器
二、 中斷服務子程序中會訪問到的非自動變量
三、 多線程應用中被幾個任務共享的變量。
進程:進程是程序運行的實例,是系統進行資源分配和調度的一個獨立單位,它包含獨立的地址空間。
線程:也被叫作輕量級進行,CPU調度的最小單位,使用進程的的地址空間。
進程有本身獨立的地址空間,不一樣進程之間地址空間是不同的。線程使用其所在進程的地址空間,可是擁有本身的堆棧。一個線程死掉會影響到該線程所在進程的全部線程,可是一個進程死掉卻不影響其餘進程的運行(360和chrome標籤頁)
exec是替換進程映像
當進程調用一種exec函數時,源進程徹底由新程序代換,而新程序則從其main函數開始執行。由於調用exec並不建立新進程,因此先後的進程ID並未改變。exec只是用另外一個新程序替換了當前進程的正文、數據、堆和棧段。特別地,在原進程中已經打開的文件描述符,在新進程中仍將保持打開,除非它們的「執行時關閉標誌」(close on exec flag)被置位。任何在原進程中已打開的目錄流都將在新進程中被關閉。
fork函數是複製進程映像
咱們能夠經過調用fork建立一個新進程。這個系統調用複製當前進程,在進程表中新建一個新的表項,新表項中的許多屬性與當前進程是相同的。新進程幾乎與元進程如出一轍,執行的代碼也徹底相同,可是新進程有本身的數據空間、環境和文件描述符。
system是先fork再exec
好比ctrl-c 發送 SIGINT 信號,用於終止正在運行的程序。
ctrl-z 發送 SIGTSTP 信號,經常使用於掛起一個進程。
在程序中能夠設計本身的信號處理函數,來進行進程間的通訊。
管道是一個存在於內核空間(內存中)的特殊文件,而且數據只能單向流動,並且只能用於具備親緣關係的進程間(即父子進程,兄弟進程),無親緣關係的進程是不能使用的。若是要使用管道進行全雙工通訊,那麼就要創建兩個管道,經過管道通訊的兩個進程,一個進程向管道寫數據,而另外一個進程從管道讀數據。
命名管道是創建在實際的磁盤介質或文件系統(而不是隻存在於內存中)上有本身名字的文件,任何進程能夠在任什麼時候間經過文件名或路徑名與該文件創建聯繫。爲了實現命名管道,引入了一種新的文件類型——FIFO文件(遵循先進先出的原則)。實現一個命名管道實際上就是實現一個FIFO文件。命名管道一旦創建,以後它的讀、寫以及關閉操做都與普通管道徹底相同。雖然FIFO文件的inode節點在磁盤上,可是僅是一個節點而已,文件的數據仍是存在於內存緩衝頁面中,和普通管道相同。
顧名思義,共享內存就是容許兩個不相關的進程訪問同一個邏輯內存。共享內存是在兩個正在運行的進程之間共享和傳遞數據的一種很是有效的方式。不一樣進程之間共享的內存一般安排爲同一段物理內存。進程能夠將同一段共享內存鏈接到它們本身的地址空間中,全部進程均可以訪問共享內存中的地址,就好像它們是由用C語言函數malloc分配的內存同樣。而若是某個進程向共享內存寫入數據,所作的改動將當即影響到能夠訪問同一段共享內存的任何其餘進程。
linux中
shmget函數用來建立共享內存
互斥體和信號量還有管程
信號量機制的引入解決了進程同步的描述問題,但信號量的大量同步操做分散在各個進程中不便於管理,還有可能致使系統死鎖。如:生產者消費者問題中將P、V顛倒可能死鎖。
爲此Dijkstra於1971年提出:把全部進程對某一種臨界資源的同步操做都集中起來,構成一個所謂的祕書進程。凡要訪問該臨界資源的進程,都需先報告祕書,由祕書來實現諸進程對同一臨界資源的互斥使用。
競爭資源和進程間推動順序非法
(1) 互斥條件:一個資源每次只能被一個進程使用。
(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已得到的資源保持不放。
(3) 不剝奪條件:進程已得到的資源,在末使用完以前,不能強行剝奪。
(4) 循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係。
main函數的返回值用於說明程序的退出狀態。若是返回0,則表明程序正常退出;返回其它數字的含義則由系統決定
從main返回。
調用exit
調用_eixt或者_Exit
最後一個線程從啓動例程返回
最後一個線程調用pthread_exit
答案:*((void (*)( ))0x100000 ) ( ); 首先要將0x100000強制轉換成函數指針,即: (void (*)())0x100000 而後再調用它: *((void (*)())0x100000)(); 用typedef能夠看得更直觀些: typedef void(*)() voidFuncPtr; *((voidFuncPtr)0x100000)();
DLL沒有本身的棧區,須要依賴於線程的棧,可是有本身的堆,因此在DLL堆中申請的資源最好在DLL中釋放。
一個進程建立的多個線程:每一個線程都擁有本身私有的Stack,但共享一個Heap
switch中表達式只能爲整型、字符型、枚舉型,case語句中的表達式也同樣
首先,每一個主機都會在本身的ARP緩衝區中創建一個ARP列表,以表示IP地址和MAC地址之間的對應關係。
2:當源主機要發送數據時,首先檢查ARP列表中是否有對應IP地址的目的主機的MAC地址,若是有,則直接發送數據,若是沒有,就向本網段的全部主機發送ARP數據包,該數據包包括的內容有:源主機 IP地址,源主機MAC地址,目的主機的IP 地址。
3:當本網絡的全部主機收到該ARP數據包時,首先檢查數據包中的IP地址是不是本身的IP地址,若是不是,則忽略該數據包,若是是,則首先從數據包中取出源主機的IP和MAC地址寫入到ARP列表中,若是已經存在,則覆蓋,而後將本身的MAC地址寫入ARP響應包中,告訴源主機本身是它想要找的MAC地址。
4:源主機收到ARP響應包後。將目的主機的IP和MAC地址寫入ARP列表,並利用此信息發送數據。若是源主機一直沒有收到ARP響應數據包,表示ARP查詢失敗。
廣播發送ARP請求,單播發送ARP響應。
客戶端瀏覽器經過DNS解析到www.baidu.com 的IP地址220.181.27.48,經過這個IP地址找到客戶端到服務器的路徑。客戶端瀏覽器發起一個HTTP會話到220.181.27.48,而後經過TCP進行封裝數據包,輸入到網絡層。
二、在客戶端的傳輸層,把HTTP會話請求分紅報文段,添加源和目的端口,如服務器使用80端口監聽客戶端的請求,客戶端由系統隨機選擇一個端口如5000,與服務器進行交換,服務器把相應的請求返回給客戶端的5000端口。而後使用IP層的IP地址查找目的端。
三、客戶端的網絡層不用關心應用層或者傳輸層的東西,主要作的是經過查找路由表肯定如何到達服務器,期間可能通過多個路由器,這些都是由路由器來完成的工做,我不做過多的描述,無非就是經過查找路由表決定經過那個路徑到達服務器。
四、客戶端的鏈路層,包經過鏈路層發送到路由器,經過鄰居協議查找給定IP地址的MAC地址,而後發送ARP請求查找目的地址,若是獲得迴應後就可使用ARP的請求應答交換的IP數據包如今就能夠傳輸了,而後發送IP數據包到達服務器的地址。
答:當DNS客戶機須要在程序中使用名稱時,它會查詢DNS服務器來解析該名稱。客戶機發送的每條查詢信息包括三條信息:包括:指定的DNS域名,指定的查詢類型,DNS域名的指定類別。基於UDP服務,端口53. 該應用通常不直接爲用戶使用,而是爲其餘應用服務,如HTTP,SMTP等在其中須要完成主機名到IP地址的轉換。
交換機
在計算機網絡系統中,交換機是針對共享工做模式的弱點而推出的。交換機擁有一條高帶寬的背部總線和內部交換矩陣。交換機的全部的端口都掛接在這條背 部總線上,當控制電路收到數據包之後,處理端口會查找內存中的地址對照表以肯定目的MAC(網卡的硬件地址)的NIC(網卡)掛接在哪一個端口上,經過內部 交換矩陣迅速將數據包傳送到目的端口。目的MAC若不存在,交換機才廣播到全部的端口,接收端口迴應後交換機會「學習」新的地址,並把它添加入內部地址表 中。
交換機工做於OSI參考模型的第二層,即數據鏈路層。交換機內部的CPU會在每一個端口成功鏈接時,經過ARP協議學習它的MAC地址,保存成一張 ARP表。在從此的通信中,發往該MAC地址的數據包將僅送往其對應的端口,而不是全部的端口。所以,交換機可用於劃分數據鏈路層廣播,即衝突域;但它不 能劃分網絡層廣播,即廣播域。
交換機被普遍應用於二層網絡交換,俗稱「二層交換機」。
交換機的種類有:二層交換機、三層交換機、四層交換機、七層交換機分別工做在OSI七層模型中的第二層、第三層、第四層盒第七層,並所以而得名。
2)路由器
路由器(Router)是一種計算機網絡設備,提供了路由與轉送兩種重要機制,能夠決定數據包歷來源端到目的端所通過 的路由路徑(host到host之間的傳輸路徑),這個過程稱爲路由;將路由器輸入端的數據包移送至適當的路由器輸出端(在路由器內部進行),這稱爲轉 送。路由工做在OSI模型的第三層——即網絡層,例如網際協議。
路由器的一個做用是連通不一樣的網絡,另外一個做用是選擇信息傳送的線路。 路由器與交換器的差異,路由器是屬於OSI第三層的產品,交換器是OSI第二層的產品(這裏特指二層交換機)。
3)網關
網關(Gateway),網關顧名思義就是鏈接兩個網絡的設備,區別於路由器(因爲歷史的緣由,許多有關TCP/IP 的文獻曾經把網絡層使用的路由器(Router)稱爲網關,在今天不少局域網採用都是路由來接入網絡,所以如今一般指的網關就是路由器的IP),常常在家 庭中或者小型企業網絡中使用,用於鏈接局域網和Internet。 網關也常常指把一種協議轉成另外一種協議的設備,好比語音網關。
在傳統TCP/IP術語中,網絡設備只分紅兩種,一種爲網關(gateway),另外一種爲主機(host)。網關能在網絡間轉遞數據包,但主機不能 轉送數據包。在主機(又稱終端系統,end system)中,數據包需通過TCP/IP四層協議處理,可是在網關(又稱中介系 統,intermediate system)只須要到達網際層(Internet layer),決定路徑以後就能夠轉送。在當時,網關 (gateway)與路由器(router)尚未區別。
在現代網絡術語中,網關(gateway)與路由器(router)的定義不一樣。網關(gateway)能在不一樣協議間移動數據,而路由器(router)是在不一樣網絡間移動數據,至關於傳統所說的IP網關(IP gateway)。
網關是鏈接兩個網絡的設備,對於語音網關來講,他能夠鏈接PSTN網絡和以太網,這就至關於VOIP,把不一樣電話中的模擬信號經過網關而轉換成數字信號,並且加入協議再去傳輸。在到了接收端的時候再經過網關還原成模擬的電話信號,最後才能在電話機上聽到。
對於以太網中的網關只能轉發三層以上數據包,這一點和路由是同樣的。而不一樣的是網關中並無路由表,他只能按照預先設定的不一樣網段來進行轉發。網關最重要的一點就是端口映射,子網內用戶在外網看來只是外網的IP地址對應着不一樣的端口,這樣看來就會保護子網內的用戶。