為系統(tǒng)內(nèi)核建立中斷機(jī)制

本章代碼有一定難度葱椭,請(qǐng)參看視頻獲得更詳細(xì)的代碼開發(fā)流程:
Linux kernel Hacker, 從零構(gòu)建自己的內(nèi)核

上一節(jié)鸿秆,我們繪制了鼠標(biāo)圖案,遺憾的是帚稠,鼠標(biāo)箭頭是死的谣旁,動(dòng)不了,要想讓鼠標(biāo)移動(dòng)滋早,我們需要為內(nèi)核建立中斷機(jī)制榄审。當(dāng)我們移動(dòng)鼠標(biāo)時(shí),鼠標(biāo)會(huì)給CPU發(fā)送信號(hào)杆麸,CPU接收到信號(hào)后搁进,終止當(dāng)前的運(yùn)算浪感,執(zhí)行內(nèi)核給定的代碼以處理鼠標(biāo)發(fā)送的信號(hào),在這段代碼中饼问,內(nèi)核根據(jù)鼠標(biāo)發(fā)送過來的相關(guān)信息篮撑,重新繪制鼠標(biāo)圖像,那么匆瓜,屏幕中的鼠標(biāo)就可以根據(jù)鼠標(biāo)硬件的挪動(dòng)而發(fā)送改變了赢笨。

這樣,我們就面臨兩個(gè)問題驮吱,一是鼠標(biāo)如何給CPU發(fā)送信號(hào)茧妒,二是CPU在接收信號(hào)后,怎么去執(zhí)行內(nèi)核提供的一段代碼左冬。我們先看第一個(gè)問題的處理桐筏,外設(shè)硬件要給CPU發(fā)送信號(hào),需要通過專門的處理芯片拇砰,這個(gè)芯片叫可編程控制器梅忌,俗稱8259A:

####****中斷信號(hào)的發(fā)送機(jī)制

這里寫圖片描述

從上圖可以得知,每一個(gè)8259A控制器有8根中斷信號(hào)線除破,總共可以接入15個(gè)外設(shè)硬件牧氮,一般情況下,鼠標(biāo)接入的是從8259A所對(duì)應(yīng)的IRQ4這根信號(hào)線瑰枫,鼠標(biāo)發(fā)送信號(hào)時(shí)踱葛,先通過管線IRQ4將信號(hào)傳遞到從8259A,然后通過管線IRQ2傳遞到主8259A,最后信號(hào)再傳遞給CPU,鍵盤產(chǎn)生的中斷通過主8259A的IRQ1管線向CPU發(fā)送信號(hào).

既然有硬件光坝,那就需要對(duì)其初始化后才能使用尸诽,對(duì)硬件的控制我們前面已經(jīng)說過,需要通過端口發(fā)送命令來完成盯另,要配置這兩個(gè)控制器性含,我們需要對(duì)指定端口發(fā)送1字節(jié)的數(shù)據(jù),這個(gè)一字節(jié)(8 bit)的數(shù)據(jù)鸳惯,我們稱之為ICW(initialization control word).主8259A對(duì)應(yīng)的端口地址是20h,21h, 從8259A對(duì)應(yīng)的端口是A0h和A1h. 對(duì)端口發(fā)送數(shù)據(jù)時(shí)商蕴,順序是定死的,不能違背:

  1. 往端口20h(主片)或A0h(從片)發(fā)送ICW1
  2. 往端口21h(主片)或A1h(從片)發(fā)送ICW2
  3. 往端口21h(主片)或A1h(從片)發(fā)送ICW3
  4. 往端口20h(主片)或A0h(從片)發(fā)送ICW4

接下來我們可以看看每個(gè)ICW的結(jié)構(gòu)和意義:
ICW1[0...7]:
ICW1[0] 設(shè)置為1表示需要發(fā)送ICW4,0表示不需要發(fā)送ICW4.
ICW1[1] 設(shè)置為1表示單個(gè)8259, 0表示級(jí)聯(lián)8259
ICW1[2] 設(shè)置為1表示4字節(jié)中斷向量悲敷,0表示8字節(jié)中斷向量
ICW1[3] 設(shè)置為1表示中斷形式是水平觸發(fā)究恤,0表示邊沿觸發(fā)
ICW1[4] 必須設(shè)置為1
ICW1[5,6,7] 必須設(shè)置為0

