什么是中斷呢?我們可以先看看單片機下面是怎么做的。在我個人看來,中斷是cpu最重要的特色。從某種意義上來說,沒有中斷就沒有嵌入式操作系統(tǒng)。一旦你明白了中斷的真正含義,你對操作系統(tǒng)的了解就算真正入門了。
[cpp] view plaincopy #include <REG51.h>
sbit LED = P1 ^ 6;unsigned int led_enable = 0;
void Delay(unsigned int a)
{ unsigned int i;
while(a)
{ a ——;for(i = 0; i < 1200; i++);}
void led_switch(void) interrupt 0 using 1 { if(0 == led_enable)
{ led_enable = 1;} else { led_enable = 0;}
EX0 = 1;}
void main(void)
{ EA = 1;EX0 = 1;
while(1){ if(led_enable)
{ LED = 0;Delay(100);LED = 1;Delay(100);}上面的代碼是一段真實的51單片機代碼。它完成的功能很簡單,就是對led燈進行點亮處理。怎么解釋呢?在單片機上電后,我們發(fā)現(xiàn)一開始led二極管沒有發(fā)生閃爍。在我們單擊按鍵之后,led開始出現(xiàn)間隙性閃爍的現(xiàn)象,之后再一次單擊按鍵,又可以發(fā)現(xiàn)led的閃爍現(xiàn)象消失了。為什么會出現(xiàn)這種現(xiàn)象?主要是因為我們單擊按鍵的時候,在單片機的引腳處產(chǎn)生了中斷。查看到中斷的單片機此時就會跳轉到中斷向量表里面查找中斷處理函數(shù)。這里的按鍵中斷處理函數(shù)就是led_switch.處理完led_switch之后,單片機又會回到原來的main函數(shù)繼續(xù)執(zhí)行,所以整個中斷的過程就像沒有發(fā)生過一樣。因為在led_switch中我們對led_enable進行了處理,所以就出現(xiàn)了我們在前面說過的各種現(xiàn)象。
說到這,也許有的朋友會說,cpu的這種中斷屬性怎么才能在pc上面仿真出來呢?其實很簡單。linux
系統(tǒng)本身就有一個優(yōu)秀的特性,那就是信號。只要我們設定相應的信號和處理函數(shù),那么linux系統(tǒng)就會在系統(tǒng)調(diào)度返回之前調(diào)用相應的信號函數(shù)來處理。整個信號處理的過程和中斷是一模一樣的。因為在處理中斷的時候,我們需要對cpu的現(xiàn)場進行保存和恢復處理,而信號的處理也是一樣。在信號處理前,系統(tǒng)肯定是處于內(nèi)核態(tài),那么linux系統(tǒng)肯定已經(jīng)為我們做好了現(xiàn)場的保護工作,處理完信號之后,系統(tǒng)本身又會恢復到原來的用戶態(tài),繼續(xù)執(zhí)行下面的代碼。所以linux自身也會默認對原來的場景進行恢復處理,就好象中斷返回一樣。
[cpp] view plaincopy #include <stdio.h> #include <time.h> #include <sys/time.h> #include <stdlib.h> #include <signal.h>
static int count = 0;static struct itimerval oldtv;
void set_timer()
{ struct itimerval itv;itv.it_interval.tv_sec = 1;itv.it_interval.tv_usec = 0;itv.it_value.tv_sec = 1;itv.it_value.tv_usec = 0;setitimer(ITIMER_REAL, &itv, &oldtv);}
void signal_handler(int m)
{ count ++;printf("%d\n", count);}
int main()
{ signal(SIGALRM, signal_handler);set_timer();while(count < 10000);exit(0);return 1;}大家可以把這樣一段代碼在Linux編譯一下,然后使用gdb調(diào)試即可。查看整個signal_handler在被斷點斷住的時候,本身線程是不是只有一個?函數(shù)堆棧是不是在一個線程里面。如果不出意外,整個信號的處理過程應該是這樣的,[cpp] view plaincopy(gdb) bt #0 signal_handler(m=14) at code.c: 23 #1 <signal handler caller> #2 main() at code.c:32到了這里,相應大家應該還有一個疑問,既然可以利用linux的signal對cpu的中斷進行仿真,那么能不能利用windows的signal對中斷進行仿真呢。因為 Windows下面的沒有SIGALRM這個信號,所以我們可以重新編寫一段代碼,然后利用visual studio 6.0進行編譯,看看對應的情況。
[cpp] view plaincopy #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <tchar.h> #include <Windows.h>
void SignalHandler(int signal)
{ printf("Application over……\n");}
int main()
{ typedef void (*SignalHandlerPointer)(int);
SignalHandlerPointer previousHandler;previousHandler = signal(SIGINT, SignalHandler);while(1)
{ Sleep(0);}
exit(1);}下面,我們首先編譯這一段代碼。接著在程序run之后,我們可以在SignalHandler之處設置一個斷點。一切就緒完畢,再按下ctrl+c之后,系統(tǒng)就會在SignalHandler之處斷住。此時單擊「Debug」-> 「Threads」,就可以看到這個情況。
相信看到這里,大家應該看明白了。其實在Windows下面,信號是專門有一個線程來完成的,和原來的main函數(shù)不是同一個線程。既然線程都不是一樣的,而中斷本身是必須在一個thread中完成的。我們怎么能利用windows來仿真cpu的中斷處理流程呢。