1)????? Linux中主要有哪幾種內(nèi)核鎖赫舒?
說(shuō)明:在多核處理器下羊娃,會(huì)存在多個(gè)進(jìn)程處于內(nèi)核態(tài)的情況唐全,在內(nèi)核態(tài)下,進(jìn)程是可以訪問所有的內(nèi)核數(shù)據(jù)蕊玷,因此需要對(duì)共享數(shù)據(jù)做保護(hù)邮利,即互 ? ? ? ? ? ? ? 斥處理。
原子性:一個(gè)操作是不可中斷的垃帅,即使在多個(gè)線程一起執(zhí)行的時(shí)候延届,一個(gè)操作一旦開始,就不會(huì)被其它線程所干擾贸诚。
?Linux的內(nèi)核鎖主要是自旋鎖和信號(hào)量方庭。
自旋鎖最多只能被一個(gè)可執(zhí)行線程持有厕吉,如果一個(gè)執(zhí)行線程試圖請(qǐng)求一個(gè)已被爭(zhēng)用(已經(jīng)被持有)的自旋鎖,那么這個(gè)線程就會(huì)一直進(jìn)行忙循環(huán)——旋轉(zhuǎn)——等待鎖重新可用械念。要是鎖未被爭(zhēng)用头朱,請(qǐng)求它的執(zhí)行線程便能立刻得到它并且繼續(xù)進(jìn)行。自旋鎖可以在任何時(shí)刻防止多于一個(gè)的執(zhí)行線程同時(shí)進(jìn)入臨界區(qū)龄减。
Linux中的信號(hào)量是一種睡眠鎖项钮。如果有一個(gè)任務(wù)試圖獲得一個(gè)已被持有的信號(hào)量時(shí),信號(hào)量會(huì)將其推入等待隊(duì)列希停,然后讓其睡眠寄纵。這時(shí)處理器獲得自由去執(zhí)行其它代碼。當(dāng)持有信號(hào)量的進(jìn)程將信號(hào)量釋放后脖苏,在等待隊(duì)列中的一個(gè)任務(wù)將被喚醒程拭,從而便可以獲得這個(gè)信號(hào)量。
信號(hào)量的睡眠特性棍潘,使得信號(hào)量適用于鎖會(huì)被長(zhǎng)時(shí)間持有的情況恃鞋;只能在進(jìn)程上下文中使用,因?yàn)橹袛嗌舷挛闹惺遣荒鼙徽{(diào)度的亦歉;另外當(dāng)代碼持有信號(hào)量時(shí)恤浪,不可以再持有自旋鎖。
2)????? Linux中的用戶模式和內(nèi)核模式是什么含意肴楷?
內(nèi)核態(tài):進(jìn)程陷入內(nèi)核代碼中執(zhí)行水由,在內(nèi)核態(tài)將會(huì)使用內(nèi)核棧,每個(gè)進(jìn)程都有自己的內(nèi)核棧赛蔫。
用戶態(tài):進(jìn)程在執(zhí)行自身的應(yīng)用代碼砂客。當(dāng)正在執(zhí)行用戶程序而突然被中斷程序中斷時(shí),此時(shí)用戶程序也可以象征性地稱為處于進(jìn)程的內(nèi)核態(tài)呵恢。因?yàn)橹袛嗵幚沓绦驅(qū)⑹褂卯?dāng)前進(jìn)程的內(nèi)核棧鞠值。這與處于內(nèi)核態(tài)的進(jìn)程的狀態(tài)有些類似。
當(dāng)用戶程序調(diào)用系統(tǒng)的API時(shí)渗钉,會(huì)產(chǎn)生中斷彤恶,進(jìn)入內(nèi)核態(tài)的API,處理完成后鳄橘,用中斷再退出声离,返回用戶態(tài)的調(diào)用函數(shù):
user??? api??? -->??? interrupt??? -->??? kernel??? api??? -->??? interrupt
雖然用戶態(tài)下和內(nèi)核態(tài)下工作的程序有很多差別,但最重要的差別就在于特權(quán)級(jí)的不同瘫怜,即權(quán)力的不同术徊。
用戶態(tài)切到內(nèi)核態(tài)的三種方式:
——>:系統(tǒng)調(diào)用:而系統(tǒng)調(diào)用的機(jī)制其核心還是使用了操作系統(tǒng)為用戶特別開放的一個(gè)中斷來(lái)實(shí)現(xiàn)。
——>:異常:當(dāng)出現(xiàn)事先不可知的異常宝磨,會(huì)切到異常內(nèi)核程序弧关,比如缺頁(yè)異常盅安。
——>:外圍設(shè)備的中斷:由用戶態(tài)切到內(nèi)核態(tài)去執(zhí)行中斷程序。
內(nèi)核模式的代碼可以無(wú)限制地訪問所有處理器指令集以及全部?jī)?nèi)存和I/O空間世囊。如果用戶模式的進(jìn)程要享有此特權(quán)别瞭,它必須通過(guò)系統(tǒng)調(diào)用向設(shè)備驅(qū)動(dòng)程序或其他內(nèi)核模式的代碼發(fā)出請(qǐng)求。另外株憾,用戶模式的代碼允許發(fā)生缺頁(yè)蝙寨,而內(nèi)核模式的代碼則不允許。
3)????? 怎樣申請(qǐng)大塊內(nèi)核內(nèi)存嗤瞎?
?? ?在Linux內(nèi)核環(huán)境下墙歪,申請(qǐng)大塊內(nèi)存的成功率隨著系統(tǒng)運(yùn)行時(shí)間的增加而減少,雖然可以通過(guò)vmalloc系列調(diào)用申請(qǐng)物理不連續(xù)但虛擬地址連續(xù)的內(nèi)存贝奇,但畢竟其使用效率不高且在32位系統(tǒng)上vmalloc的內(nèi)存地址空間有限虹菲。所以,一般的建議是在系統(tǒng)啟動(dòng)階段申請(qǐng)大塊內(nèi)存掉瞳,但是其成功的概率也只是比較高而已毕源,而不是100%。如果程序真的比較在意這個(gè)申請(qǐng)的成功與否陕习,只能退用“啟動(dòng)內(nèi)存”(Boot Memory)
4)????? 用戶進(jìn)程間通信主要哪幾種方式霎褐?
?? ?(1)管道(Pipe):管道可用于具有親緣關(guān)系進(jìn)程間的通信,允許一個(gè)進(jìn)程和另一個(gè)與它有共同祖先的進(jìn)程之間進(jìn)行通信该镣。
?? ?(2)命名管道(named pipe):命名管道克服了管道沒有名字的限制冻璃,因此,除具有管道所具有的功能外损合,它還允許無(wú)親緣關(guān)系進(jìn)程間的通信省艳。命名管道在文件系統(tǒng)中有對(duì)應(yīng)的文件名。命名管道通過(guò)命令mkfifo或系統(tǒng)調(diào)用mkfifo來(lái)創(chuàng)建塌忽。
?? ?(3)信號(hào)(Signal):信號(hào)是比較復(fù)雜的通信方式拍埠,用于通知接受進(jìn)程有某種事件發(fā)生,除了用于進(jìn)程間通信外土居,進(jìn)程還可以發(fā)送信號(hào)給進(jìn)程本身;linux除了支持Unix早期信號(hào)語(yǔ)義函數(shù)sigal外嬉探,還支持語(yǔ)義符合Posix.1標(biāo)準(zhǔn)的信號(hào)函數(shù)sigaction(實(shí)際上擦耀,該函數(shù)是基于BSD的,BSD為了實(shí)現(xiàn)可靠信號(hào)機(jī)制涩堤,又能夠統(tǒng)一對(duì)外接口眷蜓,用sigaction函數(shù)重新實(shí)現(xiàn)了signal函數(shù))。
?? ?(4)消息(Message)隊(duì)列:消息隊(duì)列是消息的鏈接表胎围,包括Posix消息隊(duì)列system V消息隊(duì)列吁系。有足夠權(quán)限的進(jìn)程可以向隊(duì)列中添加消息德召,被賦予讀權(quán)限的進(jìn)程則可以讀走隊(duì)列中的消息。消息隊(duì)列克服了信號(hào)承載信息量少汽纤,管道只能承載無(wú)格式字節(jié)流以及緩沖區(qū)大小受限等缺
?? ?(5)共享內(nèi)存:使得多個(gè)進(jìn)程可以訪問同一塊內(nèi)存空間上岗,是最快的可用IPC形式。是針對(duì)其他通信機(jī)制運(yùn)行效率較低而設(shè)計(jì)的蕴坪。往往與其它通信機(jī)制肴掷,如信號(hào)量結(jié)合使用,來(lái)達(dá)到進(jìn)程間的同步及互斥背传。
?? ?(6)信號(hào)量(semaphore):主要作為進(jìn)程間以及同一進(jìn)程不同線程之間的同步手段呆瞻。
?? ?(7)套接字(Socket):更為一般的進(jìn)程間通信機(jī)制,可用于不同機(jī)器之間的進(jìn)程間通信径玖。起初是由Unix系統(tǒng)的BSD分支開發(fā)出來(lái)的痴脾,但現(xiàn)在一般可以移植到其它類Unix系統(tǒng)上:Linux和System V的變種都支持套接字。
5)????? 通過(guò)伙伴系統(tǒng)申請(qǐng)內(nèi)核內(nèi)存的函數(shù)有哪些梳星?
在物理頁(yè)面管理上實(shí)現(xiàn)了基于區(qū)的伙伴系統(tǒng)(zone based buddy system)赞赖。對(duì)不同區(qū)的內(nèi)存使用單獨(dú)的伙伴系統(tǒng)(buddy system)管理,而且獨(dú)立地監(jiān)控空閑頁(yè)。相應(yīng)接口alloc_pages(gfp_mask, order)丰泊,_ _get_free_pages(gfp_mask, order)等薯定。
6)????? 通過(guò)slab分配器申請(qǐng)內(nèi)核內(nèi)存的函數(shù)有?
kmalloc 和 kfree瞳购。
引申:
slab:linux下的內(nèi)存分配機(jī)制话侄,針對(duì)一些經(jīng)常分配并釋放的對(duì)象,如進(jìn)程描述符学赛,對(duì)象大小一般比較小年堆。
優(yōu)點(diǎn):
1、內(nèi)核通常依賴于對(duì)小對(duì)象的分配盏浇,它們會(huì)在系統(tǒng)生命周期內(nèi)進(jìn)行無(wú)數(shù)次分配变丧。
2、slab 緩存分配器通過(guò)對(duì)類似大小的對(duì)象進(jìn)行緩存而提供這種功能绢掰,從而避免了常見的碎片問題痒蓬。
3、slab 分配器還支持通用對(duì)象的初始化滴劲,從而避免了為同一目的而對(duì)一個(gè)對(duì)象重復(fù)進(jìn)行初始化攻晒。
4、slab 分配器還可以支持硬件緩存對(duì)齊和著色班挖,這允許不同緩存中的對(duì)象占用相同的緩存行鲁捏,從而提高緩存的利用率并獲得更好的性能。
伙伴系統(tǒng):(buddy system)需要談一談linux的內(nèi)存分配系統(tǒng)
linux內(nèi)核采取了一種同時(shí)適用于32位和64位系統(tǒng)的內(nèi)存分頁(yè)模型萧芙,對(duì)于32位系統(tǒng)给梅,兩級(jí)頁(yè)表足夠用假丧,而64位系統(tǒng),需要四級(jí)頁(yè)表动羽。分別為:
頁(yè)全局目錄:包含一些頁(yè)上級(jí)目錄地址
頁(yè)上級(jí)目錄:包含頁(yè)中間目錄地址
頁(yè)中間目錄:包含一些頁(yè)表地址
頁(yè)表:????????????指向頁(yè)框包帚,linux中采用4kb大小的頁(yè)框作為標(biāo)準(zhǔn)的內(nèi)存分配單元。
在實(shí)際應(yīng)用中曹质,經(jīng)常需要分配一組連續(xù)的頁(yè)框婴噩,而頻繁地申請(qǐng)和釋放不同大小的連續(xù)頁(yè)框,必然導(dǎo)致在已分配頁(yè)框的內(nèi)存塊中分散了許多小塊的空閑頁(yè)框羽德。這樣几莽,即使這些頁(yè)框是空閑的,其他需要分配連續(xù)頁(yè)框的應(yīng)用也很難得到滿足宅静。
為了避免出現(xiàn)這種情況章蚣,Linux內(nèi)核中引入了伙伴系統(tǒng)算法(buddy system)。把所有的空閑頁(yè)框分組為11個(gè)塊鏈表姨夹,每個(gè)塊鏈表分別包含大小為1纤垂,2,4磷账,8峭沦,16,32逃糟,64吼鱼,128,256绰咽,512和1024個(gè)連續(xù)頁(yè)框的頁(yè)框塊菇肃。最大可以申請(qǐng)1024個(gè)連續(xù)頁(yè)框,對(duì)應(yīng)4MB大小的連續(xù)內(nèi)存取募。每個(gè)頁(yè)框塊的第一個(gè)頁(yè)框的物理地址是該塊大小的整數(shù)倍琐谤。
假設(shè)要申請(qǐng)一個(gè)256個(gè)頁(yè)框的塊,先從256個(gè)頁(yè)框的鏈表中查找空閑塊玩敏,如果沒有斗忌,就去512個(gè)頁(yè)框的鏈表中找,找到了則將頁(yè)框塊分為2個(gè)256個(gè)頁(yè)框的塊旺聚,一個(gè)分配給應(yīng)用飞蹂,另外一個(gè)移到256個(gè)頁(yè)框的鏈表中。如果512個(gè)頁(yè)框的鏈表中仍沒有空閑塊翻屈,繼續(xù)向1024個(gè)頁(yè)框的鏈表查找,如果仍然沒有妻坝,則返回錯(cuò)誤伸眶。
頁(yè)框塊在釋放時(shí)惊窖,會(huì)主動(dòng)將兩個(gè)連續(xù)的頁(yè)框塊合并為一個(gè)較大的頁(yè)框塊。
7)????? Linux的內(nèi)核空間和用戶空間是如何劃分的(以32位系統(tǒng)為例)厘贼?
? ? ??Linux將4G的地址劃分為用戶空間和內(nèi)核空間兩部分界酒。在Linux內(nèi)核的低版本中(2.0.X),通常0-3G為用戶空間嘴秸,3G-4G為內(nèi)核空間毁欣。這個(gè)分界點(diǎn)是可以改動(dòng)的。?正是這個(gè)分界點(diǎn)的存在岳掐,限制了Linux可用的最大內(nèi)存為2G.而且要通過(guò)重編內(nèi)核凭疮,調(diào)整這個(gè)分界點(diǎn)才能達(dá)到。實(shí)際上還可以有更好的方法來(lái)解決這個(gè)問題串述。由于內(nèi)核空間與用戶空間互不重合执解,所以可以用段機(jī)制提供的保護(hù)功能來(lái)保護(hù)內(nèi)核級(jí)代碼。2.2.X版的內(nèi)核對(duì)此進(jìn)行了改動(dòng)纲酗。這樣內(nèi)核空間擴(kuò)張到了4G衰腌。從表面上看內(nèi)核的基地址變?yōu)榱?,但實(shí)際上觅赊,內(nèi)核通常仍在虛址3G以上右蕊。?用戶空間在2.2.X中從直觀上變?yōu)?-4G,讓人迷惑吮螺,不是可以直接訪問內(nèi)核了饶囚??其實(shí)不然,同過(guò)使用頁(yè)機(jī)制提供的保護(hù)规脸,阻止了用戶程序訪問內(nèi)核空間坯约。
8)????? vmalloc()申請(qǐng)的內(nèi)存有什么特點(diǎn)?
原型為:void *vmalloc(unsigned long size)莫鸭。size要分配內(nèi)存的大小. 以字節(jié)為單位闹丐。在設(shè)備驅(qū)動(dòng)程序或者內(nèi)核模塊中動(dòng)態(tài)開辟內(nèi)存,不是用malloc被因,而是kmalloc ,vmalloc卿拴,或者用get_free_pages直接申請(qǐng)頁(yè)。釋放內(nèi)存用的是kfree,vfree梨与,或free_pages.?
kmalloc函數(shù)返回的是虛擬地址(線性地址). kmalloc特殊之處在于它分配的內(nèi)存是物理上連續(xù)的,這對(duì)于要進(jìn)行DMA的設(shè)備十分重要. 而用vmalloc分配的內(nèi)存只是線性地址連續(xù),物理地址不一定連續(xù),不能直接用于DMA堕花。vmalloc函數(shù)的工作方式類似于kmalloc,只不過(guò)前者分配的內(nèi)存虛擬地址是連續(xù)的粥鞋,而物理地址則無(wú)需連續(xù)缘挽。它通過(guò)分配非連續(xù)的物理內(nèi)存塊,再修改頁(yè)表,把內(nèi)存映射到邏輯地址空間的連續(xù)區(qū)域中壕曼。通過(guò)vmalloc獲得的頁(yè)必須一個(gè)一個(gè)地進(jìn)行映射苏研,效率不高,因此腮郊,只在不得已(一般是為了獲得大塊內(nèi)存)時(shí)使用摹蘑。vmalloc函數(shù)返回一個(gè)指針,指向邏輯上連續(xù)的一塊內(nèi)存區(qū)轧飞,其大小至少為size衅鹿。在發(fā)生錯(cuò)誤時(shí),函數(shù)返回NULL过咬。vmalloc可能睡眠大渤,因此,不能從中斷上下文中進(jìn)行調(diào)用援奢,也不能從其它不允許阻塞的情況下調(diào)用兼犯。要釋放通過(guò)vmalloc所獲得的內(nèi)存,應(yīng)使用vfree函數(shù)集漾。
Kmalloc 是連續(xù)的物理內(nèi)存切黔。?
Vmalloc 是非連續(xù)的。
vmalloc是一頁(yè)一頁(yè)地去獲取內(nèi)存具篇,然后把獲取到的這些頁(yè)映射成連續(xù)的虛擬地址纬霞;
kmalloc是一次性獲取所需要的所有頁(yè),并且不需要再做映射驱显;
vmalloc 是否效率遠(yuǎn)不如 kmalloc
9)????? 用戶程序使用malloc()申請(qǐng)到的內(nèi)存空間在什么范圍诗芜?
?0~0xBFFFFFFF
簡(jiǎn)單的說(shuō)就是:內(nèi)存是分散成一些小塊的,malloc管理的內(nèi)存是通過(guò)鏈表的方式把這些塊串在一起埃疫,以這些內(nèi)存的起始地址排序組織的伏恐,相鄰的內(nèi)存塊如果尾首地址連續(xù),那就把它們合并為一塊栓霜,當(dāng)你申請(qǐng)一定大小的內(nèi)存時(shí)以first fit模式,在內(nèi)存鏈中找第一個(gè)大于你需要大小的內(nèi)存翠桦,返回內(nèi)存指針以best fit模式,要遍歷整個(gè)內(nèi)存鏈胳蛮,找剛好最接近但大于所需要大小的內(nèi)存當(dāng)然這是出于對(duì)內(nèi)存不浪費(fèi)的考慮销凑,效率是有損失.釋放的話相反,把內(nèi)存放回內(nèi)存管理鏈中仅炊,可能的話合并相鄰的內(nèi)存碎片斗幼。避免內(nèi)存過(guò)于零散Linux下malloc函數(shù)主要用來(lái)在用戶空間從heap申請(qǐng)內(nèi)存,申請(qǐng)成功返回指向所分配內(nèi)存的指針抚垄,申請(qǐng)失敗返回NULL谋逻。默認(rèn)情況下渠羞,Linux內(nèi)核使用“樂觀的”分配內(nèi)存策略,首先粗略估計(jì)系統(tǒng)可使用的內(nèi)存數(shù)次询,然后分配內(nèi)存屯吊,但是在使用的時(shí)候才真正把這塊分配的內(nèi)存給你。這樣一來(lái)盒卸,即使用malloc申請(qǐng)內(nèi)存沒有返回NULL次氨,你也不一定能完全使用這塊內(nèi)存,特別是在一次或連續(xù)多次申請(qǐng)很多內(nèi)存的時(shí)候虹蓄。如果一直連續(xù)用malloc申請(qǐng)內(nèi)存,而不真正使用幸撕,所申請(qǐng)的內(nèi)存總數(shù)可以超過(guò)真正可以使用的內(nèi)存數(shù)薇组。但是當(dāng)真正使用這塊內(nèi)存,比如用memset或bzero函數(shù)一次性把所申請(qǐng)到的大塊內(nèi)存“使用掉”坐儿,Linux系統(tǒng)就會(huì)Out Of Memory律胀,這個(gè)時(shí)候OOM Killer就會(huì)kill掉用戶空間的其他進(jìn)程來(lái)騰出更多可使用內(nèi)存。OOM Killer根據(jù)OOM score來(lái)決定kill哪個(gè)進(jìn)程貌矿,OOM score可以看/proc/<PID>/oom_score炭菌,score由badness函數(shù)計(jì)算得出,根據(jù)進(jìn)程運(yùn)行時(shí)間長(zhǎng)短逛漫,進(jìn)程優(yōu)先級(jí)黑低,進(jìn)程所使用的內(nèi)存數(shù)等等【⌒ǎ可以通過(guò)/proc/<PID>/oom_adj來(lái)干預(yù)計(jì)算socre投储,這個(gè)值的取值范圍是-17~15,如果是-17該進(jìn)程就永遠(yuǎn)不會(huì)被kill(這個(gè)可能也和內(nèi)核版本有關(guān)阔馋,不見得所有內(nèi)核版本都支持牙捉,得實(shí)際試試)≡“默認(rèn)情況”Linux是這種做的浪箭,“默認(rèn)情況”是指/proc/sys/vm/overcommit_memory為0的時(shí)候。這個(gè)參數(shù)也可以調(diào)整,如果為1表示“來(lái)著不拒”客蹋,只要你malloc過(guò)來(lái)申請(qǐng)塞蹭,我啥都不做,立馬給你分配內(nèi)存讶坯,這樣的話性能就會(huì)有大幅度的提高番电;如果為2表示Linux會(huì)精確計(jì)算所有可使用的內(nèi)存和所申請(qǐng)的內(nèi)存辆琅,如果所申請(qǐng)的超過(guò)的可使用的內(nèi)存數(shù)就返回NULL婉烟∷圃可使用的內(nèi)存值計(jì)算方法昙衅,虛擬內(nèi)存(swap)+ /proc/sys/vm/overcommit_memory(百分比) × 物理內(nèi)存畜挥。/proc/sys/vm/overcommit_memory默認(rèn)值為50,計(jì)算起來(lái)就是50%的物理內(nèi)存數(shù)蟹但。Linux自身內(nèi)核會(huì)占一部分內(nèi)存华糖,還有buffer/cache所占用的內(nèi)存客叉,所以實(shí)際上能被malloc申請(qǐng)后使用的內(nèi)存并非物理內(nèi)存大小兼搏,demsg的輸出里面包含了相關(guān)信息(如果看不到佛呻,可能是被別的信息沖掉了吓著,重啟系統(tǒng),在系統(tǒng)起來(lái)后馬上看):
Memory: 2071220k/2097152k available (2122k kernel code, 24584k reserved, 884k data, 228k init, 1179584k highmem)
10)? 在支持并使能MMU的系統(tǒng)中暖眼,Linux內(nèi)核和用戶程序分別運(yùn)行在物理地址模式還是虛擬地址模式诫肠?
虛擬地址模式
在ARM存儲(chǔ)系統(tǒng)中,使用內(nèi)存管理單元(MMU)實(shí)現(xiàn)虛擬地址到實(shí)際物理地址的映射浪南。利用MMU络凿,可把SDRAM的地址完全映射到0x0起始的一片連續(xù)地址空間,而把原來(lái)占據(jù)這片空間的FLASH或者ROM映射到其他不相沖突的存儲(chǔ)空間位置虐先。例如蛹批,F(xiàn)LASH的地址從0x0000 0000~0x00ff ffff差导,而SDRAM的地址范圍是0x3000 0000~Ox3lff ffff设褐,則可把SDRAM地址映射為0x0000 0000~Oxlfff ffff而FLASH的地址可以映射到Ox9000 0000~Ox90ff ffff(此處地址空間為空閑助析,未被占用)外冀。映射完成后锥惋,如果處理器發(fā)生異常,假設(shè)依然為IRQ中斷遭商,PC指針指向Oxl8處的地址劫流,而這個(gè)時(shí)候PC實(shí)際上是從位于物理地址的Ox3000 0018處讀取指令祠汇。通過(guò)MMU的映射可很,則可實(shí)現(xiàn)程序完全運(yùn)行在SDRAM之中。在實(shí)際的應(yīng)用中.可能會(huì)把兩片不連續(xù)的物理地址空間分配給SDRAM袜茧。而在操作系統(tǒng)中纳鼎,習(xí)慣于把SDRAM的空間連續(xù)起來(lái)贱鄙,方便內(nèi)存管理贰逾,且應(yīng)用程序申請(qǐng)大塊的內(nèi)存時(shí)疙剑,操作系統(tǒng)內(nèi)核也可方便地分配言缤。通過(guò)MMU可實(shí)現(xiàn)不連續(xù)的物理地址空間映射為連續(xù)的虛擬地址空間管挟。操作系統(tǒng)內(nèi)核或者一些比較關(guān)鍵的代碼僻孝,一般是不希望被用戶應(yīng)用程序訪問穿铆。通過(guò)MMU可以控制地址空間的訪問權(quán)限荞雏,從而保護(hù)這些代碼不被破壞凤优。
MMU的實(shí)現(xiàn)過(guò)程筑辨,實(shí)際上就是一個(gè)查表映射的過(guò)程棍辕。建立頁(yè)表(translate table)是實(shí)現(xiàn)MMU功能不可缺少的一步。頁(yè)表是位于系統(tǒng)的內(nèi)存中蚕甥,頁(yè)表的每一項(xiàng)對(duì)應(yīng)于一個(gè)虛擬地址到物理地址的映射菇怀。每一項(xiàng)的長(zhǎng)度即是一個(gè)字的長(zhǎng)度(在ARM中帅霜,一個(gè)字的長(zhǎng)度被定義為4B)身冀。頁(yè)表項(xiàng)除完成虛擬地址到物理地址的映射功能之外搂根,還定義了訪問權(quán)限和緩沖特性等剩愧。
MMU的映射分為兩種仁卷,一級(jí)頁(yè)表的變換和二級(jí)頁(yè)表變換锦积。兩者的不同之處就是實(shí)現(xiàn)的變換地址空間大小不同充包。一級(jí)頁(yè)表變換支持1 M大小的存儲(chǔ)空間的映射基矮,而二級(jí)可以支持64 kB家浇,4 kB和1 kB大小地址空間的映射
11).ARM處理器是通過(guò)幾級(jí)頁(yè)表進(jìn)行存儲(chǔ)空間映射的钢悲?
虛擬存儲(chǔ)空間到物理存儲(chǔ)空間的映射是以內(nèi)存塊為單位進(jìn)行的还棱,虛擬存儲(chǔ)空間中的一塊連續(xù)存儲(chǔ)空間被映射成物理存儲(chǔ)空間中同樣大小的一塊連續(xù)存儲(chǔ)空間珍手。每一個(gè)地址變換條目(頁(yè)表項(xiàng))記錄了一個(gè)虛擬存儲(chǔ)空間的存儲(chǔ)塊的基地址與物理存儲(chǔ)空間相應(yīng)的一個(gè)存儲(chǔ)塊的基地址的對(duì)應(yīng)關(guān)系琳要。根據(jù)存儲(chǔ)塊大小不同稚补,可以有多種地址變換课幕。
ARM處理器支持的存儲(chǔ)塊大小有以下幾種:
1)段(section):大小為1MB的存儲(chǔ)塊撰豺。
2)大頁(yè)(Large Page):大小為64KB的存儲(chǔ)塊污桦。
3)小頁(yè)(Small Page):大小為4KB的存儲(chǔ)塊凡橱。
4)極小頁(yè)(Tiny Page):大小為1KB的存儲(chǔ)塊顾稀。
通過(guò)采用適當(dāng)?shù)脑L問控制機(jī)制静秆,還可以將大頁(yè)分成大小為16KB的子頁(yè)抚笔,也可將小頁(yè)分成大小為1KB的子頁(yè)殊橙,但極小頁(yè)不能再細(xì)分膨蛮,只能以1KB大小的整頁(yè)為單位敞葛。
ARM處理器采用兩級(jí)頁(yè)表實(shí)現(xiàn)地址映射:
1)一級(jí)頁(yè)表中包含以段為單位的地址變換條目或者指向二級(jí)頁(yè)表的指針制肮,一級(jí)頁(yè)表實(shí)現(xiàn)的地址映射粒度較大。
2)二級(jí)頁(yè)表中包含以大頁(yè)款慨、小頁(yè)和極小頁(yè)為單位的地址變換條目檩奠。
當(dāng)以二級(jí)分頁(yè)管理某段存儲(chǔ)空間時(shí)埠戳,要同時(shí)設(shè)置一級(jí)頁(yè)表項(xiàng)和二級(jí)頁(yè)表項(xiàng),一個(gè)一級(jí)頁(yè)表項(xiàng)對(duì)應(yīng)一段(1section=1MB)虛擬存儲(chǔ)空間的映射關(guān)系喳钟,一個(gè)一級(jí)頁(yè)表項(xiàng)對(duì)應(yīng)一張二級(jí)頁(yè)表,這張二級(jí)頁(yè)表中的所有頁(yè)表項(xiàng)合在一起對(duì)應(yīng)了前面一級(jí)頁(yè)表項(xiàng)所對(duì)應(yīng)的一段虛擬存儲(chǔ)空間的映射關(guān)系蔽午。ARM處理器的二級(jí)頁(yè)表分為粗粒度二級(jí)頁(yè)表和細(xì)粒度二級(jí)頁(yè)表及老,一張粗粒度二級(jí)頁(yè)表的最大容量為1KB骄恶,一張細(xì)粒度二級(jí)頁(yè)表的最大容量為4KB叠蝇,不管是粗粒度還是細(xì)粒度頁(yè)表悔捶,每張頁(yè)表都對(duì)應(yīng)一段(1M)虛擬存儲(chǔ)空間的映射關(guān)系蜕该。所以粗粒度二級(jí)頁(yè)表的頁(yè)表項(xiàng)(頁(yè)描述符)最小只能描述4KB大小(小頁(yè))虛擬存儲(chǔ)空間的映射關(guān)系扒腕,如果再小就沒有足夠的頁(yè)表空間來(lái)存放一段虛擬存儲(chǔ)空間的全部頁(yè)表項(xiàng)(因?yàn)榇至6榷?jí)頁(yè)表的最大容量為1KB)皆的,因?yàn)榇至6榷?jí)頁(yè)表容量最大容量為1K费薄,一個(gè)頁(yè)表項(xiàng)為4個(gè)字節(jié)楞抡,所以1K容量最多有1024/4=256個(gè)頁(yè)表項(xiàng)召廷,所以最小只能描述1M/256=4K大惺酢(小頁(yè))虛擬空間的存儲(chǔ)映射關(guān)系泡孩,而細(xì)粒度二級(jí)頁(yè)表的頁(yè)描述符最小可以描述1KB大新嘏浮(極小頁(yè))的虛擬存儲(chǔ)空間的映射關(guān)系眼俊。
綜上所述疮胖,我們可以歸納出以下6種ARM處理器的地址變換方法:
1)分段地址變換澎灸,這種變換只需要一級(jí)地址變換性昭,而下面5種都需要兩級(jí)地址變換糜颠;
2)粗粒度大頁(yè)(64K)地址變換其兴;
3)粗粒度小頁(yè)(4K)地址變換(Linux通常使用的地址變換方法)忌警;
4)細(xì)粒度大頁(yè)(64K)地址變換箕速;
5)細(xì)粒度小頁(yè)(4K)地址變換盐茎;
6)細(xì)粒度極小頁(yè)(1K)地址變換。
在講解以上各種地址變換方法之前我們先介紹一下一級(jí)映射描述符和二級(jí)映射描述符的定義狡赐。
12)? Linux是通過(guò)什么組件來(lái)實(shí)現(xiàn)支持多種文件系通的枕屉?
VFS
13)? Linux虛擬文件系統(tǒng)的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)有哪些搀擂?(至少寫出四個(gè))
VFS超級(jí)塊:struct super_block
VFS的i節(jié)點(diǎn):struct inode
i節(jié)點(diǎn)的操作函數(shù):struct inode_operations
VFS的dentry結(jié)構(gòu):struct dentry
14)? 對(duì)文件或設(shè)備的操作函數(shù)保存在那個(gè)數(shù)據(jù)結(jié)構(gòu)中?
file_operations
file_operations結(jié)構(gòu)體威恼,用來(lái)存儲(chǔ)驅(qū)動(dòng)內(nèi)核模塊提供的對(duì)設(shè)備進(jìn)行各種操作的函數(shù)的指針箫措。
常用的操作包括:read蒂破、write附迷、poll喇伯、ioctl稻据、mmap捻悯、open今缚、close姓言、flush何荚、llseek等方法餐塘。
file 每個(gè)打開的文件在內(nèi)核空間都有一個(gè)對(duì)應(yīng)的file結(jié)構(gòu)
file結(jié)構(gòu)體唠倦,打開的文件描述
通用的描述有冈止,f_mode(讀寫屬性)熙暴、f_ops(當(dāng)前文件位移)慌盯、f_rdev(設(shè)備)亚皂、f_flags(文件標(biāo)志)灭必、f_count(打開文件的數(shù)目)禁漓、f_reada播歼、f_inode(指向inode的結(jié)構(gòu)指針)秘狞、file_operations?
inode
inode 索引節(jié)點(diǎn)雇初,和存儲(chǔ)有關(guān)廓潜。?
inode內(nèi)容:
除了文件名以外的所有文件信息呻畸,都存在inode之中伤为。
* 文件的字節(jié)數(shù)* 文件擁有者的User ID
* 文件的Group ID
* 文件的讀绞愚、寫位衩、執(zhí)行權(quán)限
* 文件的時(shí)間戳糖驴,共有三個(gè):ctime指inode上一次變動(dòng)的時(shí)間贮缕,mtime指文件內(nèi)容上一次變動(dòng)的時(shí)間感昼,atime指文件上一次打開的時(shí)間定嗓。
* 鏈接數(shù)蜕乡,即有多少文件名指向這個(gè)inode
* 文件數(shù)據(jù)block的位置
可以用stat命令层玲,查看某個(gè)文件的inode信息:stat???? xxx.txt
struct ? file ?結(jié)構(gòu)體中包含有struct ? file_operations結(jié)構(gòu)體辛块,struct ? file_operations是struct file的一個(gè)域;我們?cè)谑褂孟到y(tǒng)調(diào)用open()打開一個(gè)設(shè)備節(jié)點(diǎn)struct inode時(shí)尘盼,我們會(huì)得到一個(gè)文件struct ?file,同時(shí)返回一個(gè)文件描述符,該文件描述符是一個(gè)整數(shù)配紫,我們稱之為句柄躺孝,通過(guò)訪問句柄我們能夠訪問設(shè)備文件struct file底桂,描述符是一個(gè)有著特殊含義的整數(shù)于个,特定位都有一定的意義或?qū)傩浴?/p>
文件描述符就是句柄览濒,是一個(gè)整數(shù)贷笛,通過(guò)句柄來(lái)訪問設(shè)備文件 file乏苦。文件file里有相關(guān)的文件屬性汇荐,并且包含相關(guān)的文件操作掀淘。
15)? Linux中的文件包括哪些?
?? ?普通文件 : 通常是流式文件
?? ?目錄文件 : 用于表示和管理系統(tǒng)中的全部文件
?? ?連接文件 : 用于不同目錄下文件的共享
?? ?設(shè)備文件 : 包括塊設(shè)備文件和字符設(shè)備文件拦惋,塊設(shè)備文件表示磁盤文件厕妖、光盤等言秸,字符設(shè)備文件按照字符操作終端埋嵌、鍵盤等設(shè)備。
?? ?管道(FIFO)文件 :? 提供進(jìn)程建通信的一種方式
?? ?套接字(socket) 文件: 該文件類型與網(wǎng)絡(luò)通信有關(guān)
16)? 創(chuàng)建進(jìn)程的系統(tǒng)調(diào)用有那些合是?
fork();創(chuàng)建子進(jìn)程聪全,其實(shí)是復(fù)制了父進(jìn)程难礼,但是父進(jìn)程的程序代碼和全局變量沒有被復(fù)制蛾茉。
父進(jìn)程調(diào)用fork會(huì)返回子進(jìn)程的ID號(hào)谦炬,調(diào)用失敗返回-1键思,子進(jìn)程調(diào)用返回0。
execve()赔桌;子進(jìn)程調(diào)用execve(),是為了運(yùn)行另一個(gè)屬于自己的程序裸卫。
exit()墓贿;進(jìn)程調(diào)用exit()就會(huì)立即退出,系統(tǒng)的跟進(jìn)程會(huì)接替被中止進(jìn)程的地位穴吹。
wait()嗜侮;進(jìn)程調(diào)用港令,阻塞自己,等到自己的某個(gè)子進(jìn)程退出再繼續(xù)運(yùn)行锈颗。
vfork()顷霹;也是創(chuàng)建一個(gè)子進(jìn)程,但它并不把父進(jìn)程的映像全部復(fù)制到子進(jìn)程中击吱,而是只是用復(fù)制指針的方法使子進(jìn)程與父進(jìn)程的資源共享淋淀。它與父進(jìn)程共享一個(gè)內(nèi)存空間。
17)? 調(diào)用schedule()進(jìn)行進(jìn)程切換的方式有幾種覆醇?
進(jìn)程的切換與系統(tǒng)的一般執(zhí)行過(guò)程 - 20135222 - 博客園
?? ?直接調(diào)用 延遲調(diào)用
? ? 切換用戶空間
? ? 切換內(nèi)存堆棧
引申:
????進(jìn)程的調(diào)度時(shí)機(jī):
中斷處理過(guò)程(包括時(shí)鐘中斷、I/O中斷、系統(tǒng)調(diào)用和異常)中,直接調(diào)用schedule()党瓮,或者返回用戶態(tài)時(shí)根據(jù)need_resched標(biāo)記調(diào)用schedule();
內(nèi)核線程可以直接調(diào)用schedule()進(jìn)行進(jìn)程切換瓷翻,也可以在中斷處理過(guò)程中進(jìn)行調(diào)度对妄,也就是說(shuō)內(nèi)核線程作為一類的特殊的進(jìn)程可以主動(dòng)調(diào)度孝常,也可以被動(dòng)調(diào)度冻押;
用戶態(tài)進(jìn)程無(wú)法實(shí)現(xiàn)主動(dòng)調(diào)度稿茉,僅能通過(guò)陷入內(nèi)核態(tài)后的某個(gè)時(shí)機(jī)點(diǎn)進(jìn)行調(diào)度渺蒿,即在中斷處理過(guò)程中進(jìn)行調(diào)度少态。
????進(jìn)程的切換:
——為了控制進(jìn)程的執(zhí)行,內(nèi)核必須有能力掛起正在CPU上執(zhí)行的進(jìn)程为肮,并恢復(fù)以前掛起的某個(gè)進(jìn)程的執(zhí)行棋枕,這叫做進(jìn)程切換祖很、任務(wù)切換笨鸡、上下文切換趟脂;
——掛起正在CPU上執(zhí)行的進(jìn)程,與中斷時(shí)保存現(xiàn)場(chǎng)是不同的,中斷前后是在同一個(gè)進(jìn)程上下文中,只是由用戶態(tài)轉(zhuǎn)向內(nèi)核態(tài)執(zhí)行叠洗;
——進(jìn)程上下文包含了進(jìn)程執(zhí)行需要的所有信息
? ? |???? 用戶地址空間:包括程序代碼腾节,數(shù)據(jù),用戶堆棧等
? ? |????控制信息:進(jìn)程描述符,內(nèi)核堆棧等
? ? |????硬件上下文(注意中斷也要保存硬件上下文只是保存的方法不同)
——schedule()函數(shù)選擇一個(gè)新的進(jìn)程來(lái)運(yùn)行陡舅,并調(diào)用context_switch進(jìn)行上下文的切換田弥,這個(gè)宏調(diào)用switch_to來(lái)進(jìn)行關(guān)鍵上下文切換
? ? |????next = pick_next_task(rq, prev);????????//進(jìn)程調(diào)度算法都封裝這個(gè)函數(shù)內(nèi)部
? ? |????context_switch(rq, prev, next); ? ? ? ? ?//進(jìn)程上下文切換
? ? |????switch_to利用了prev和next兩個(gè)參數(shù):prev指向當(dāng)前進(jìn)程枯途,next指向被調(diào)度的進(jìn)程
18)? Linux調(diào)度程序是根據(jù)進(jìn)程的動(dòng)態(tài)優(yōu)先級(jí)還是靜態(tài)優(yōu)先級(jí)來(lái)調(diào)度進(jìn)程的库说?
?? ?動(dòng)態(tài)優(yōu)先級(jí)----完全公平調(diào)度器CFS
CFS 調(diào)度器 - uefi_artisan - CSDN博客
? ? 實(shí)時(shí)進(jìn)程優(yōu)于普通進(jìn)程亡呵,每次進(jìn)行進(jìn)程調(diào)度時(shí)沦泌,會(huì)計(jì)算出每一個(gè)進(jìn)程占用處理器權(quán)利的權(quán)重參數(shù)weight,優(yōu)先運(yùn)行weight值大的進(jìn)程涡驮。
19)? 進(jìn)程調(diào)度的核心數(shù)據(jù)結(jié)構(gòu)是哪個(gè)无牵?
???進(jìn)程控制塊?task_struct
淺析Linux下的task_struct結(jié)構(gòu)體 - qq_29503203的博客 - CSDN博客
20)? 如何加載夜只、卸載一個(gè)模塊?
使用insmod 命令加載模塊儒搭,使用rmmod命令卸載模塊擦酌。
insmod ? ? ?xxx.ko ? ? ——????rmmod ? ?xxx.ko ????—— lsmod
21)? 模塊和應(yīng)用程序分別運(yùn)行在什么空間遇伞?
?? ?模塊運(yùn)行在內(nèi)核空間驯耻、應(yīng)用程序運(yùn)行在用戶空間
22)? Linux中的浮點(diǎn)運(yùn)算由應(yīng)用程序?qū)崿F(xiàn)還是內(nèi)核實(shí)現(xiàn)涩赢?
?? ?由內(nèi)核實(shí)現(xiàn)
23)? 模塊程序能否使用可鏈接的庫(kù)函數(shù)?
?? ?不能搪柑,模塊是內(nèi)核函數(shù),不能使用C庫(kù)函數(shù)
24)? TLB中緩存的是什么內(nèi)容椿猎?
TLB(Translation Lookaside Buffer)傳輸后備緩沖器是一個(gè)內(nèi)存管理單元用于改進(jìn)虛擬地址到物理地址轉(zhuǎn)換速度的緩存。TLB是一個(gè)小的吉殃,虛擬尋址的緩存烘贴,其中每一行都保存著一個(gè)由單個(gè)PTE組成的塊。如果沒有TLB呢袱,則每次取數(shù)據(jù)都需要兩次訪問內(nèi)存,即查頁(yè)表獲得物理地址和取數(shù)據(jù)。
25)? Linux中有哪幾種設(shè)備卿吐?
字符設(shè)備 ?塊設(shè)備 網(wǎng)絡(luò)設(shè)備
26)? 字符設(shè)備驅(qū)動(dòng)程序的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)是哪個(gè)芜辕?
?? ?file_operations
字符設(shè)備驅(qū)動(dòng)的開始,我們必須了解的是三個(gè)很重要的數(shù)據(jù)結(jié)構(gòu),他們分別是file_operations、inode、file
27)? 設(shè)備驅(qū)動(dòng)程序包括哪些功能函數(shù)双饥?
模塊的注冊(cè)與注銷
設(shè)備的打開锉桑、關(guān)閉、讀微驶、寫及其他操作函數(shù)
設(shè)備的中斷服務(wù)程序
28)? 如何唯一標(biāo)識(shí)一個(gè)設(shè)備?
?? ?主設(shè)備號(hào)和從設(shè)備號(hào)
????通常漆撞,為了使應(yīng)用程序區(qū)分所控制設(shè)備的類型,內(nèi)核使用主設(shè)備號(hào)旺上。而存在多臺(tái)同類設(shè)備時(shí)瓶蚂,為了選擇其中的一種,設(shè)備驅(qū)動(dòng)程序就使用次設(shè)備號(hào)宣吱。
29)? Linux通過(guò)什么方式實(shí)現(xiàn)系統(tǒng)調(diào)用窃这?
?? ?SWI(軟中斷)
linux內(nèi)核中設(shè)置了一組用于實(shí)現(xiàn)系統(tǒng)功能的子程序,稱為系統(tǒng)調(diào)用征候。系統(tǒng)調(diào)用和普通庫(kù)函數(shù)調(diào)用非常相似杭攻,只是系統(tǒng)調(diào)用由操作系統(tǒng)核心提供,運(yùn)行于核心態(tài)疤坝,而普通的函數(shù)調(diào)用由函數(shù)庫(kù)或用戶自己提供兆解,運(yùn)行于用戶態(tài)。
用戶空間的程序無(wú)法直接執(zhí)行內(nèi)核代碼跑揉。它們不能直接調(diào)用內(nèi)核空間中的函數(shù)锅睛,因?yàn)閮?nèi)核駐留在受保護(hù)的地址空間上埠巨。如果進(jìn)程可以直接在內(nèi)核的地址空間上讀寫的話,系統(tǒng)安全就會(huì)失去控制现拒。所以辣垒,應(yīng)用程序應(yīng)該以某種方式通知系統(tǒng),告訴內(nèi)核自己需要執(zhí)行一個(gè)系統(tǒng)調(diào)用印蔬,希望系統(tǒng)切換到內(nèi)核態(tài)勋桶,這樣內(nèi)核就可以代表應(yīng)用程序來(lái)執(zhí)行該系統(tǒng)調(diào)用了。?
通知內(nèi)核的機(jī)制是靠軟件中斷實(shí)現(xiàn)的扛点。首先哥遮,用戶程序?yàn)橄到y(tǒng)調(diào)用設(shè)置參數(shù)岂丘。其中一個(gè)參數(shù)是系統(tǒng)調(diào)用編號(hào)陵究。參數(shù)設(shè)置完成后,程序執(zhí)行“系統(tǒng)調(diào)用”指令奥帘。x86系統(tǒng)上的軟中斷由int產(chǎn)生铜邮。這個(gè)指令會(huì)導(dǎo)致一個(gè)異常:產(chǎn)生一個(gè)事件,這個(gè)事件會(huì)致使處理器切換到內(nèi)核態(tài)并跳轉(zhuǎn)到一個(gè)新的地址寨蹋,并開始執(zhí)行那里的異常處理程序松蒜。此時(shí)的異常處理程序?qū)嶋H上就是系統(tǒng)調(diào)用處理程序。它與硬件體系結(jié)構(gòu)緊密相關(guān)已旧。?
新地址的指令會(huì)保存程序的狀態(tài)秸苗,計(jì)算出應(yīng)該調(diào)用哪個(gè)系統(tǒng)調(diào)用,調(diào)用內(nèi)核中實(shí)現(xiàn)那個(gè)系統(tǒng)調(diào)用的函數(shù)运褪,恢復(fù)用戶程序狀態(tài)惊楼,然后將控制權(quán)返還給用戶程序。系統(tǒng)調(diào)用是設(shè)備驅(qū)動(dòng)程序中定義的函數(shù)最終被調(diào)用的一種方式秸讹。
在Linux中檀咙,每個(gè)系統(tǒng)調(diào)用被賦予一個(gè)系統(tǒng)調(diào)用號(hào)。這樣璃诀,通過(guò)這個(gè)獨(dú)一無(wú)二的號(hào)就可以關(guān)聯(lián)系統(tǒng)調(diào)用弧可。當(dāng)用戶空間的進(jìn)程執(zhí)行一個(gè)系統(tǒng)調(diào)用的時(shí)候,這個(gè)系統(tǒng)調(diào)用號(hào)就被用來(lái)指明到底是要執(zhí)行哪個(gè)系統(tǒng)調(diào)用劣欢。進(jìn)程不會(huì)提及系統(tǒng)調(diào)用的名稱棕诵。
30)? Linux軟中斷和工作隊(duì)列的作用是什么?
?? ?????軟中斷(softirq):Linux系統(tǒng)把中斷分為兩部分凿将,前半部分是中斷立即執(zhí)行的年鸳,后半部分可以在稍后的某個(gè)時(shí)候執(zhí)行。由于后半部分的緊急程度不那么“硬”丸相,也由于后半部分的執(zhí)行是由軟件來(lái)啟動(dòng)的搔确,所以后半部分的中斷機(jī)制也叫做“軟中斷”。
?????? 工作隊(duì)列:Linux總是在已經(jīng)進(jìn)入就緒狀態(tài)的進(jìn)程中來(lái)選擇一個(gè)合適的進(jìn)程來(lái)運(yùn)行的。為了加快尋找速度膳算,Linux就把所有已就緒的進(jìn)程集中起來(lái)形成一個(gè)就緒進(jìn)程隊(duì)列座硕。這個(gè)隊(duì)列就叫工作隊(duì)列。