ICW2[0...7]:
ICW2[0,1,2] 對(duì)于80X86架構(gòu)必須設(shè)置為0
ICW2[3...7]: 80X86中斷向量

ICW3[0...7](主片):
ICW3[0] 設(shè)置為1, IR0級(jí)聯(lián)從片后德,0無從片
ICW3[1] 設(shè)置為1, IR1級(jí)聯(lián)從片抄腔,0無從片
ICW3[2] 設(shè)置為1瓢湃, IR2級(jí)聯(lián)從片理张,0無從片
ICW3[3] 設(shè)置為1, IR3級(jí)聯(lián)從片绵患,0無從片
ICW3[4] 設(shè)置為1雾叭, IR4級(jí)聯(lián)從片,0無從片
ICW3[5] 設(shè)置為1落蝙, IR5級(jí)聯(lián)從片织狐,0無從片
ICW3[6] 設(shè)置為1, IR6級(jí)聯(lián)從片筏勒,0無從片
ICW3[7] 設(shè)置為1移迫, IR7級(jí)聯(lián)從片,0無從片

ICW3[0...7](從片):
ICW3[0,1,2] 從片連接主片的IR號(hào)
ICw3[3...7] 必須是0

ICW4[0...7]:
ICW4[0] 設(shè)置為1管行,表示x86模式厨埋,0表示MCS 80/85模式
ICW4[1] 設(shè)置為1,自動(dòng)EOI捐顷;0 正常EOI
ICW4[2,3] 表示主從緩沖模式
ICW4[4] 1表示SFNM模式; 0 sequential 模式
ICW4[5,6,7] 設(shè)置為0

上面一些概念大家可能不明白荡陷,不用擔(dān)心,繼續(xù)往下走迅涮,后面我再對(duì)應(yīng)解釋废赞。下面我們通過代碼配置兩個(gè)中斷控制器:
1: 先向主8259A發(fā)生ICW1:
mov al, 011h
out 02h, al

011h 對(duì)應(yīng)的二進(jìn)制是00010001,對(duì)應(yīng)ICW1的說明,由于ICW1[0]=1表示需要發(fā)送ICW4, ICW1[1] = 0,說明有級(jí)聯(lián)8259A(我們買來的電腦都是級(jí)聯(lián)的)叮姑,
ICW1[2] =0 表示用8字節(jié)來設(shè)置中斷向量號(hào)蛹头,ICW1[3]=0表示中斷形式是邊沿觸發(fā),ICW[4]必須設(shè)置為1戏溺,ICW[5,6,7]必須是0.

2: 向從8259A發(fā)送ICW1:
out A0h, al
3: 向主8259A發(fā)送ICW2:
mov al, 20h
out 021h, al

20h 分解成ICW2 是, ICW2[0,1,2] = 0, 這是強(qiáng)制要求的渣蜗,也就是ICW2的值不能是0x21,0x22之類,只要前三位不是0就不行旷祸,整個(gè)ICW2 = 0x20,這樣的話耕拷,當(dāng)主8259A對(duì)應(yīng)的IRQ0管線向CPU發(fā)送信號(hào)時(shí),CPU根據(jù)0x20這個(gè)值去查找要執(zhí)行的代碼托享,IRQ1管線向CPU發(fā)送信號(hào)時(shí)骚烧,CPU根據(jù)0x21這個(gè)值去查找要執(zhí)行的代碼,依次類推闰围。

4: 向從8259A發(fā)送ICW2:
mov al, 028h
out A1h, al

028h分解成ICW2是ICW[0,1,2]=0,這是強(qiáng)制要求赃绊,整個(gè)ICW2為0x28,表示當(dāng)從8259A的IRQ0管線發(fā)送信號(hào)時(shí)羡榴,CPU根據(jù)數(shù)據(jù)0x28去查找要執(zhí)行的代碼碧查,IRQ1管線發(fā)送信號(hào)時(shí),CPU根據(jù)數(shù)據(jù)0x29去查詢要執(zhí)行的代碼,以此類推忠售。

