1 進(jìn)程和線程
- 進(jìn)程:具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨立單位.
- 線程:進(jìn)程的一個執(zhí)行單元,是CPU調(diào)度和分派的基本單位,也被稱為稱為輕量級進(jìn)程蚯舱。
關(guān)聯(lián):
- 一個進(jìn)程可以由多個線程或單個線程組成
- 線程與同屬一個進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源。
- 二者均可并發(fā)執(zhí)行辆憔。
區(qū)別:
- 地址空間:進(jìn)程擁有獨立的地址空間杂瘸; 線程共享本進(jìn)程的地址空間揭朝。
- 資源擁有: 進(jìn)程是擁有系統(tǒng)資源的一個獨立單位纽乱,而線程自己基本上不擁有系統(tǒng)資源幸缕,只擁有一點在運行中必不可少的資源(如程序計數(shù)器,一組寄存器和棧)悔详,和其他線程共享本進(jìn)程的相關(guān)資源如內(nèi)存涵亏、I/O宰睡、cpu等。
- 獨立性: 一個進(jìn)程崩潰后溯乒,在保護(hù)模式下不會對其他進(jìn)程產(chǎn)生影響夹厌,但是一個線程崩潰整個進(jìn)程都死掉。所以多進(jìn)程要比多線程健壯裆悄。
- 系統(tǒng)開銷:在進(jìn)程切換時矛纹,涉及到整個當(dāng)前進(jìn)程CPU環(huán)境的保存環(huán)境的設(shè)置以及新被調(diào)度運行的CPU環(huán)境的設(shè)置,而線程切換只需保存和設(shè)置少量的寄存器的內(nèi)容光稼,并不涉及存儲器管理方面的操作或南,可見孩等,進(jìn)程切換的開銷也遠(yuǎn)大于線程切換的開銷。
- 執(zhí)行過程: 每個獨立的線程有一個程序運行的入口采够、順序執(zhí)行序列和程序的出口肄方。但是線程不能夠獨立執(zhí)行,必須依存在應(yīng)用程序中蹬癌,由應(yīng)用程序提供多個線程執(zhí)行控制权她。
2 進(jìn)程之間如何通信
進(jìn)程間通信(IPC,InterProcess Communication)是指在不同進(jìn)程之間傳播或交換信息逝薪。
IPC的方式通常有
- 管道(包括無名管道和命名管道)
- 消息隊列
- 信號量
- 信號
- 消息隊列
- 共享內(nèi)存
- 套接字( socket )隅要、
- 遠(yuǎn)程過程調(diào)用:RPC等。其中 套接字( socket )和遠(yuǎn)程過程調(diào)用:RPC支持不同主機(jī)上的兩個進(jìn)程IPC董济。
1步清、管道( pipe )
既可在程序中使用,也可在shell中使用虏肾。
管道是一種半雙工的通信方式廓啊,數(shù)據(jù)只能單向流動。
管道的問題在于他們沒有名字封豪,只能在具有親緣關(guān)系(父子進(jìn)程間)的進(jìn)程間使用谴轮。
擴(kuò)展:
管道由pipe函數(shù)創(chuàng)建,提供一個單向數(shù)據(jù)流撑毛。當(dāng)需要一個雙向數(shù)據(jù)流時书聚,我們必須創(chuàng)建兩個管道,每個方向一個藻雌。這也就是全雙工管道的實現(xiàn)原理:由兩個半雙工管道構(gòu)成。
2斩个、命名管道 (named pipe) :即FIFO
命名管道也是半雙工的通信方式胯杭。提供單向數(shù)據(jù)流。
克服了管道沒有名字的限制受啥,因此允許無親緣關(guān)系的進(jìn)程間通信做个,解決了管道的上述問題。
擴(kuò)展:
管道和FIFO都是使用通常的read和write函數(shù)訪問滚局。
FIFO由mkfifo函數(shù)創(chuàng)建居暖。FIFO不同于管道的是,每個FIFO有一個路徑名與之關(guān)聯(lián)藤肢,從而允許無親緣關(guān)系的進(jìn)程訪問同一FIFO太闺。
FIFO的真正優(yōu)勢表現(xiàn)在服務(wù)器可以是一個長期運行的進(jìn)程(如守護(hù)進(jìn)程),而且與其客戶可以無親緣關(guān)系嘁圈。
3省骂、信號量( semophore )
主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段蟀淮。
進(jìn)程間通信處理同步互斥的機(jī)制。信號量是一個計數(shù)器钞澳,可以用來控制多個進(jìn)程對共享資源的訪問怠惶。它常作為一種鎖機(jī)制,防止某進(jìn)程正在訪問共享資源時轧粟,其他進(jìn)程也訪問該資源策治。
4、信號 ( sinal )
是一種處理異步事件的方式兰吟。
信號是一種比較復(fù)雜的通信方式览妖,用于通知接收進(jìn)程某個事件已經(jīng)發(fā)生。除了用于進(jìn)程外揽祥,還可以發(fā)送信號給進(jìn)程本身讽膏。
信號和信號量是不同的,他們雖然都可用來實現(xiàn)同步和互斥拄丰,但前者是使用信號處理器來進(jìn)行的府树,后者是使用P,V操作來實現(xiàn)的。
5料按、消息隊列( message queue )
消息隊列是消息的鏈表奄侠,包括Posix消息隊列systemV消息隊列。
有足夠權(quán)限的進(jìn)程都可以向隊列中添加消息载矿,有足夠讀權(quán)限的進(jìn)程都可以讀走隊列中的消息垄潮。
消息隊列克服了信號承載信息量少,管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點闷盔。
擴(kuò)展:
消息隊列具有隨內(nèi)核的持續(xù)性弯洗,這跟管道和FIFO不一樣。當(dāng)一個管道或FIFO的最后一次關(guān)閉發(fā)生時逢勾,仍在該管道或FIFO上的數(shù)據(jù)將被丟棄牡整。
兩種消息隊列:都不使用真正的描述符,因此在消息隊列上使用select或poll是困難的溺拱。兩種消息隊列:在某個進(jìn)程往一個隊列寫入消息之前逃贝,并不需要另外某個進(jìn)程在該隊列上等待消息的到達(dá)。
SystemV消息隊列的問題之一是無法通知一個進(jìn)程何時在某個隊列中放置了一個消息迫摔,也就是無法窺探一個消息沐扳。而Posix消息隊列允許異步事件通知,以告知何時有一個消息放置到了某個空消息隊列中句占。
Posix消息隊列缺失的主要特性是從隊列中讀出指定優(yōu)先級消息的能力沪摄。
使用管道和FIFO時,為在兩個方向上交換數(shù)據(jù),需要兩個IPC通道卓起。而使用消息隊列時單個隊列就夠用和敬,由每個消息的類型來標(biāo)識該消息是從客戶到服務(wù)器還是從服務(wù)器到客戶。
Posix消息隊列消息鏈表的鏈表頭中含有當(dāng)前隊列的兩個屬性:隊列中允許的最大消息數(shù)和每個消息的最大大小戏阅。
Posix消息隊列消息隊列的2個限制:一個進(jìn)程能同時擁有打開著的消息隊列的最大數(shù)目昼弟;任意消息的最大優(yōu)先級。
6奕筐、共享內(nèi)存( shared memory )
是由一個進(jìn)程創(chuàng)建舱痘,但多個進(jìn)程都可以訪問的同一塊內(nèi)存空間。是最快的可用IPC形式(因為共享內(nèi)存區(qū)中的單個數(shù)據(jù)副本對于共享該內(nèi)存的所有線程或進(jìn)程都是可用的)离赫。
是針對其他通信機(jī)制運行效率較低而設(shè)計的芭逝。往往與其它通信機(jī)制,如信號量結(jié)合使用渊胸,來達(dá)到進(jìn)程間的同
步和通信旬盯。
一般IPC形式(管道、FIFO翎猛、消息隊列)的問題在于胖翰,兩個進(jìn)程要交換信息,這些信息必須經(jīng)由內(nèi)核傳遞切厘。而進(jìn)程間共享內(nèi)存時萨咳,交換數(shù)據(jù)就不再涉及內(nèi)核。這些進(jìn)程必須協(xié)調(diào)或同步對該共享內(nèi)存區(qū)的使用疫稿。
將共享內(nèi)存區(qū)用于客戶-服務(wù)器文件復(fù)制:該共享內(nèi)存區(qū)同時存在于客戶和服務(wù)器的地址空間培他。
7、套接字( socket )
更為一般的進(jìn)程間通信機(jī)制遗座,可用于不同機(jī)器之間的進(jìn)程間通信舀凛。
8、遠(yuǎn)程過程調(diào)用:RPC
構(gòu)筑一個應(yīng)用程序時员萍,如果所有進(jìn)程都在同一臺主機(jī)腾降,那么可以使用前面的各種IPC方式;如果進(jìn)程不在同一個主機(jī)上碎绎,那就要求進(jìn)程間使用某種形式的網(wǎng)絡(luò)通信,RPC提供了這樣一種工具抗果,它屬于隱式網(wǎng)絡(luò)編程的范疇筋帖。
RPC是用于從一個系統(tǒng)(客戶主機(jī))上某個程序調(diào)用另一個系統(tǒng)上(服務(wù)器主機(jī))某個函數(shù)的一種方法。
它的調(diào)用進(jìn)程和被調(diào)用進(jìn)程可在不同主機(jī)上執(zhí)行冤馏,客戶和服務(wù)器運行在不同主機(jī)上日麸,而且過程調(diào)用中涉及網(wǎng)絡(luò)I/O,對于程序員是透明的。
另外代箭,RPC也可用于同一主機(jī)上的客戶和服務(wù)器之間墩划,因此也可認(rèn)為是另一種形式的消息傳遞。
3 進(jìn)程有哪幾種狀態(tài)嗡综?
就緒狀態(tài):進(jìn)程已獲得除處理機(jī)以外的所需資源乙帮,等待分配處理機(jī)資源
運行狀態(tài):占用處理機(jī)資源運行,處于此狀態(tài)的進(jìn)程數(shù)小于等于CPU數(shù)
阻塞狀態(tài): 進(jìn)程等待某種條件极景,在條件滿足之前無法執(zhí)行
4 多個線程之間可以共享那些數(shù)據(jù)
- 進(jìn)程代碼段
- 進(jìn)程的公有數(shù)據(jù)(利用這些共享的數(shù)據(jù)察净,線程很容易的實現(xiàn)相互之間的通訊)、
- 進(jìn)程打開的文件描述符
- 信號的處理器
- 進(jìn)程的當(dāng)前目錄
- 進(jìn)程用戶ID與進(jìn)程組ID盼樟。
5 多線程的鎖氢卡,也是多線程的同步方式
- 互斥鎖
- 自旋鎖
- 信號量
- 讀寫鎖
- 遞歸鎖
互斥鎖:
用于保護(hù)臨界區(qū),確保同一時間只有一個線程訪問數(shù)據(jù)晨缴。對共享資源的訪問译秦,先對互斥量進(jìn)行加鎖,如果互斥量已經(jīng)上鎖击碗,調(diào)用線程會阻塞筑悴,直到互斥量被解鎖。在完成了對共享資源的訪問后延都,要對互斥量進(jìn)行解鎖雷猪。
自旋鎖:
與互斥量類似,它不是通過休眠使進(jìn)程阻塞晰房,而是在獲取鎖之前一直處于循環(huán)檢測保持者是否已經(jīng)釋放了鎖(自旋)的狀態(tài)求摇。用在以下情況:鎖持有的時間短,而且線程并不希望在重新調(diào)度上花太多的成本殊者。自旋鎖與互斥鎖的區(qū)別:線程在申請自旋鎖的時候与境,線程不會被掛起,而是處于忙等的狀態(tài)猖吴。
信號量:
信號量是一個計數(shù)器摔刁,可以用來控制多個進(jìn)程對共享資源的訪問。它常作為一種鎖機(jī)制海蔽,防止某進(jìn)程正在訪問共享資源時共屈,其他進(jìn)程也訪問該資源。因此党窜,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段拗引。
讀寫鎖(rwlock):
高級別鎖,區(qū)分讀和寫幌衣,符合條件時允許多個線程訪問對象矾削。處于讀鎖操作時可以允許其他線程和本線程的讀鎖, 但不允許寫鎖, 處于寫鎖時則任何鎖操作都會睡眠等待哼凯;常見的操作系統(tǒng)會在寫鎖等待時屏蔽后續(xù)的讀鎖操作以防寫鎖被無限孤立而等待欲间,在操作系統(tǒng)不支持情況下可以用引用計數(shù)加寫優(yōu)先等待來用互斥鎖實現(xiàn)。 讀寫鎖適用于大量讀少量寫的環(huán)境断部,但由于其特殊的邏輯使得其效率相對普通的互斥鎖和自旋鎖要慢一個數(shù)量級猎贴;值得注意的一點是按POSIX標(biāo)準(zhǔn)在線程申請讀鎖并未釋放前本線程申請寫鎖是成功的,但運行后的邏輯結(jié)果是無法預(yù)測
遞歸鎖(recursivelock):
嚴(yán)格上講遞歸鎖只是互斥鎖的一個特例家坎,同樣只能有一個線程訪問該對象嘱能,但允許同一個線程在未釋放其擁有的鎖時反復(fù)對該鎖進(jìn)行加鎖操作; windows下的臨界區(qū)默認(rèn)是支持遞歸鎖的虱疏,而linux下的互斥量則需要設(shè)置參數(shù)PTHREAD_MUTEX_RECURSIVE_NP惹骂,默認(rèn)則是不支持
6 什么是死鎖?死鎖產(chǎn)生的條件做瞪?
在兩個或者多個并發(fā)進(jìn)程中对粪,如果每個進(jìn)程持有某種資源而又等待其它進(jìn)程釋放它或它們現(xiàn)在保持著的資源,在未改變這種狀態(tài)之前都不能向前推進(jìn)装蓬,稱這一組進(jìn)程產(chǎn)生了死鎖著拭。通俗的講就是兩個或多個進(jìn)程無限期的阻塞、相互等待的一種狀態(tài)牍帚。
死鎖產(chǎn)生的四個條件(有一個條件不成立儡遮,則不會產(chǎn)生死鎖)
- 互斥條件:一個資源一次只能被一個進(jìn)程使用
- 請求與保持條件:一個進(jìn)程因請求資源而阻塞時,對已獲得資源保持不放
- 不剝奪條件:進(jìn)程獲得的資源暗赶,在未完全使用完之前鄙币,不能強(qiáng)行剝奪
- 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的環(huán)形等待資源關(guān)系
7 什么是緩沖區(qū)溢出?有什么危害蹂随?其原因是什么十嘿?
緩沖區(qū)溢出是指當(dāng)計算機(jī)向緩沖區(qū)填充數(shù)據(jù)時超出了緩沖區(qū)本身的容量,溢出的數(shù)據(jù)覆蓋在合法數(shù)據(jù)上岳锁。
危害有以下兩點:
- 程序崩潰绩衷,導(dǎo)致拒絕額服務(wù)
- 跳轉(zhuǎn)并且執(zhí)行一段惡意代碼
造成緩沖區(qū)溢出的主要原因是程序中沒有仔細(xì)檢查用戶輸入。
8 分頁和分段有什么區(qū)別激率?
段是信息的邏輯單位咳燕,它是根據(jù)用戶的需要劃分的,因此段對用戶是可見的 乒躺;頁是信息的物理單位迟郎,是為了管理主存的方便而劃分的,對用戶是透明的聪蘸。
段的大小不固定,有它所完成的功能決定;頁大大小固定健爬,由系統(tǒng)決定
段向用戶提供二維地址空間控乾;頁向用戶提供的是一維地址空間
段是信息的邏輯單位,便于存儲保護(hù)和信息的共享娜遵,頁的保護(hù)和共享受到限制蜕衡。
9 虛擬內(nèi)存空間是什么,為什么要有虛擬內(nèi)存空間设拟。
虛擬地址空間:是指應(yīng)用程序自己認(rèn)為慨仿,自己所處的地址空間。它區(qū)別于物理地址空間纳胧。后者是真實存在的镰吆,比如電腦有一根8G的內(nèi)存條,物理地址空間就是0~8Gb跑慕。CPU的MMU(內(nèi)存管理單元)負(fù)責(zé)把虛擬地址轉(zhuǎn)換成物理地址万皿。
引入虛擬地址的好處:
- 程序員不再關(guān)心真實的物理內(nèi)存空間是什么樣的,理論上來說(64位CPU的虛擬內(nèi)存為2^64)核行,程序員有幾乎無限大的虛擬內(nèi)存空間可用牢硅,最后只要建立虛擬地址和物理地址的對應(yīng)關(guān)系即可。
- 操作系統(tǒng)屏蔽了物理內(nèi)存空間的細(xì)節(jié)芝雪,進(jìn)程無法訪問到操作系統(tǒng)禁止訪問的物理地址减余,也不能訪問到別的進(jìn)程的地址空間,這大大增強(qiáng)了程序安全性惩系。
- 由虛擬地址空間引申出來的分頁(Paging)技術(shù)位岔,大大提高了內(nèi)存的使用效率。要想運行一個程序蛆挫,不再需要把整個程序都放入內(nèi)存中執(zhí)行赃承,我們只要保證將要執(zhí)行的頁在內(nèi)存中即可,如果不存在則導(dǎo)致頁錯誤悴侵。
10 操作系統(tǒng)內(nèi)核態(tài)瞧剖,用戶態(tài)
- 內(nèi)核態(tài): CPU可以訪問內(nèi)存所有數(shù)據(jù), 包括外圍設(shè)備, 例如硬盤, 網(wǎng)卡. CPU也可以將自己從一個程序切換到另一個程序
- 用戶態(tài): 只能受限的訪問內(nèi)存, 且不允許訪問外圍設(shè)備. 占用CPU的能力被剝奪, CPU資源可以被其他程序獲取
為什么要有用戶態(tài)和內(nèi)核態(tài)
由于需要限制不同的程序之間的訪問能力, 防止他們獲取別的程序的內(nèi)存數(shù)據(jù), 或者獲取外圍設(shè)備的數(shù)據(jù), 并發(fā)送到網(wǎng)絡(luò), CPU劃分出兩個權(quán)限等級 -- 用戶態(tài) 和 內(nèi)核態(tài)
用戶態(tài)與內(nèi)核態(tài)的切換
所有用戶程序都是運行在用戶態(tài)的, 但是有時候程序確實需要做一些內(nèi)核態(tài)的事情, 例如從硬盤讀取數(shù)據(jù), 或者從鍵盤獲取輸入等. 而唯一可以做這些事情的就是操作系統(tǒng), 所以此時程序就需要先操作系統(tǒng)請求以程序的名義來執(zhí)行這些操作.
這時需要一個這樣的機(jī)制: 用戶態(tài)程序切換到內(nèi)核態(tài), 但是不能控制在內(nèi)核態(tài)中執(zhí)行的指令
這種機(jī)制叫系統(tǒng)調(diào)用, 在CPU中的實現(xiàn)稱之為陷阱指令(Trap Instruction)
他們的工作流程如下:
- 用戶態(tài)程序?qū)⒁恍?shù)據(jù)值放在寄存器中, 或者使用參數(shù)創(chuàng)建一個堆棧(stack frame), 以此表明需要操作系統(tǒng)提供的服務(wù).
- 用戶態(tài)程序執(zhí)行陷阱指令
- CPU切換到內(nèi)核態(tài), 并跳到位于內(nèi)存指定位置的指令, 這些指令是操作系統(tǒng)的一部分, 他們具有內(nèi)存保護(hù), 不可被用戶態(tài)程序訪問
- 這些指令稱之為陷阱(trap)或者系統(tǒng)調(diào)用處理器(system call handler). 他們會讀取程序放入內(nèi)存的數(shù)據(jù)參數(shù), 并執(zhí)行程序請求的服務(wù)
- 系統(tǒng)調(diào)用完成后, 操作系統(tǒng)會重置CPU為用戶態(tài)并返回系統(tǒng)調(diào)用的結(jié)果
11 棧和堆
棧: 由系統(tǒng)自動分配的內(nèi)存區(qū)域, 由系統(tǒng)自動釋放可免。例如抓于,在函數(shù)中聲明一個局部變量 int b; 系統(tǒng)自動在棧中為b開辟空間
堆: 需要程序員自己申請的內(nèi)存區(qū)域,并指明大小浇借,并且需要主動進(jìn)行釋放捉撮。 例如: 在c中malloc函數(shù),如p1 = (char*)malloc(10);在C++中用new運算符如p2 = new char[10];
參考文章
http://www.reibang.com/p/b2ff3117faf1
https://zhuanlan.zhihu.com/p/23755202
https://www.cnblogs.com/z-sm/p/6254103.html