<xmp id="gc8um"><menu id="gc8um"></menu>
<tr id="gc8um"></tr>
<tr id="gc8um"></tr>
<object id="gc8um"><center id="gc8um"></center></object>
<rt id="gc8um"><small id="gc8um"></small></rt>
<tr id="gc8um"></tr>
<acronym id="gc8um"><center id="gc8um"></center></acronym>
<samp id="gc8um"></samp>
<option id="gc8um"></option>
<tt id="gc8um"><div id="gc8um"></div></tt>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<samp id="gc8um"></samp>
<rt id="gc8um"></rt>
<rt id="gc8um"></rt>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt>
<tr id="gc8um"></tr>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<sup id="gc8um"><small id="gc8um"></small></sup>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt>
<optgroup id="gc8um"><menu id="gc8um"></menu></optgroup>
<tr id="gc8um"></tr>
<rt id="gc8um"><small id="gc8um"></small></rt>
<menu id="gc8um"><noscript id="gc8um"></noscript></menu>
<option id="gc8um"></option>
<rt id="gc8um"></rt>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt><acronym id="gc8um"><small id="gc8um"></small></acronym><rt id="gc8um"></rt>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt><acronym id="gc8um"><small id="gc8um"></small></acronym>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<object id="gc8um"><small id="gc8um"></small></object>
<tr id="gc8um"></tr>
<rt id="gc8um"><small id="gc8um"></small></rt>
<tr id="gc8um"><optgroup id="gc8um"></optgroup></tr>
<samp id="gc8um"></samp>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
  • 1. Linux內核源代碼導讀 中國科學技術大學計算機系 陳香蘭(0551-3606864) [email protected] Spring 2009
  • 2. 一個典型的Linux操作系統的結構用戶應用程序System call對硬件資源的管理Shell,libKernel implementation10/16/20182Linux內核源代碼導讀
  • 3. 系統調用的意義操作系統為用戶態進程與硬件設備進行交互提供了一組接口——系統調用 把用戶從底層的硬件編程中解放出來 極大的提高了系統的安全性 使用戶程序具有可移植性10/16/20183Linux內核源代碼導讀
  • 4. API和系統調用應用編程接口(application program interface, API) 和系統調用是不同的 API只是一個函數定義 系統調用通過“軟”中斷向內核發出一個明確的請求 在x86中為int指令 Libc庫定義的一些API引用了封裝例程(wrapper routine,唯一目的就是發布系統調用) 一般每個系統調用對應一個封裝例程 庫再用這些封裝例程定義出給用戶的API10/16/20184Linux內核源代碼導讀
  • 5. 不是每個API都對應一個特定的系統調用。 API可能直接提供用戶態的服務 如,一些數學函數 一個單獨的API可能調用幾個系統調用 不同的API可能調用了同一個系統調用 返回值 大部分封裝例程返回一個整數,其值的含義依賴于相應的系統調用 -1在多數情況下表示內核不能滿足進程的請求 Libc中定義的errno變量包含特定的出錯碼10/16/20185Linux內核源代碼導讀
  • 6. 系統調用程序及服務例程當用戶態進程調用一個系統調用時,CPU切換到內核態并開始執行一個內核函數。 在Linux中是通過執行int $0x80來執行系統調用的, 這條匯編指令產生向量為128的編程異常 (回憶,trap_init中系統調用入口的初始化) 傳參: 內核實現了很多不同的系統調用, 進程必須指明需要哪個系統調用,這需要傳遞一個名為系統調用號的參數 使用eax寄存器10/16/20186Linux內核源代碼導讀
  • 7. 系統調用的返回值所有的系統調用返回一個整數值。 正數或0表示系統調用成功結束 負數表示一個出錯條件 這里的返回值與封裝例程返回值的約定不同 內核沒有設置或使用errno變量 封裝例程在系統調用返回取得返回值之后設置errno 當系統調用出錯時,返回的那個負值將要存放在errno變量中返回給應用程序10/16/20187Linux內核源代碼導讀
  • 8. 系統調用處理程序也和其他異常處理程序的結構類似 在進程的內核態堆棧中保存大多數寄存器的內容 (即保存恢復進程到用戶態執行所需要的上下文) 調用相應的系統調用服務例程處理系統調用 sys_xxx 通過syscall_exit從系統調用返回10/16/20188Linux內核源代碼導讀
  • 9. 應用程序、封裝例程、系統調用處理程序及系統調用服務例程之間的關系10/16/20189Linux內核源代碼導讀
  • 10. 為了把系統調用號與相應的服務例程關聯起來,內核利用了一個系統調用分派表(dispatch table)。 這個表存放在sys_call_table數組中, 有nr_syscalls個表項:第n個表項對應了系統調用號為n的服務例程的入口地址的指針 觀察sys_call_table 觀察nr_syscalls的定義10/16/201810Linux內核源代碼導讀
  • 11. 初始化系統調用內核初始化期間調用trap_init()函數建立IDT表中向量128對應的表項,語句如下: 其中,SYSCALL_VECTOR被定義為0x80 該調用把下列值存入這個系統門描述符的相應字段: segment selector:內核代碼段__KERNEL_CS的段選擇符 offset:指向system_call()異常處理程序的入口地址 type:置為15。表示這個異常是一個陷阱,相應的處理程序不禁止可屏蔽中斷 DPL(描述符特權級):置為3。這就允許用戶態進程訪問這個門,即在用戶程序中使用int $0x80是合法的10/16/201811Linux內核源代碼導讀
  • 12. CPU執行int 0x80指令過程類似中斷 在進入system_call 之前,堆棧情況為10/16/201812Linux內核源代碼導讀
  • 13. system_call()函數10/16/201813Linux內核源代碼導讀
  • 14. 觀察SAVE_ALL宏SAVE_ALL 在堆棧上依次保存了3個段寄存器fs、es、ds的值,以及ax、bp、di、si、dx、cx、bx這7個寄存器的值。 并對段寄存器ds、es、fs賦予適當的值10/16/201814Linux內核源代碼導讀
  • 15. 系統調用的參數傳遞系統調用也需要輸入輸出參數,例如 實際的值 用戶態進程地址空間的變量的地址 甚至是包含指向用戶態函數的指針的數據結構的地址 system_call是linux中所有系統調用的入口點,每個系統調用至少有一個參數,即由eax傳遞的系統調用號 例如: 一個應用程序調用fork()封裝例程,那么在執行int $0x80之前就把eax寄存器的值置為2(即__NR_fork)。 這個寄存器的設置是libc庫中的封裝例程進行的,因此用戶一般不關心系統調用號10/16/201815Linux內核源代碼導讀
  • 16. 很多系統調用需要不止一個參數 普通C函數的參數傳遞是通過把參數值寫入堆棧(用戶態堆棧或內核態堆棧)來實現的。但因為系統調用是一種特殊函數,它由用戶態進入了內核態,所以既不能使用用戶態的堆棧也不能直接使用內核態堆棧用戶態堆棧用戶態C函數內核態堆棧內核態C函數?10/16/201816Linux內核源代碼導讀
  • 17. 在int $0x80匯編指令之前,系統調用的參數被寫入CPU的寄存器。然后,在進入內核態調用系統調用服務例程之前,內核再把存放在CPU寄存器中的參數拷貝到內核態堆棧中。因為畢竟服務例程是C函數,它還是要到堆棧中去尋找參數的用戶態堆棧用戶態C函數內核態堆棧內核態C函數寄存器10/16/201817Linux內核源代碼導讀
  • 18. 回想一下在進入中斷和異常處理程序前,在內核態堆棧中保存的pt_regs結構,此時pt_regs結構中的一些寄存器被用來傳遞參數或者pt_regs結構本身就是參數 使用寄存器傳參的限制 一個參數最長32位 根據pt_regs結構,最多可以傳遞6個參數10/16/201818Linux內核源代碼導讀
  • 19. 參數傳遞舉例處理write系統調用的sys_write服務例程聲明如下 該函數期望在棧頂找到fd,buf和count參數 在封裝sys_write()的封裝例程中,將會在ebx、ecx和edx寄存器中分別填入這些參數的值,然后在進入system_call時,SAVE_ALL會把這些寄存器保存在堆棧中,進入sys_write服務例程后,就可以在相應的位置找到這些參數 舉例觀察asmlinkage使得編譯器不通過寄存器(x=0)而 使用堆棧傳遞參數10/16/201819Linux內核源代碼導讀
  • 20. SAVE_ALL后的 堆棧情況10/16/201820Linux內核源代碼導讀
  • 21. 在有些系統調用中,C庫接口中盡管沒有提供參數,但是在內核中卻會依賴保存的pt_regs信息,例如fork()?sys_clone()?do_frok()10/16/201821Linux內核源代碼導讀
  • 22. 傳遞返回值服務例程的返回值是將會被寫入eax寄存器中 這個是在執行“return”指令時,由編譯器自動完成的10/16/201822Linux內核源代碼導讀
  • 23. 驗證參數在內核打算滿足用戶的請求之前,必須仔細的檢查所有的系統調用參數 比如前面的write()系統調用,fd參數是一個文件描述符,sys_write()必須檢查這個fd是否確實是以前已打開文件的一個文件描述符,進程是否有向fd指向的文件的寫權限,如果有條件不成立,那這個處理程序必須返回一個負數10/16/201823Linux內核源代碼導讀
  • 24. 只要一個參數指定的是地址,那么內核必須檢查它是否在這個進程的地址空間之內,有兩種驗證方法: 驗證這個線性地址是否屬于進程的地址空間,并且是否有合理的訪問權限 僅僅驗證這個線性地址小于PAGE_OFFSET(用戶態地址,粗粒度) 對于第一種方法: 費時 大多數情況下,不必要 對于第二種方法: 高效 在后續的執行過程中,會自然的捕獲到出錯情況(配合缺頁異常) 從linux2.2開始執行第二種檢查10/16/201824Linux內核源代碼導讀
  • 25. 對用戶地址參數的粗略驗證在內核中,可以訪問到所有的內存 要防止用戶將一個內核地址作為參數傳遞給內核,這將導致它借用內核代碼來讀寫任意內存 檢查方法: Addr+size是否超出當前進程的地址邊界對于用戶進程:不大于3G 對于內核線程:可以使用整個4G10/16/201825Linux內核源代碼導讀
  • 26. 訪問進程的地址空間系統調用服務例程需要非常頻繁的讀寫進程地址空間的數據10/16/201826Linux內核源代碼導讀
  • 27. 舉例get_userget_user__get_user_x10/16/201827Linux內核源代碼導讀
  • 28. 訪問進程地址空間時的缺頁內核對進程傳遞的地址參數只進行粗略的檢查 訪問進程地址空間時的缺頁,可以有多種情況 合理的缺頁:來自虛存技術 由于錯誤引起的缺頁 由于非法引起的缺頁10/16/201828Linux內核源代碼導讀
  • 29. 非法缺頁的判定內核中,只有少數幾個函數/宏會訪問用戶地址空間 對于一次非法缺頁,一定來自于這些函數/宏 可以將訪問用戶地址空間的指令的地址一一列舉出來,當發生非法缺頁時,根據引起出錯的指令地址來定位 若定位到:則說明系統調用參數有問題 否則,可能是更嚴重的bug引起的 Linux使用了異常表的概念 __ex_table, __start___ex_table, __stop___ex_table10/16/201829Linux內核源代碼導讀
  • 30. __ex_table的表項 哪條指令訪問了用戶地址空間如果這條指令引起了非法缺頁,該怎么處理Fixup所指向的代碼,稱為修正代碼 通常為匯編代碼10/16/201830Linux內核源代碼導讀
  • 31. 舉例get_user相關文件getuser_32.S10/16/201831Linux內核源代碼導讀
  • 32. 缺頁異常對非法缺頁的處理在缺頁異常do_page_fault中,若最后發現是非法缺頁,就會執行下面的操作 假設找到了修正代碼,會發生什么事情?該操作使用引起出錯的代碼地址在異常表中進行查找,若找到,就返回 相應的修正代碼地址,填寫在regs->eip中10/16/201832Linux內核源代碼導讀
  • 33. IDT表, 進入異 常處理某內核函數缺頁缺頁處理作為一次故障,要重新執行引起出錯的代碼正常情況下,這個eip在發生異常時, 由硬件保存到堆棧中 因此,正常情況下,返回此處非法異常修改堆棧中的eip,指向修正代碼 因此,非法缺頁時,返回此處修正代碼異常處理后,返回eip指定的位置執行10/16/201833Linux內核源代碼導讀
  • 34. 系統調用的返回RESTORE_REGS10/16/201834Linux內核源代碼導讀
  • 35. 中斷、異常、系統調用小結用戶態內核態IDT表中斷異常系統調用iretreturn_from_intr return_from_exception syscall_exit10/16/201835Linux內核源代碼導讀
  • 36. Project自選: 分析中斷、異常和系統調用的代碼之一,提交分析報告 采用某種方法截獲一個中斷,例如鍵盤中斷 采用某種方法制造缺頁異常 自己編寫一個系統調用 提交project,詳細說明你的分析或者實驗10/16/201836Linux內核源代碼導讀