5: 向主8259A發(fā)送ICW3
mov al, 04h
out 21h, al

04h 分解成ICW3 相當(dāng)于ICW[2] = 1, 這表示從8259A通過主IRQ2管線連接到
主8259A控制器传惠,如上圖所示
6: 向從8259A 發(fā)送 ICW3
mov al, 02h
out Alh , al
根據(jù)從片的ICW3, 將02h對(duì)應(yīng)過來是, ICW[0,1,2] = 2, 表示當(dāng)前從片是從IRQ2管線接入主8259A芯片的稻扬,如上圖卦方。

7: 向主8259A發(fā)送ICW4:
mov al, 002h
out 021h, al

001h 對(duì)應(yīng)的ICW4為,ICW4[0]=1表示當(dāng)前CPU架構(gòu)師80X86泰佳,ICW4[1]=1表示自動(dòng)EOI, 如果這位設(shè)置成0的話盼砍,那么中斷響應(yīng)后,代碼要想繼續(xù)處理中斷逝她,就得主動(dòng)給CPU發(fā)送一個(gè)信號(hào)浇坐,如果設(shè)置成1,那么代碼不用主動(dòng)給CPU發(fā)送信號(hào)就可以再次處理中斷汽绢。

8: 向從8259A發(fā)送ICW4,原理同上:
out 0A1h, al

當(dāng)上面的配置完成后吗跋,我們還需要再向兩個(gè)芯片分別發(fā)送一個(gè)字節(jié),叫OCW(operation control word), 一個(gè)OCW是一字節(jié)數(shù)據(jù)宁昭,也就是8bit,每一bit設(shè)置作用是跌宛,當(dāng)OCW[i] = 1 時(shí),屏蔽對(duì)應(yīng)的IRQ(i)管線的信號(hào),例如OCW[0]=1, 那么IRQ0管線的信號(hào)將不會(huì)被CPU接收积仗,以此類推疆拘。配置代碼如下:

mov al, 11111101b
out 21h, al

表示CPU只接收主8259A, IRQ1管線發(fā)送的信號(hào),其他管線發(fā)送信號(hào)一概忽略寂曹,IRQ1對(duì)應(yīng)的是鍵盤產(chǎn)生的中斷哎迄。

mov al, 11111111b
out 0A1h, al

上面代碼使得CPU忽略所有來自從8259A芯片的信號(hào)。
當(dāng)我們移動(dòng)鼠標(biāo)時(shí)隆圆,鼠標(biāo)是通過從8259A的IRQ4管線向CPU發(fā)送信號(hào)漱挚。
綜合以上,我們得到的初始化代碼如下:

init8259A:
 init8259A:
     mov  al, 011h
     out  02h, al
     call io_delay
  
     out 0A0h, al
     call io_delay

     mov al, 020h
     out 021h, al
     call io_delay

     mov  al, 028h
     out  0A1h, al
     call io_delay

     mov  al, 004h
     out  021h, al
     call io_delay

     mov  al, 002h
     out  0A1h, al
     call io_delay

     mov  al, 002h
     out  021h, al
     call io_delay

     out  0A1h, al
     call io_delay

     mov  al, 11111101b;允許接收鍵盤中斷
     out  021h, al
     call io_delay

     mov  al, 11111111b
     out  0A1h, al
     call io_delay

     ret

io_delay:
     nop
     nop
     nop
     nop
     ret
  

####****中斷代碼的執(zhí)行機(jī)制
前面我們處理了硬件如何發(fā)送信號(hào)的問題渺氧,接下來旨涝,我們看看,當(dāng)CPU接收到信號(hào)后侣背,如何執(zhí)行內(nèi)核指定的代碼白华。要執(zhí)行相應(yīng)代碼,CPU必須知道代碼所在的內(nèi)存位置贩耐,這個(gè)信息是通過中斷描述符表來實(shí)現(xiàn)的弧腥,我們看看中斷描述符的數(shù)據(jù)結(jié)構(gòu):

struct GATE_DESCRIPTOR {
short offset_low;
short selector;
char dw_count;
char attribute;
short offset_high;
};

