一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

利用異常表處理LINUX內(nèi)核態(tài)缺頁異v常

 木芙蓉的圖書館 2011-07-21

在程序的執(zhí)行過程中,因?yàn)橛龅侥撤N障礙而使 CPU 無法最終訪問到相應(yīng)的物理內(nèi)存單元,即無法完成從虛擬地址到物理地址映射的時(shí)候,CPU 會(huì)產(chǎn)生一次缺頁異常,從而進(jìn)行相應(yīng)的缺頁異常處理?;?CPU 的這一特性,Linux 采用了請(qǐng)求調(diào)頁(Demand Paging)和寫時(shí)復(fù)制(Copy On Write)的技術(shù)。

  1. 請(qǐng)求調(diào)頁是一種動(dòng)態(tài)內(nèi)存分配技術(shù),它把頁框的分配推遲到不能再推遲為止。這種技術(shù)的動(dòng)機(jī)是:進(jìn)程開始運(yùn)行的時(shí)候并不訪問地址空間中的全部?jī)?nèi)容。事實(shí)上,有 一部分地址也許永遠(yuǎn)也不會(huì)被進(jìn)程所使用。程序的局部性原理也保證了在程序執(zhí)行的每個(gè)階段,真正使用的進(jìn)程頁只有一小部分,對(duì)于臨時(shí)用不到的頁,其所在的頁 框可以由其它進(jìn)程使用。因此,請(qǐng)求分頁技術(shù)增加了系統(tǒng)中的空閑頁框的平均數(shù),使內(nèi)存得到了很好的利用。從另外一個(gè)角度來看,在不改變內(nèi)存大小的情況下,請(qǐng) 求分頁能夠提高系統(tǒng)的吞吐量。當(dāng)進(jìn)程要訪問的頁不在內(nèi)存中的時(shí)候,就通過缺頁異常處理將所需頁調(diào)入內(nèi)存中。

  2. 寫時(shí)復(fù)制主要應(yīng)用于系統(tǒng)調(diào)用fork,父子進(jìn)程以只讀方式共享頁框,當(dāng)其中之一要修改頁框時(shí),內(nèi)核才通過缺頁異常處理程序分配一個(gè)新的頁框,并將頁框標(biāo)記 為可寫。這種處理方式能夠較大的提高系統(tǒng)的性能,這和Linux創(chuàng)建進(jìn)程的操作過程有一定的關(guān)系。在一般情況下,子進(jìn)程被創(chuàng)建以后會(huì)馬上通過系統(tǒng)調(diào)用 execve將一個(gè)可執(zhí)行程序的映象裝載進(jìn)內(nèi)存中,此時(shí)會(huì)重新分配子進(jìn)程的頁框。那么,如果fork的時(shí)候就對(duì)頁框進(jìn)行復(fù)制的話,顯然是很不合適的。

  在上述的兩種情況下出現(xiàn)缺頁異常,進(jìn)程運(yùn)行于用戶態(tài),異常處理程序可以讓進(jìn)程從出現(xiàn)異常的指令處恢復(fù)執(zhí)行,使用戶感覺不到異常的發(fā)生。當(dāng)然,也 會(huì)有異常無法正?;謴?fù)的情況,這時(shí),異常處理程序會(huì)進(jìn)行一些善后的工作,并結(jié)束該進(jìn)程。也就是說,運(yùn)行在用戶態(tài)的進(jìn)程如果出現(xiàn)缺頁異常,不會(huì)對(duì)操作系統(tǒng)核 心的穩(wěn)定性造成影響。那么對(duì)于運(yùn)行在核心態(tài)的進(jìn)程如果發(fā)生了無法正?;謴?fù)的缺頁異常,應(yīng)該如何處理呢?是否會(huì)導(dǎo)致系統(tǒng)的崩潰呢?是否能夠解決好內(nèi)核態(tài)缺頁 異常對(duì)于操作系統(tǒng)核心的穩(wěn)定性來說會(huì)產(chǎn)生很大的影響,如果一個(gè)誤操作就會(huì)造成系統(tǒng)的Oops,這對(duì)于用戶來說顯然是不能容忍的。本文正是針對(duì)這個(gè)問題,介 紹了一種Linux內(nèi)核中所采取的解決方法。

  在讀者繼續(xù)往下閱讀之前,有一點(diǎn)需要先說明一下,本文示例中所選的代碼取自于Linux-2.4.0,編譯環(huán)境是gcc-2.96,objdump的版本是2.11.93.0.2,具體的版本信息可以通過以下的命令進(jìn)行查詢:

