青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-80  評論-24  文章-0  trackbacks-0
該文件是系統調用實現的主要文件。為了弄清楚系統調用,首先應該拿一個實例來看。
WinixJ系統僅僅實現了一個系統調用getpid(),但是其他系統調用的框架應是完全相同的,只在函數實現細節上有所不同,因此我們打算以getpid()作為案例講解。
先看看getpid()呈現給用戶的調用接口吧:
POSIX規范的getpid()聲明如下:
pid_t getpid();等同于int getpid();為了簡單起見我們就實現為int getpid();
它的代碼也十分簡單:

 1 int getpid()
 2 {
 3     int res;
 4     __asm__ __volatile__ (
 5             "movl $0x0, %%eax\n\t"
 6             "movl $0x0, %%ebx\n\t"
 7             "movl $0x0, %%ecx\n\t"
 8             "movl $0x0, %%edx\n\t"
 9             "int $0x30\n"
10             :"=a" (res)
11             :);
12     return res;
13 }
14 

雖然有嵌入匯編,但是也不難理解,看似是將eax、ebx、ecx、edx四個寄存器均傳值為0,然后調用軟中斷int 0x30(實際上應該稱之為陷阱,陷阱和中斷還是有細微區別的,見此博文),最后將返回的結果由eax賦值給res變量。很簡單,不是嗎?
但是為何eax、ebx、ecx、edx都賦值了呢?調用int 0x30之后又發生什么了呢?
先說調用int 0x30之后會發生的事情。我們看下面這段代碼,其實它在此博文已經出現過,就是sys_call函數的實現:

 1 ; 系統調用框架,系統調用采用0x30號中斷向量,利用int 0x30指令產
 2 ; 生一個軟中斷,之后便進入sys_call函數,該函數先調用save_all框
 3 ; 架保存所有寄存器值,然后調用對應系統調用號的入口函數完成系統調用
 4 ; 注意!?。。。∠到y調用默認有三個參數,分別利用ebx、ecx、edx來
 5 ; 傳遞,其中eax保存系統調用號
 6 sys_call:
 7     save_all
 8 
 9     sti
10 
11     push ebx
12     push ecx
13     push edx
14     call [sys_call_table + eax * 4]
15     add esp, 4 * 3
16 
17     recover_from_sys_call
18 
19     cli
20 
21     iretd
22 

再看看save_all:

 1 ; 一個宏,因為所有的irq中斷函數以及系統調用都是先保存現場并將數據段等堆棧段
 2 ; 切換到內核態,因此,該操作所有的irq中斷入口函數均相同
 3 ; 故寫成宏節省空間
 4 %macro save_all 0
 5     push eax
 6     push ecx
 7     push edx
 8     push ebx
 9     push ebp
10     push esi
11     push edi
12     push ds
13     push es
14     push fs
15     push gs
16     mov si, ss
17     mov ds, si
18     mov es, si
19     mov gs, si
20     mov fs, si
21 %endmacro
22 

有了這一段代碼再說int 0x30后都發生了什么就比較簡單了,首先和發生時鐘中斷等硬件中斷類似,發生陷阱的時候CPU同樣先從當前進程對應的TSS段中找到SS0和ESP0,然后將當前進程的SS/ESP/EFLAGS/CS/EIP五個寄存器值壓入SS0:ESP0,然后再去執行save_all的代碼,save_all同樣是將所有的常規寄存器壓入堆棧,這樣一個過程之后就完成了從用戶態到內核態的切換,之后再看sys_call代碼,壓入三個寄存器作為形參,然后調用sys_call_table[eax * 4]函數。到這兒肯定就明白了,原來getpid()函數是通過四個通用寄存器來向內核態的系統調用函數傳遞參數的,這樣做是為了快捷。
還有一點就是install_sys_call_handler和install_sys_call兩個函數功能是不同的,說白了,WinixJ就只有一個系統調用,sys_call,它是所有POSIX規定的系統調用的框架,所有系統調用的實現都在sys_call_table[]函數數組里。這樣,將getpid()作為第0號系統調用的意思就是將sys_call_table[0] = sys_call_getpid();然后getpid()函數在發生陷阱的時候會通過eax傳入系統調用號0,這樣在sys_call中就會調用sys_call_table[eax * 4],即sys_call_table[0],即sys_call_getpid();  而install_sys_call_handler函數的作用是將IDT中0x30這一中斷描述符項設置成DPL = 3的陷阱門,該陷阱門的入口為sys_call,這樣,當用戶程序調用int 0x30的時候就會調用sys_call;而install_sys_call的作用是將getpid()函數與第0號系統調用對應起來,即完成這一工作:sys_call_table[0] = sys_call_getpid();這樣,當通過eax = 0傳入sys_call中時,sys_call知道需要調用sys_call_table[]中的第幾個函數指針。
到此基本就明白了,還有最后一個細節:為什么在系統調用完成后返回的時候不使用所有中斷返回時都使用的宏recover_all,而使用recover_from_sys_call?我們看看代碼:

 1 ; 一個宏,恢復現場
 2 %macro recover_all 0
 3     pop gs
 4     pop fs
 5     pop es
 6     pop ds
 7     pop edi
 8     pop esi
 9     pop ebp