中斷描述符跟前面說到的全局描述符類似,也是用于描述內(nèi)存性質(zhì)的潮太,只不過它專門用于描述可執(zhí)行代碼所在的內(nèi)存管搪, offset_low 和 offset_high 合在一起作為中斷函數(shù)在代碼執(zhí)行段中的偏移,selector 用來指向全局描述符表中的某個(gè)描述符,中斷函數(shù)的代碼就處于該描述符所指向的段中抛蚤,dw_count設(shè)置為0台谢,attribute設(shè)置為08Eh寻狂,我們看看如何在內(nèi)核中加載中斷描述符表:

;Gate selecotor, offset, DCount, Attr
%macro Gate 4
  dw  (%2 & 0FFFFh)
  dw  %1
  dw  (%3 & 1Fh) | ((%4 << 8) & 0FF00h)
  dw  ((%2>>16) & 0FFFFh)
%endmacro

上面匯編代碼中岁经,%2對(duì)應(yīng)的是4字節(jié)的地址偏移,把地址偏移的低2字節(jié)放到中斷門的前兩字節(jié)蛇券,接下來的一字節(jié)是宏定義的第一個(gè)參數(shù)缀壤,是中斷代碼所在的代碼段的全局描述符,第三行設(shè)置中斷描述符的屬性纠亚,當(dāng)前寫死為08Eh,最后一行設(shè)置中斷代碼偏移的高二字節(jié)塘慕。

在內(nèi)核代碼里,當(dāng)全局描述符表加載到CPU后蒂胞,就是我們加載中斷描述符表的時(shí)機(jī)了图呢,首先我們要初始化一個(gè)中斷描述符:

LABEL_IDT:
%rep  255
    Gate  SelectorCode32, SpuriousHandler,0, DA_386IGate
%endrep

IdtLen  equ $ - LABEL_IDT
IdtPtr  dw  IdtLen - 1
        dd  0

上面代碼中,我們通過指令%rep 255 重復(fù)定義255個(gè)中斷描述符骗随,這么說來蛤织,CPU其實(shí)可以支持255種中斷,其中兩個(gè)8259A芯片的15個(gè)中斷信號(hào)就包含在255個(gè)中斷中鸿染,SpuriousHandler是中斷代碼的入口指蚜,我們把255個(gè)中斷的處理代碼都設(shè)置成SpuriousHandler,也就是無論哪個(gè)中斷發(fā)生,都調(diào)用這個(gè)函數(shù)來處理:

     xor   eax, eax
     mov   ax,  ds
     shl   eax, 4
     add   eax, LABEL_IDT
     mov   dword [IdtPtr + 2], eax
     lidt  [IdtPtr]

上面代碼跟以前我們加載全局描述符表是一樣的,由于加載全局描述符時(shí)我們使用指令cli關(guān)閉了中斷功能涨椒,因此我們需要回復(fù)中斷功能摊鸡,CPU才能相應(yīng)來自8259A芯片的信號(hào):

  [SECTION .s32]
     [BITS  32]
     LABEL_SEG_CODE32:
     ;initialize stack for c code
     mov  ax, SelectorStack
     mov  ss, ax
     mov  esp, TopOfStack

     mov  ax, SelectorVram
     mov  ds,  ax

     mov  ax, SelectorVideo
     mov  gs, ax

     sti
     %include "write_vga_desktop.asm"
    
     jmp  $

上面的代碼通過運(yùn)行指令sti 恢復(fù)中斷功能。最后再看看SpuriousHandler的實(shí)現(xiàn):

_SpuriousHandler:
SpuriousHandler  equ _SpuriousHandler - $$
call intHandlerFromC
iretd

當(dāng)點(diǎn)擊鍵盤蚕冬,引發(fā)中斷時(shí)免猾,_SpuriousHandler的代碼被調(diào)用,它又調(diào)用了C模塊實(shí)現(xiàn)的函數(shù)intHandlerFromC囤热。我們看看C語言怎么實(shí)現(xiàn)intHandlerFromC的:

void intHandlerFromC(char* esp) {
    char*vram = bootInfo.vgaRam;
    int xsize = bootInfo.screenX, ysize = bootInfo.screenY;
    boxfill8(vram, xsize, COL8_000000, 0,0,32*8 -1, 15);
    showString(vram, xsize, 0, 0, COL8_FFFFFF, "PS/2 keyboard"); 
    for (;;) {
        io_hlt();
    }
    show_char();
}