$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)
$ objdump -v
GNU objdump 2.11.93.0.2 20020207
Copyright 2002 Free Software Foundation, Inc.

   GCC的擴(kuò)展功能

  由于本文中會(huì)用到GCC的擴(kuò)展功能,即匯編器as中提供的.section偽操作,在文章開始之前我再作一個(gè)簡(jiǎn)要的介紹。此偽操作對(duì)于不同的可 執(zhí)行文件格式有不同的解釋,我也不一一列舉,僅對(duì)我們所感興趣的Linux中常用的ELF格式的用法加以描述,其指令格式如下:

 .section NAME[, "FLAGS"]
  
  大家所熟知的C程序一般由以下的幾個(gè)部分組成:代碼段(text section)、初始化數(shù)據(jù)段(data section)、非初始化數(shù)據(jù)段(bss section)、棧(heap)以及堆(stack),具體的地址空間布局可以參考《UNIX環(huán)境高級(jí)編程》一書。

  在Linux內(nèi)核中,通過使用.section的偽操作,可以把隨后的代碼匯編到一個(gè)由NAME指定的段中。而FLAGS字段則說明了該段的屬性,它可以用下面介紹的單個(gè)字符來表示,也可以是多個(gè)字符的組合。

'a' 可重定位的段;
  'w' 可寫段;
  'x' 可執(zhí)行段;
  'W' 可合并的段;
  's' 共享段。

  舉個(gè)例子來說明,讀者在后面會(huì)看到的:.section .fixup, "ax"。這樣的一條指令定義了一個(gè)名為.fixup的段,隨后的指令會(huì)被加入到這個(gè)段中,該段的屬性是可重定位并可執(zhí)行。

  內(nèi)核缺頁異常處理
  運(yùn)行在核心態(tài)的進(jìn)程經(jīng)常需要訪問用戶地址空間的內(nèi)容,但是誰都無法保證內(nèi)核所得到的這些從用戶空間傳入的地址信息是"合法"的。為了保護(hù)內(nèi)核不受錯(cuò)誤信息的攻擊,需要驗(yàn)證這些從用戶空間傳入的地址信息的正確性。

  在老版本的Linux中,這個(gè)工作是通過函數(shù)verify_area來完成的:

extern inline int verify_area(int type, const void * addr, unsigned long size)

  該函數(shù)驗(yàn)證了是否可以以type中說明的訪問類型(read or write)訪問從地址addr開始、大小為size的一塊虛擬存儲(chǔ)區(qū)域。為了做到這一點(diǎn),verify_read首先需要找到包含地址addr的虛擬存 儲(chǔ)區(qū)域(vma)。一般的情況下(正確運(yùn)行的程序)這個(gè)測(cè)試都會(huì)成功返回,在少數(shù)情況下才會(huì)出現(xiàn)失敗的情況。也就是說,大部分的情況下內(nèi)核在一些無用的驗(yàn) 證操作上花費(fèi)了不算短的時(shí)間,這從操作系統(tǒng)運(yùn)行效率的角度來說是不可接受的。

  為了解決這個(gè)問題,現(xiàn)在的Linux設(shè)計(jì)中將驗(yàn)證的工作交給虛存中的硬件設(shè)備來完成。當(dāng)系統(tǒng)啟動(dòng)分頁機(jī)制以后,如果一條指令的虛擬地址所對(duì)應(yīng)的 頁框(page frame)不在內(nèi)存中或者訪問的類型有錯(cuò)誤,就會(huì)發(fā)生缺頁異常。處理器把引起缺頁異常的虛擬地址裝到寄存器CR2中,并提供一個(gè)出錯(cuò)碼,指示引起缺頁異 常的存儲(chǔ)器訪問的類型,隨后調(diào)用Linux的缺頁異常處理函數(shù)進(jìn)行處理。

  Linux中進(jìn)行缺頁異常處理的函數(shù)如下:

asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
{
  ……………………
  __asm__("movl %%cr2,%0":"=r" (address));
  ……………………
  vma = find_vma(mm, address);
  if (!vma)
  goto bad_area;
  if (vma->vm_start <= address)
  goto good_area;
  if (!(vma->vm_flags & VM_GROWSDOWN))
  goto bad_area;
  if (error_code & 4) {
  if (address + 32 < regs->esp)
  goto bad_area;
  ……………………
bad_area:
  ……………………
no_context:
/* Are we prepared to handle this kernel fault? */
  if ((fixup = search_exception_table(regs->eip)) != 0) {
  regs->eip = fixup;
  return;
  }
  ………………………
}

  首先讓我們來看看傳給這個(gè)函數(shù)調(diào)用的兩個(gè)參數(shù):它們都是通過entry.S在堆棧中建立的(arch/i386/kernel /entry.S),參數(shù)regs指向保存在堆棧中的寄存器,error_code中存放著異常的出錯(cuò)碼,具體的堆棧布局參見圖一(堆棧的生成過程請(qǐng)參考 《Linux內(nèi)核源代碼情景分析》一書)

  該函數(shù)首先從CPU的控制寄存器CR2中獲取出現(xiàn)缺頁異常的虛擬地址。由于缺頁異常處理程序需要處理的缺頁異常類型很多,分支也很復(fù)雜?;诒疚牡闹髦?,我們只關(guān)心以下的幾種內(nèi)核缺頁異常處理的情況:

  1." 程序要訪問的內(nèi)核地址空間的內(nèi)容不在內(nèi)存中,先跳轉(zhuǎn)到標(biāo)號(hào)vmalloc_fault,如果當(dāng)前訪問的內(nèi)容所對(duì)應(yīng)的頁目錄項(xiàng)不在內(nèi)存中,再跳轉(zhuǎn)到標(biāo)號(hào)no_context;

  2. 缺頁異常發(fā)生在中斷或者內(nèi)核線程中,跳轉(zhuǎn)到標(biāo)號(hào)no_context;

  3. 程序在核心態(tài)運(yùn)行時(shí)訪問用戶空間的數(shù)據(jù),被訪問的數(shù)據(jù)不在內(nèi)存中

  a) 出現(xiàn)異常的虛擬地址在進(jìn)程的某個(gè)vma中,但是系統(tǒng)內(nèi)存無法分配空閑頁框(page frame),則先跳轉(zhuǎn)到標(biāo)號(hào)out_of_memory,再跳轉(zhuǎn)到標(biāo)號(hào)no_context;

  b) 出現(xiàn)異常的虛擬地址不屬于進(jìn)程任一個(gè)vma,而且不屬于堆棧擴(kuò)展的范疇,則先跳轉(zhuǎn)到標(biāo)號(hào)bad_area,最終也是到達(dá)標(biāo)號(hào)no_context。

  從上面的這幾種情況來看,我們關(guān)注的焦點(diǎn)最后集中到標(biāo)號(hào)no_context處,即對(duì)函數(shù)search_exception_table的調(diào) 用。這個(gè)函數(shù)的作用就是通過發(fā)生缺頁異常的指令(regs->eip)在異常表(exception table)中尋找下一條可以繼續(xù)運(yùn)行的指令(fixup)。這里提到的異常表包含一些地址對(duì),地址對(duì)中的前一個(gè)地址表示出現(xiàn)異常的指令的地址,后一個(gè)表 示當(dāng)前一個(gè)指令出現(xiàn)錯(cuò)誤時(shí),程序可以繼續(xù)得以執(zhí)行的修復(fù)地址。

  如果這個(gè)查找操作成功的話,缺頁異常處理程序?qū)⒍褩V械姆祷氐刂罚╮egs->eip)修改成修復(fù)地址并返回,隨后,發(fā)生異常的進(jìn)程將按照fixup中安排好的指令繼續(xù)執(zhí)行下去。當(dāng)然,如果無法找到與之匹配的修復(fù)地址,系統(tǒng)只有打印出出錯(cuò)信息并停止運(yùn)作。

  那么,這個(gè)所謂的修復(fù)地址又是如何生成的呢?是系統(tǒng)自動(dòng)生成的嗎?答案當(dāng)然是否定的,這些修復(fù)指令都是編程人員通過as提供的擴(kuò)展功能寫進(jìn)內(nèi)核源碼中的。下面我們就來分析一下其實(shí)現(xiàn)機(jī)制。


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    国产精品久久三级精品| 91人妻人澡人人爽人人精品| 国产精品成人免费精品自在线观看 | 亚洲国产精品久久网午夜| 国产精品人妻熟女毛片av久| 精品日韩视频在线观看| 日韩美女偷拍视频久久| 久久久精品区二区三区| 亚洲综合激情另类专区老铁性| 亚洲精品中文字幕一二三| 日本免费一级黄色录像| 国产精品蜜桃久久一区二区| 91久久精品国产一区蜜臀| 91国内视频一区二区三区| 麻豆欧美精品国产综合久久| 国产又粗又长又大高潮视频| 俄罗斯胖女人性生活视频| 四十女人口红哪个色好看| 风韵人妻丰满熟妇老熟女av| 91超精品碰国产在线观看| 91亚洲精品亚洲国产| 一级片二级片欧美日韩| 最近的中文字幕一区二区| 亚洲最新一区二区三区| 欧美午夜视频免费观看| 欧美日韩人妻中文一区二区| 日系韩系还是欧美久久| 麻豆亚州无矿码专区视频| 国产av乱了乱了一区二区三区| 日韩免费国产91在线| 偷拍偷窥女厕一区二区视频| 麻豆精品在线一区二区三区| 欧美日韩综合免费视频| 久久精品国产99精品最新| 老司机精品视频在线免费| 中文字字幕在线中文乱码二区| 国产在线小视频你懂的| 日韩黄色一级片免费收看| 国产又粗又爽又猛又黄的| 国产日韩久久精品一区| 亚洲第一区欧美日韩在线|