中斷與系統調用


系統調用的概念

  程序員或系統管理員通常並非直接和系統調用打交道,在實際應用中,程序員調用的的函數,或稱為應用程序接口(API),管理員使用的則是更高層次的系統命令。操作系統為每個系統調用在標准C函數庫中構造一個具有相同名字的封裝函數,由它來屏蔽下層的復雜性,負責把操作系統提供的服務接口----系統調用-----封裝成應用程序能夠直接調用的函數(庫函數)

  系統調用通過中斷機制向內核提交請求,它的功能由內核函數實現,進入內核后不同系統調用找到各自對應的內核函數,這些內核函數就是系統調用的“服務例程”。API實質上是一個函數定義,說明如何獲得一個給定服務,如read(),malloc(),free()等。它有可能和系統調用形式上一致,如read()函數就和read()系統調用對應,但未必總是一一對應,往往會出現不同函數的內部用到同一個內核函數,如malloc(),free()內部均利用sys_brk()內核函數來擴大或縮小進程堆;一個函數也可利用幾個內核函數組合完成任務,有些函數不需要任何內核函數,它的實現與內核無關。系統命令相對與編程接口有更高的層次,它們是內部引用函數的可執行程序,如常用的系統命令ls,hostname等,而這些命令的實現大多數依靠系統調用。

  下面以read()為例來了解系統調用的執行流程,當應用程序調用read(fd,buffer,nbytes)函數時,該函數在Linux/GNU提供的標准C庫,即libc中,對應的封裝函數由下面匯編指令實現:

      movel  $3,%eax

      movel  fd,%ebx

      movel  buffer,%ecx

      movel  nbutes,%edx      

      int  $0x80

  在Linux中規定int  $0x80指令是系統調用的總入口,若干個寄存器中存放應用程序傳遞個內核的參數。內核為了區分不同的系統調用,需要給每個都分配唯一的系統調用號,而相對應的內核函數的入口地址都放在系統調用表中。內核在獲得系統調用號后根據寄存器EAX中調用號的值跳轉到系統調用表相應的內核函數,以完成應用程序請求的服務。

系統調用的執行流程

  系統調用與普通C語言函數調用最大的區別在於系統調用需要陷入內核態,發生特權級的轉換。

  1.保存現場  2.跳到內核函數  3.參數傳遞  

  4.系統調用封裝

  應用程序發出的系統調用是同步事件,雖然它在內核態執行,但卻在調用進程的上下文中,所以既可以訪問進程地址空間,也可以訪問內核空間。system_call()在內核棧上保存硬件上下文,然后使用系統調用號作為系統調用表system_call_table的索引,以確定system_call()應該執行哪個系統調用對應的內核函數。當系統調用執行結束后,system_call()在對應的寄存器EAX中放入返回的int值或錯誤碼,並從內核棧恢復硬件上下文,回到用戶態並把控制權交給庫函數,庫函數再返回給應用程序。

  5.系統調用上下文

  內核在執行系統調用時處於進程上下文中,current指針指向當前進程,即引發系統調用的進程。

 

https://www.cnblogs.com/qiaoshanzi/archive/2013/05/16/3082550.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM