posts - 403, comments - 310, trackbacks - 0, articles - 7
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          發(fā)信人: Zellux (null), 信區(qū): Software_06
          標(biāo) 題: OSLab之中斷處理
          發(fā)信站: 日月光華 (2008年08月30日20:15:58 星期六), 站內(nèi)信件

          1. 準(zhǔn)備工作
          在開(kāi)始分析Support Code之前,先配置下我們的Source Insight,使它能夠支持.s文件的搜索。

          在Options->Document Options->Document Types中選擇x86 Asm Source File,在File fileter中增加一個(gè)*.s,變成*.asm;*.inc;*.s 然后在Project->Add and Remove
          Project Files中重新將整個(gè)oslab的目錄加入,這樣以后進(jìn)行文本搜索時(shí).s文件也不會(huì)漏掉了。

          2. Source Insight使用
          接下來(lái)簡(jiǎn)單分析下內(nèi)核啟動(dòng)的過(guò)程,在瀏覽代碼的過(guò)程中可以迅速的掌握Source Insight的使用技巧。

          lib/multiboot /multiboot.s完成了初始化工作,可以看到其中一句call
          EXT(multiboot_main)調(diào)用了C函數(shù)multiboot_main,使用ctrl+/搜索包含multiboot_main的所有文件,最終base_multiboot_main.c中找到了它的定義。依次進(jìn)行cpu、內(nèi)存的初
          始化,然后開(kāi)啟中斷,跳轉(zhuǎn)到kernel_main函數(shù),也是Lab1中所要改寫(xiě)的函數(shù)之一。另外
          在這里可以通過(guò)ctrl+單擊或者ctrl+=跳轉(zhuǎn)到相應(yīng)的函數(shù)定義處,很方便。

          3. irq處理初始化工作
          來(lái)看下Lab 1的重點(diǎn)之一,irq的處理。跟蹤multiboot_main->base_cpu_setup->base_cp
          u_init->base_irq_init,可以看到這行代碼
          gate_init(base_idt, base_irq_inittab, KERNEL_CS);
          繼續(xù)使用ctrl+/找到base_irq_inittab的藏身之處:base_irq_inittab.s

          4. base_irq_inittab.s
          這個(gè)匯編文件做了不少重復(fù)性工作,方便我們?cè)赾語(yǔ)言級(jí)別實(shí)現(xiàn)各種handler。
          GATE_INITTAB_BEGIN(base_irq_inittab) /* irq處理函數(shù)表的起始,還記得jump
          table 嗎? */
          MASTER(0, 0) /* irq0 對(duì)應(yīng)的函數(shù) */


          來(lái)看看這個(gè)MASTER(0, 0)宏展開(kāi)后是什么樣子:
          #define MASTER(irq, num) \
          GATE_ENTRY(BASE_IRQ_MASTER_BASE + (num), 0f, ACC_PL_K|ACC_INTR_GATE) ;\
          P2ALIGN(TEXT_ALIGN) ;\
          0: ;\
          pushl $(irq) /* error code = irq vector */ ;\
          pushl $BASE_IRQ_MASTER_BASE + (num) /* trap number */ ;\
          pusha /* save general registers */ ;\
          movl $(irq),%ecx /* irq vector number */ ;\
          movb $1 << num,%dl /* pic mask for this irq */ ;\
          jmp master_ints

          依次push irq號(hào),trap號(hào)(0x20+irq號(hào)),通用寄存器(eax ecx等)入棧,把irq號(hào)保
          存到ecx寄存器,然后跳轉(zhuǎn)到master_ints,master_ints是所有master interrupts公用
          的代碼。

          跳過(guò)master_ints的前幾行,從第七行開(kāi)始
          /* Acknowledge the interrupt */
          movb $0x20,%al
          outb %al,$0x20

          /* Save the rest of the standard trap frame (oskit/x86/base_trap.h). */
          pushl %ds
          pushl %es
          pushl %fs
          pushl %gs

          /* Load the kernel's segment registers. */
          movw %ss,%dx
          movw %dx,%ds
          movw %dx,%es

          /* Increment the hardware interrupt nesting counter */
          incb EXT(base_irq_nest)

          /* Load the handler vector */
          movl EXT(base_irq_handlers)(,%ecx,4),%esi

          注釋寫(xiě)得很詳細(xì),首先發(fā)送0x20到0x20端口,也就是Lab1文檔上所說(shuō)的發(fā)送INT_CTL_DON
          E到INT_CTL_REG,看來(lái)這一步support code已經(jīng)替我們完成了。接下來(lái)保存四個(gè)段寄存
          器ds es fs gs,并讀入kernel態(tài)的段寄存器信息。

          最后一句很關(guān)鍵,把base_irq_handlers + %ecx * 4這個(gè)值保存到了esi寄存器中,%ecx
          中保存了irq號(hào),而*4則是一個(gè)函數(shù)指針的大小,那么base_irq_handlers是什么呢?繼
          續(xù)用ctrl+/搜索,可以在base_irq.c中找到這個(gè)數(shù)組的定義
          unsigned int (*base_irq_handlers[BASE_IRQ_COUNT])(struct trap_state *ts)
          且初始時(shí)這個(gè)數(shù)組的每一項(xiàng)都是base_irq_default_handler

          看來(lái)這句匯編代碼的功能是把處理irq對(duì)應(yīng)的函數(shù)地址保存到了esi寄存器中。
          為了證實(shí)這一點(diǎn),繼續(xù)看base_irq_inittab.s的代碼:
          #else
          /* Call the interrupt handler with the trap frame as a parameter */
          pushl %esp
          call *%esi
          popl %edx
          #endif
          果然,在保存了esp值后,緊接著就調(diào)用了esi指向的那個(gè)函數(shù)。而從那個(gè)函數(shù)返回后,
          之前在棧上保存的相關(guān)信息都被恢復(fù)了:

          /* blah blah blah */
          /* Return from the interrupt */
          popl %gs
          popl %fs
          popl %es
          popl %ds
          popa
          addl $4*2,%esp /* Pop trap number and error code */
          iret
          這樣就恢復(fù)到了進(jìn)入這個(gè)irq處理單元前的狀態(tài),文檔中所要求的保存通用寄存器這一步
          其實(shí)在這里也已經(jīng)完成了,不需要我們自己寫(xiě)代碼。

          好了,這樣一分析后,我們要做的事情就很簡(jiǎn)單,就是把base_irq_handlers數(shù)組中的對(duì)
          應(yīng)項(xiàng)改成相應(yīng)的handler函數(shù)就行了。
          注意index是相應(yīng)的idt_entry號(hào)減去BASE_IRQ_SLAVE_BASE,或者直接使用IRQ號(hào)。

          另外這個(gè)數(shù)組的初始值都是base_irq_default_handler,用ctrl+左鍵跳到這個(gè)函數(shù)的定
          義,可以看到這個(gè)函數(shù)只有一句簡(jiǎn)單的輸出語(yǔ)句:
          printf("Unexpected interrupt %d\n", ts->err);
          而這就是沒(méi)有注冊(cè)handler前我們所看到的那句Unexpected interrupt 0的來(lái)源了。

          5. struct trap_state *ts
          所有的handler函數(shù)的參數(shù)都是一個(gè)struct trap_state *ts,這個(gè)參數(shù)是哪來(lái)的呢?
          注意call *%esi的前一行
          /* Call the interrupt handler with the trap frame as a parameter */
          pushl %esp
          這里把當(dāng)前的esp當(dāng)作指向ts的指針傳給了handler,列一下從esp指向的地址開(kāi)始的內(nèi)容
          ,也就是在此之前push入棧的內(nèi)容:

          pushl $(irq) /* error code = irq vector */ ;\
          pushl $BASE_IRQ_MASTER_BASE + (num) /* trap number */ ;\
          pusha /* save general registers */ ;\
          pushl %ds
          pushl %es
          pushl %fs
          pushl %gs

          再看一下trap_state的定義,你會(huì)發(fā)現(xiàn)正好和push的順序相反:
          /* Saved segment registers */
          unsigned int gs;
          unsigned int fs;
          unsigned int es;
          unsigned int ds;

          /* PUSHA register state frame */
          unsigned int edi;
          unsigned int esi;
          unsigned int ebp;
          unsigned int cr2; /* we save cr2 over esp for page faults */
          unsigned int ebx;
          unsigned int edx;
          unsigned int ecx;
          unsigned int eax;

          /* Processor trap number, 0-31. */
          unsigned int trapno;

          /* Error code pushed by the processor, 0 if none. */
          unsigned int err;

          而這個(gè)定義后面的
          /* Processor state frame */
          unsigned int eip;
          unsigned int cs;
          unsigned int eflags;
          unsigned int esp;
          unsigned int ss;
          則是發(fā)生interrupt時(shí)硬件自動(dòng)push的五個(gè)數(shù)據(jù)(參見(jiàn)Understand the Linux Kernel)

          也就是說(shuō),ts指針指向的是調(diào)用當(dāng)前handler前的寄存器狀態(tài),也是當(dāng)前handler結(jié)束后
          用來(lái)恢復(fù)的寄存器狀態(tài),了解這一點(diǎn)對(duì)以后的幾個(gè)lab幫助很大。

          p.s. 另外提一句和這個(gè)lab無(wú)關(guān)的話,非vm86模式下棧上是不會(huì)有v86_es等四個(gè)寄存器
          信息的,所以以后根據(jù)task_struct指針計(jì)算*ts的地址時(shí)使用的偏移量不應(yīng)該是sizeof(
          struct trap_state)

          6. The End
          這樣差不多就把support code中處理interrupt的方法過(guò)了一遍(另外還有base_trap_in
          ittab.s,不過(guò)和irq的處理很相似)

          了解這些后Lab1就比較簡(jiǎn)單了,不需要任何內(nèi)嵌匯編代碼即可完成。

          posted @ 2008-09-02 11:55 ZelluX 閱讀(647) | 評(píng)論 (5)編輯 收藏

               摘要: 美國(guó)為什么需要這么多大學(xué)生,而中國(guó)培育出這么多優(yōu)秀大學(xué)生為什么失業(yè)?難道是我們學(xué)生程度不夠?難道是我們同學(xué)不夠用功?難道是我們同學(xué)專業(yè)不對(duì)口?那我告訴所有讀者,為什么大學(xué)生就業(yè)難……   閱讀全文

          posted @ 2008-07-28 11:31 ZelluX 閱讀(687) | 評(píng)論 (5)編輯 收藏

          用ctags -R或者ctags * -R的時(shí)候只能生成當(dāng)前目錄下的tag,檢查了半天發(fā)現(xiàn)原來(lái)這個(gè)版本的ctags的參數(shù)順序只能老老實(shí)實(shí)的來(lái):ctags -R *

          太囧了,總歸要bs下的,雖說(shuō)也有那么一點(diǎn)點(diǎn)可能是bash解析參數(shù)時(shí)的問(wèn)題,不過(guò)我猜問(wèn)題來(lái)源還是這個(gè)低版本的ctags = =

          話說(shuō)我也挺圡的,不習(xí)慣用source insight,還是喜歡用vim寫(xiě)代碼

          posted @ 2008-07-15 10:41 ZelluX 閱讀(553) | 評(píng)論 (3)編輯 收藏

          沒(méi)心思看離散,也不準(zhǔn)備堅(jiān)持看沒(méi)有荷蘭的歐洲杯決賽。閑著點(diǎn)好友的Q-Zone,原來(lái)Q-Zone首先會(huì)判斷你的瀏覽器,如果是Firefox它會(huì)重定向到RSS閱讀界面。

          安然在開(kāi)學(xué)后2個(gè)月寫(xiě)的一篇日志,“記憶里的名單”,驚喜的看到有我。也列出了一張屬于我的名單。好,等待時(shí)間的遴選。

          “于是想 如果有個(gè)妹妹 我要告訴她 好好放肆猖狂 做不可思議的事情 為友情和少年青澀的愛(ài)情花心思 做只是喜歡沒(méi)有功利目的的事情 這么好的年華 就是用來(lái)這樣浪費(fèi) 和珍惜的~”

          可惜我只保持了四五個(gè)月的這種瘋狂,現(xiàn)在依然糾結(jié)于功利的選擇。有時(shí)候曾想,或許那次失敗更適合我,或許我終將把這么一條平淡無(wú)奇的路走到盡頭。“表面強(qiáng)者”,或許還是很有道理的。

          看到fofo的博的文字,“我要去杭州,把所有的事情拋掉,不管后果。這個(gè)地方太讓人壓抑,盡管有很玩得來(lái)的室友,有很好的足球隊(duì)的隊(duì)友,可以看很多以前爸媽不讓看的喜歡的書(shū)還有過(guò)米的比賽,吃的東西也都很習(xí)慣,還是會(huì)在天氣很好的星期天下午突然想起曾經(jīng)在冬日的陽(yáng)光照射下一家人在陽(yáng)臺(tái)上圍著一張桌子吃飯的情景,還是會(huì)在一個(gè)人騎在去計(jì)算機(jī)協(xié)會(huì)的路上很難過(guò)地想著再也不會(huì)有那么四個(gè)或者五個(gè)人在一起吃完小炒放肆地在鋪滿夕陽(yáng)的校園小路上勾肩搭背地行走了,還是會(huì)在一百多個(gè)人的課堂上懷念起那些艱苦卻簡(jiǎn)單的日子里所有的笑聲,還是會(huì)在網(wǎng)吧包夜的時(shí)候想起初中時(shí)捏著飯錢(qián)偷偷摸摸地去電腦房玩星際……想找找朋友們,調(diào)整一下自己的心情。”

          真的找不回來(lái)了。在寫(xiě)這篇博文時(shí)也找不到以前寫(xiě)字的感覺(jué)了。

          明天離散考試,某個(gè)記錄或許將要因此打破。

          posted @ 2008-06-30 02:09 ZelluX 閱讀(379) | 評(píng)論 (1)編輯 收藏

          不枉我周末練了那么多ZvP

          不過(guò)總比分太慘了。。

          posted @ 2008-06-24 00:20 ZelluX 閱讀(411) | 評(píng)論 (0)編輯 收藏

               摘要: 一篇關(guān)于函數(shù)式編程的介紹,在水木Java版引起了熱烈討論。  閱讀全文

          posted @ 2008-06-05 21:10 ZelluX 閱讀(772) | 評(píng)論 (1)編輯 收藏

          1. framwork/policies/Singleton.h
          Singleton模式,可以指定相應(yīng)的線程模型、創(chuàng)建策略和生命期控制策略。
          對(duì)于全局范圍的Singleton實(shí)例,定義了若干個(gè)宏便于訪問(wèn),例如
          #define?sLog?MaNGOS::Singleton<Log>::Instance()
          #define?sMaster?MaNGOS::Singleton<Master>::Instance()

          Singleton的定義:


          不知道這里的注釋Prohibited actions...this does not prevent hijacking.是什么意思,copy constructor和hijacking有什么關(guān)系呢?

          另外注意這行typedef typename ThreadingModel::Lock Guard;,原來(lái)typedef還可以用在函數(shù)上。

          Singleton的Instance方法用的是標(biāo)準(zhǔn)的double-checked lock方法,關(guān)于DCL可以參考這篇博文http://www.aygfsteel.com/zellux/archive/2008/04/07/191365.html

          2. Explicit Constructors
          game/WorkPacket.h中看到的語(yǔ)法,防止構(gòu)造函數(shù)中參數(shù)的隱式轉(zhuǎn)型
          比如explicit String(int n); 用String('c')聲明時(shí)就會(huì)報(bào)錯(cuò)

          posted @ 2008-06-03 19:03 ZelluX 閱讀(783) | 評(píng)論 (0)編輯 收藏

          一套基于文件系統(tǒng)的安全方案,主要通過(guò)隔離運(yùn)行不可信任的程序、taint記錄、事故恢復(fù)。

          我的presentation:
          http://docs.google.com/Presentation?id=dcjk4xx7_473cv5ddgc8

          出于時(shí)間考慮沒(méi)有提到paper中進(jìn)程間通信的解決方法

          posted @ 2008-05-28 15:23 ZelluX 閱讀(518) | 評(píng)論 (0)編輯 收藏

          水木上有人貼了個(gè)有趣的程序

          #include? < stdlib.h >
          #include?
          < stdio.h >

          void ?print_forever( int ?n)
          {
          ????printf(
          " %d\n " ,?n);
          ????print_forever(n?
          + ? 1 );
          }


          int ?main( int ?argc,? char ? * argv[])
          {
          ????print_forever(
          0 );
          ????
          return ? 0 ;
          }


          用gcc -O2編譯運(yùn)行后會(huì)不停地打印從0開(kāi)始的自然數(shù),注意如果編譯器沒(méi)有做優(yōu)化的話,打印到某個(gè)數(shù)的時(shí)候肯定會(huì)發(fā)生棧溢出從而程序終止的情況,但這個(gè)程序卻能一直運(yùn)行下去,說(shuō)明編譯器做了尾遞歸優(yōu)化。

          用gcc -O2 -S生成這個(gè)程序的匯編代碼后證實(shí)了這一點(diǎn)。
          .L6:
          ????????movl????
          %ebx,?4(%esp)
          ????????addl????$
          1,?%ebx
          ????????movl????$.LC0,?(
          %esp)
          ????????call????printf
          ????????jmp?????.L6
          print_forever的關(guān)鍵部分被優(yōu)化成了一個(gè)n不斷增加的死循環(huán)。

          接下來(lái)是分析哪個(gè)優(yōu)化選項(xiàng)處理了尾遞歸。

          用O3 O2 O1三個(gè)優(yōu)化強(qiáng)度編譯程序,查看匯編代碼后,發(fā)現(xiàn)尾遞歸優(yōu)化是O2中新增的功能。于是查看O2新開(kāi)啟的優(yōu)化開(kāi)關(guān):
          gcc -c -Q -O1 --help=optimizers > /tmp/O1-opts
          gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts
          diff /tmp/O2-opts /tmp/O1-opts?| grep enabled
          輸出結(jié)果:

          經(jīng)證實(shí)是-foptimize-sibling-calls這個(gè)選項(xiàng)實(shí)現(xiàn)了尾遞歸的優(yōu)化,具體內(nèi)容可以參看
          http://gcc.gnu.org./ml/gcc-patches/2000-03/msg00867.html

          posted @ 2008-05-24 02:05 ZelluX 閱讀(2453) | 評(píng)論 (1)編輯 收藏

          睡覺(jué)去恩

          P.S 點(diǎn)球真不是人看的

          posted @ 2008-05-22 05:44 ZelluX 閱讀(454) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題
          共39頁(yè): 上一頁(yè) 1 2 3 4 5 6 7 8 9 下一頁(yè) Last 
          主站蜘蛛池模板: 南丰县| 沙雅县| 扶绥县| 凤阳县| 句容市| 福泉市| 公主岭市| 政和县| 澄城县| 阿拉善左旗| 安丘市| 宝兴县| 澄江县| 偏关县| 壶关县| 阿拉善左旗| 邳州市| 威海市| 安庆市| 阿荣旗| 广宗县| 兴海县| 日土县| 威海市| 新巴尔虎右旗| 常州市| 布拖县| 瑞昌市| 清河县| 汉源县| 如东县| 巩留县| 济源市| 海原县| 长丰县| 韶关市| 博乐市| 平乡县| 休宁县| 治县。| 阳山县|