<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      前言

      最近有點事情,馬上要開學了,所以學習的腳步就慢下來了。這一篇主要是來說操作系統(tǒng)的系統(tǒng)調用的,像C語言的printf深入到內部就是一個有關屏幕輸出的系統(tǒng)調用

      什么是系統(tǒng)調用


      之前提過操作系統(tǒng)是對硬件的抽象,也是軟硬件之間的一層。之前比如如果我們想要在屏幕上輸出一些字符,就需要一些指令操作,然后把數(shù)據(jù)放到顯存上。但是在有了操作系統(tǒng)后,就不需要這樣做,也不能這樣做了。這時候只要操作系統(tǒng)提供一個接口來讓我們完成這個任務

      由操作系統(tǒng)實現(xiàn)提供的所有系統(tǒng)調用所構成的集合即程序接口或應用編程接口(Application Programming
      Interface,API)。是應用程序同系統(tǒng)之間的接口。

      系統(tǒng)調用的實現(xiàn)

      在硬件設計上,通過區(qū)分內核態(tài)和用戶態(tài)來把內核程序和用戶程序隔離開

      CS寄存器最低的兩位為0即是內核態(tài),為3是用戶態(tài)

      但是系統(tǒng)調用的代碼是處在內核態(tài)的,所以就需要提供一種方法來能夠讓用戶程序進入內核態(tài)來實現(xiàn)系統(tǒng)調用

      在X86里,INT指令就是硬件用來提供由用戶態(tài)進入內核態(tài)的方法,所以系統(tǒng)調用的實現(xiàn)就可以變?yōu)椋?br>
      * 由用戶程序發(fā)起一個INT指令,指明要調用的服務
      * 在操作系統(tǒng)里寫出相應的中斷處理
      * 由操作系統(tǒng)根據(jù)用戶指明要調用的服務取執(zhí)行相應的代碼
      內聯(lián)匯編

      稍微說一下C里的內聯(lián)匯編,以免之后忘記。

      gcc的內聯(lián)匯編一般都是這個格式
      asm ( 匯編指令 : 輸出操作數(shù) // 非必需 : 輸入操作數(shù) // 非必需 : 其他被污染的寄存器 // 非必需 );
      *
      第一部分就是匯編指令

      *
      第二部分是輸出操作數(shù),都是 "=?"(var) 的形式, var可以是任意內存變量(輸出結果會存到這個變量中), ?一般是下面這些標識符
      (表示內聯(lián)匯編中用什么來代理這個操作數(shù)):

      a,b,c,d,S,D 分別代表 eax,ebx,ecx,edx,esi,edi 寄存器
      r 上面的寄存器的任意一個(誰閑著就用誰)
      m 內存
      i 立即數(shù)(常量,只用于輸入操作數(shù))
      g 寄存器、內存、立即數(shù) 都行
      在匯編中用%序號來代表這些輸入/輸出操作數(shù),序號從0開始。為了與操作數(shù)區(qū)分開來,寄存器用兩個%引出,如:%%eax

      *
      第三部分是是輸入操作數(shù),都是 "?"(var) 的形式, ? 除了可以是上面的那些標識符,還可以是輸出操作數(shù)的序號,表示用 var
      來初始化該輸出操作數(shù),上面的程序中 %0 和 %1 就是一個東西,初始化為 1(a的值)。

      *
      第四部分標出那些在匯編代碼中修改了的、 又沒有在輸入/輸出列表中列出的寄存器, 這樣 gcc 就不會擅自使用這些"危險的"寄存器。 還可以用
      "memory" 表示在內聯(lián)匯編中修改了內存, 之前緩存在寄存器中的內存變量需要重新讀取。

      參考鏈接 <https://github.com/1184893257/simplelinux/blob/master/inlineasm.md>

      Linux0.11里對系統(tǒng)調用的代碼實現(xiàn)

      設置中斷

      * 首先需要對IDT設置中斷調用的處理函數(shù) #define set_system_gate(n,addr) \
      _set_gate(&idt[n],15,3,addr) #define _set_gate(gate_addr,type,dpl,addr) \
      __asm__ ("movw %%dx,%%ax\n\t" \ "movw %0,%%dx\n\t" \ "movl %%eax,%1\n\t" \
      "movl %%edx,%2" \ : \ : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \ "o"
      (*((char *) (gate_addr))), \ "o" (*(4+(char *) (gate_addr))), \ "d" ((char *)
      (addr)),"a" (0x00080000)) set_system_gate(0x80,&system_call);
      實現(xiàn)中斷函數(shù)

      * sys_call_table[]是一個指針數(shù)組,定義在include/linux/sys.h中,該指針數(shù)組中設置了所有72個系統(tǒng)調用C處理函數(shù)地址。
      system_call: cmpl $nr_system_calls-1,%eax ja bad_sys_call push %ds push %es
      push %fs pushl %edx pushl %ecx # push %ebx,%ecx,%edx as parameters pushl %ebx #
      to the system call movl $0x10,%edx # set up ds,es to kernel space mov %dx,%ds
      mov %dx,%es movl $0x17,%edx # fs points to local data space mov %dx,%fs call
      sys_call_table(,%eax,4) pushl %eax movl current,%eax cmpl $0,state(%eax) #
      state jne reschedule cmpl $0,counter(%eax) # counter je reschedule
      提供接口

      * 在linux向應用程序提供系統(tǒng)調用接口write
      * _syscall3的本質上是一個宏 _syscall3(int,write,int,fd,const char *,buf,off_t,count)
      #define _syscall3(type,name,atype,a,btype,b,ctype,c) \ type name(atype a,btype
      b,ctype c) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \
      : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \ if
      (__res>=0) \ return (type) __res; \ errno=-__res; \ return -1; \ }
      小結

      這樣對于一個系統(tǒng)調用就會變成

      printf 用戶調用

      ?

      int 0x80 庫函數(shù)的實現(xiàn)

      ?

      進入內核

      system_call 中斷調用

      ?

      sys_ 系統(tǒng)調用

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          天天操天天日天天射 | 天天搞天天操天天日 | 奴役支配狂虐xxxxx在线 | 欧美性生活在线观看 | 欧美一级婬片免费视频黄 | 国产精品女A片爽视频爽 | 国产真实露脸乱子伦 | 在线观看免费A片免费视频 | 成人爽视频 | AAA一级黄片 |