上面函數(shù)先繪制一個(gè)背景為黑色的矩形猎提,在矩形里用白色的字體顯示字符串"PS/2 keyboard"。當(dāng)上面的代碼編譯后赢乓,啟動(dòng)虛擬機(jī)加載內(nèi)核忧侧,初始畫面如下:


這里寫圖片描述

然后隨便點(diǎn)擊鍵盤一個(gè)按鈕,結(jié)果如下:


這里寫圖片描述

可見牌芋,我們中斷機(jī)制的設(shè)置完全正確蚓炬,CPU能夠接收8259A芯片,同時(shí)CPU能夠正確的執(zhí)行內(nèi)核提交的中斷處理函數(shù)躺屁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肯夏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驯击,老刑警劉巖烁兰,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異徊都,居然都是意外死亡沪斟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門暇矫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來主之,“玉大人,你說我怎么就攤上這事李根〔坜龋” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵房轿,是天一觀的道長(zhǎng)粤攒。 經(jīng)常有香客問我,道長(zhǎng)囱持,這世上最難降的妖魔是什么夯接? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮洪唐,結(jié)果婚禮上钻蹬,老公的妹妹穿的比我還像新娘。我一直安慰自己凭需,他們只是感情好问欠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粒蜈,像睡著了一般顺献。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枯怖,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天注整,我揣著相機(jī)與錄音,去河邊找鬼度硝。 笑死肿轨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蕊程。 我是一名探鬼主播椒袍,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼藻茂!你這毒婦竟也來了驹暑?” 一聲冷哼從身側(cè)響起玫恳,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎优俘,沒想到半個(gè)月后京办,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帆焕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年惭婿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片视搏。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡审孽,死狀恐怖县袱,靈堂內(nèi)的尸體忽然破棺而出浑娜,到底是詐尸還是另有隱情,我是刑警寧澤式散,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布筋遭,位于F島的核電站,受9級(jí)特大地震影響暴拄,放射性物質(zhì)發(fā)生泄漏漓滔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一乖篷、第九天 我趴在偏房一處隱蔽的房頂上張望响驴。 院中可真熱鬧,春花似錦撕蔼、人聲如沸豁鲤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琳骡。三九已至,卻和暖如春讼溺,著一層夾襖步出監(jiān)牢的瞬間楣号,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工怒坯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留炫狱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓剔猿,卻偏偏與公主長(zhǎng)得像视译,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艳馒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 8086匯編 本筆記是筆者觀看小甲魚老師(魚C論壇)《零基礎(chǔ)入門學(xué)習(xí)匯編語言》系列視頻的筆記,在此感謝他和像他一樣...
    Gibbs基閱讀 37,218評(píng)論 8 114
  • 1 中斷介紹 1.1 簡(jiǎn)介 中斷控制是計(jì)算機(jī)發(fā)展中一種重要的技術(shù)别威。最初它是為克服對(duì)I/O接口控制采用程序查詢所帶來...
    瘋狂小王子閱讀 8,081評(píng)論 0 9
  • 從本質(zhì)上講躯舔,中斷(硬)是一種電信號(hào),當(dāng)設(shè)備有某種事情發(fā)生的時(shí)候省古,他就會(huì)產(chǎn)生中斷粥庄,通過總線把電信號(hào)發(fā)送給中斷控制器。...
    Joe_HUST閱讀 22,716評(píng)論 0 10
  • “改天請(qǐng)你吃飯训堆!” “改天再說!” “改天我們好好聚一聚白嘁!” “改天我一定去坑鱼!” 很多事情被安排在了改天里,一個(gè)改...
    魔線科技閱讀 591評(píng)論 0 2
  • 可以說是面向切面編程的典范了絮缅。1 aspect修改原來的類通過消息轉(zhuǎn)發(fā)實(shí)現(xiàn)回調(diào)2 這三個(gè)哥們是集合鲁沥,但是無論怎么搞...
    事件_666閱讀 327評(píng)論 0 0