10     pop ebx
11     pop edx
12     pop ecx
13     pop eax
14 %endmacro
15 
16 ; 注意從系統調用返回時不需要從棧中彈出eax的值,因為eax保存著調用
17 ; 對應系統調用之后的返回值
18 %macro recover_from_sys_call 0
19     pop gs
20     pop fs
21     pop es
22     pop ds
23     pop edi
24     pop esi
25     pop ebp
26     pop ebx
27     pop edx
28     pop ecx
29     add esp, 4 * 1
30 %endmacro

仔細研究代碼應該已經明白了,其實getpid()是需要返回值的,恰好我們就使用eax作為返回值,這樣,在從堆棧中恢復現場的時候就不能將eax的值恢復,因為eax還需要傳遞返回值。
至此,所有的系統調用細節應該明白了,這里只是講述的一種系統調用的實現,而有些操作系統的系統調用采用完全不同的風格實現的,它沒有sys_call_table[]這樣的函數數組,而是將每個系統調用都設置成一個陷阱門,在IDT中都占有一個描述符項,至于優劣,其實沒有大的差別。WinixJ使用的方法正是Linux的方法。在此向Linus和Linux致敬。
posted on 2012-02-14 15:41 myjfm 閱讀(542) 評論(0)  編輯 收藏 引用 所屬分類: 操作系統
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品视频va| 羞羞色国产精品| 亚洲精品一区二区三区蜜桃久| 亚洲欧美制服中文字幕| 亚洲高清久久| 国产精品地址| 欧美理论视频| 亚洲无吗在线| 亚洲欧美日韩中文在线制服| 日韩视频在线免费观看| 一区二区三区三区在线| 一区二区三区日韩精品| 亚洲无亚洲人成网站77777| 亚洲宅男天堂在线观看无病毒| 亚洲午夜一区| 久久蜜桃香蕉精品一区二区三区| 亚洲影院免费| 免费h精品视频在线播放| 国产精品综合不卡av| 韩国女主播一区二区三区| 亚洲国产cao| 亚洲最新在线视频| 久久久www成人免费毛片麻豆| 久久免费高清| 国产精品99久久99久久久二8| 亚洲欧美一区二区三区极速播放 | 欧美电影电视剧在线观看| 欧美精品在线播放| 亚洲大片在线| 狠狠干狠狠久久| 国产偷久久久精品专区| 日韩一级欧洲| 欧美粗暴jizz性欧美20| 亚洲欧美制服另类日韩| 欧美日本一区二区视频在线观看| 国产一区二区三区四区在线观看| 亚洲精品欧美极品| 久久精品在线免费观看| 亚洲视频免费在线| 欧美激情综合在线| 亚洲黄色三级| 91久久久亚洲精品| 裸体丰满少妇做受久久99精品| 国产精品丝袜xxxxxxx| 午夜视频精品| 国产婷婷色一区二区三区在线| 亚洲午夜伦理| 香蕉国产精品偷在线观看不卡| 欧美激情在线观看| 欧美粗暴jizz性欧美20| 在线视频一区观看| 亚洲欧美美女| 18成人免费观看视频| 亚洲久久成人| 国产精品一区二区在线观看不卡| 午夜综合激情| 嫩草影视亚洲| 伊人成人网在线看| 亚洲经典自拍| 国产一区二区欧美日韩| 男人插女人欧美| 亚洲高清色综合| 欧美日韩精品一区二区三区四区| 一区二区三区www| 亚洲欧美日韩精品| 9l国产精品久久久久麻豆| 国内激情久久| 欧美凹凸一区二区三区视频| 欧美精品久久久久久久久老牛影院| 亚洲性视频网站| 久久嫩草精品久久久精品| 亚洲欧美国产视频| 欧美电影资源| 男女av一区三区二区色多| 欧美涩涩视频| 亚洲激情网站| 亚洲美女福利视频网站| 久久婷婷人人澡人人喊人人爽| 亚洲欧美日韩一区二区三区在线| 欧美成人乱码一区二区三区| 欧美黑人一区二区三区| 亚洲破处大片| 欧美日韩高清区| av成人动漫| 国产精品看片资源| 亚洲伦伦在线| 欧美亚洲日本国产| 国产日本欧美一区二区三区在线| 日韩亚洲视频| 久久九九99视频| 亚洲国产第一页| 欧美日韩国产首页在线观看| 亚洲免费电影在线观看| 亚洲自拍啪啪| 国产精品激情偷乱一区二区∴| 欧美一区二区三区四区夜夜大片 | 亚洲激情小视频| 欧美呦呦网站| 久久久精品久久久久| 亚洲第一网站| 国产精品少妇自拍| 看片网站欧美日韩| 亚洲伦理精品| 欧美成人69| 欧美亚洲自偷自偷| 亚洲三级影院| 黄色日韩在线| 国产日韩欧美| 国产精品一区二区女厕厕| 久久久久久尹人网香蕉| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 久久免费视频一区| 亚洲男同1069视频| 一区二区欧美在线| 亚洲精品日韩精品| 91久久精品一区二区三区| 狠狠色香婷婷久久亚洲精品| 国产美女诱惑一区二区| 欧美好骚综合网| 久久天堂国产精品| 久久在线播放| 免费观看欧美在线视频的网站| 亚洲一区二区三| 99精品欧美一区| 亚洲一级在线观看| 在线观看欧美日韩| 欧美激情一区二区三级高清视频 | 久久精品人人做人人爽电影蜜月| 亚洲香蕉视频| 久久疯狂做爰流白浆xx| 欧美 日韩 国产在线 | 999亚洲国产精| 亚洲一级免费视频| 小黄鸭视频精品导航| 久久伊人一区二区| 欧美日本国产一区| 国产精品日韩二区| 欧美日韩免费在线视频| 国产精品久久久久毛片大屁完整版| 国产日韩精品在线播放| 亚洲毛片在线观看| 欧美一激情一区二区三区| 亚洲国产精品黑人久久久| 亚洲影院色无极综合| 欧美成人精品一区二区三区| 国产精品腿扒开做爽爽爽挤奶网站| 极品尤物久久久av免费看| 亚洲欧美日韩成人高清在线一区| 看欧美日韩国产| 欧美一级视频精品观看| 欧美色图麻豆| 一本一本a久久| 亚洲国产成人91精品| 久久久久久亚洲精品中文字幕| 国产精品盗摄一区二区三区| 亚洲精品免费一区二区三区| 国产精品你懂的| 午夜电影亚洲| 亚洲天堂av图片| 欧美国产日韩视频| 老色批av在线精品| 国产午夜精品视频免费不卡69堂| 99国产一区二区三精品乱码| 免费在线亚洲欧美| 玖玖在线精品| 日韩五码在线| 欧美色网一区二区| 欧美一区二区三区在线观看视频 | 亚洲日本成人网| 免费观看一区| 欧美伦理a级免费电影| 亚洲欧美日韩久久精品| 欧美一激情一区二区三区| 在线不卡视频| 亚洲美女黄网| 国产一区91精品张津瑜| 欧美风情在线观看| 欧美日本亚洲视频| 久久久精品国产免费观看同学| 欧美一级欧美一级在线播放| 好吊妞这里只有精品| 亚洲欧洲日产国产网站| 欧美日韩一区免费| 噜噜噜噜噜久久久久久91| 国产精品白丝jk黑袜喷水| 久久久久国色av免费看影院 | 午夜精品国产| 亚洲网站在线| 欧美电影打屁股sp| 久久久国产午夜精品| 欧美日韩在线观看一区二区| 日韩午夜在线播放| 欧美一区二区视频网站| 亚洲综合电影一区二区三区| 久久综合伊人77777蜜臀| 久久er精品视频| 国产精品视频免费在线观看| 99精品国产一区二区青青牛奶| **性色生活片久久毛片| 亚洲综合视频一区|