下載文檔到電腦,查找使用更方便

需要 10 金幣 [ 分享文檔獲得金幣 ] 0 人已下載

下載文檔

平特争霸
<xmp id="gc8um"><menu id="gc8um"></menu>
<tr id="gc8um"></tr>
<tr id="gc8um"></tr>
<object id="gc8um"><center id="gc8um"></center></object>
<rt id="gc8um"><small id="gc8um"></small></rt>
<tr id="gc8um"></tr>
<acronym id="gc8um"><center id="gc8um"></center></acronym>
<samp id="gc8um"></samp>
<option id="gc8um"></option>
<tt id="gc8um"><div id="gc8um"></div></tt>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<samp id="gc8um"></samp>
<rt id="gc8um"></rt>
<rt id="gc8um"></rt>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt>
<tr id="gc8um"></tr>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<sup id="gc8um"><small id="gc8um"></small></sup>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt>
<optgroup id="gc8um"><menu id="gc8um"></menu></optgroup>
<tr id="gc8um"></tr>
<rt id="gc8um"><small id="gc8um"></small></rt>
<menu id="gc8um"><noscript id="gc8um"></noscript></menu>
<option id="gc8um"></option>
<rt id="gc8um"></rt>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt><acronym id="gc8um"><small id="gc8um"></small></acronym><rt id="gc8um"></rt>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt><acronym id="gc8um"><small id="gc8um"></small></acronym>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<object id="gc8um"><small id="gc8um"></small></object>
<tr id="gc8um"></tr>
<rt id="gc8um"><small id="gc8um"></small></rt>
<tr id="gc8um"><optgroup id="gc8um"></optgroup></tr>
<samp id="gc8um"></samp>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<xmp id="gc8um"><menu id="gc8um"></menu>
<tr id="gc8um"></tr>
<tr id="gc8um"></tr>
<object id="gc8um"><center id="gc8um"></center></object>
<rt id="gc8um"><small id="gc8um"></small></rt>
<tr id="gc8um"></tr>
<acronym id="gc8um"><center id="gc8um"></center></acronym>
<samp id="gc8um"></samp>
<option id="gc8um"></option>
<tt id="gc8um"><div id="gc8um"></div></tt>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<samp id="gc8um"></samp>
<rt id="gc8um"></rt>
<rt id="gc8um"></rt>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt>
<tr id="gc8um"></tr>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<sup id="gc8um"><small id="gc8um"></small></sup>
<acronym id="gc8um"><optgroup id="gc8um"></optgroup></acronym>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt>
<optgroup id="gc8um"><menu id="gc8um"></menu></optgroup>
<tr id="gc8um"></tr>
<rt id="gc8um"><small id="gc8um"></small></rt>
<menu id="gc8um"><noscript id="gc8um"></noscript></menu>
<option id="gc8um"></option>
<rt id="gc8um"></rt>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt><acronym id="gc8um"><small id="gc8um"></small></acronym><rt id="gc8um"></rt>
<rt id="gc8um"><optgroup id="gc8um"></optgroup></rt><acronym id="gc8um"><small id="gc8um"></small></acronym>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
<object id="gc8um"><small id="gc8um"></small></object>
<tr id="gc8um"></tr>
<rt id="gc8um"><small id="gc8um"></small></rt>
<tr id="gc8um"><optgroup id="gc8um"></optgroup></tr>
<samp id="gc8um"></samp>
<acronym id="gc8um"><small id="gc8um"></small></acronym>
埃弗顿巴萨 2013彩票平台注册送彩金 海洋游乐场注册 济南麻将胡牌技巧 一零八好汉APP mg东方珍兽中奖规律 斯帕尔足球俱乐部球衣 龙的财富试玩 福彩3d走势图综和版 上海时时彩五星走势图 北京赛pk10开奖合法吗 勒沃库森2013球衣 我叫mt4石碑任务 波斯波利斯球队对棉农 广东快乐10分app pc蛋蛋是国家开的吗