?? system_call.s
字號:
pushl $ret_from_sys_call # 把下面調(diào)用返回的地址入棧。jmp _math_error # 執(zhí)行C 函數(shù)math_error()(kernel/math/math_emulate.c,37)#### int7 -- 設(shè)備不存在或協(xié)處理器不存在(Coprocessor not available)。# 如果控制寄存器CR0 的EM 標(biāo)志置位,則當(dāng)CPU 執(zhí)行一個ESC 轉(zhuǎn)義指令時就會引發(fā)該中斷,這樣就# 可以有機(jī)會讓這個中斷處理程序模擬ESC 轉(zhuǎn)義指令(169 行)。# CR0 的TS 標(biāo)志是在CPU 執(zhí)行任務(wù)轉(zhuǎn)換時設(shè)置的。TS 可以用來確定什么時候協(xié)處理器中的內(nèi)容(上下文)# 與CPU 正在執(zhí)行的任務(wù)不匹配了。當(dāng)CPU 在運(yùn)行一個轉(zhuǎn)義指令時發(fā)現(xiàn)TS 置位了,就會引發(fā)該中斷。# 此時就應(yīng)該恢復(fù)新任務(wù)的協(xié)處理器執(zhí)行狀態(tài)(165 行)。參見(kernel/sched.c,77)中的說明。# 該中斷最后將轉(zhuǎn)移到標(biāo)號ret_from_sys_call 處執(zhí)行下去(檢測并處理信號)。.align 2_device_not_available:push %dspush %espush %fspushl %edxpushl %ecxpushl %ebxpushl %eaxmovl $0x10,%eax # ds,es 置為指向內(nèi)核數(shù)據(jù)段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax # fs 置為指向局部數(shù)據(jù)段(出錯程序的數(shù)據(jù)段)。mov %ax,%fspushl $ret_from_sys_call # 把下面跳轉(zhuǎn)或調(diào)用的返回地址入棧。clts # clear TS so that we can use math5.5 system_call.s 程序movl %cr0,%eaxtestl $0x4,%eax # EM (math emulation bit)# 如果不是EM 引起的中斷,則恢復(fù)新任務(wù)協(xié)處理器狀態(tài),je _math_state_restore # 執(zhí)行C 函數(shù)math_state_restore()(kernel/sched.c,77)。pushl %ebppushl %esipushl %edicall _math_emulate # 調(diào)用C 函數(shù)math_emulate(kernel/math/math_emulate.c,18)。popl %edipopl %esipopl %ebpret # 這里的ret 將跳轉(zhuǎn)到ret_from_sys_call(101 行)。#### int32 -- (int 0x20) 時鐘中斷處理程序。中斷頻率被設(shè)置為100Hz(include/linux/sched.h,5),# 定時芯片8253/8254 是在(kernel/sched.c,406)處初始化的。因此這里jiffies 每10 毫秒加1。# 這段代碼將jiffies 增1,發(fā)送結(jié)束中斷指令給8259 控制器,然后用當(dāng)前特權(quán)級作為參數(shù)調(diào)用# C 函數(shù)do_timer(long CPL)。當(dāng)調(diào)用返回時轉(zhuǎn)去檢測并處理信號。.align 2_timer_interrupt:push %ds # save ds,es and put kernel data spacepush %es # into them. %fs is used by _system_callpush %fspushl %edx # we save %eax,%ecx,%edx as gcc doesn'tpushl %ecx # save those across function calls. %ebxpushl %ebx # is saved as we use that in ret_sys_callpushl %eaxmovl $0x10,%eax # ds,es 置為指向內(nèi)核數(shù)據(jù)段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax # fs 置為指向局部數(shù)據(jù)段(出錯程序的數(shù)據(jù)段)。mov %ax,%fsincl _jiffies# 由于初始化中斷控制芯片時沒有采用自動EOI,所以這里需要發(fā)指令結(jié)束該硬件中斷。movb $0x20,%al # EOI to interrupt controller #1outb %al,$0x20 # 操作命令字OCW2 送0x20 端口。# 下面3 句從選擇符中取出當(dāng)前特權(quán)級別(0 或3)并壓入堆棧,作為do_timer 的參數(shù)。movl CS(%esp),%eaxandl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)pushl %eax# do_timer(CPL)執(zhí)行任務(wù)切換、計時等工作,在kernel/shched.c,305 行實現(xiàn)。call _do_timer # 'do_timer(long CPL)' does everything fromaddl $4,%esp # task switching to accounting ...jmp ret_from_sys_call#### 這是sys_execve()系統(tǒng)調(diào)用。取中斷調(diào)用程序的代碼指針作為參數(shù)調(diào)用C 函數(shù)do_execve()。# do_execve()在(fs/exec.c,182)。.align 2_sys_execve:lea EIP(%esp),%eaxpushl %eaxcall _do_execveaddl $4,%esp # 丟棄調(diào)用時壓入棧的EIP 值。ret5.5 system_call.s 程序#### sys_fork()調(diào)用,用于創(chuàng)建子進(jìn)程,是system_call 功能2。原形在include/linux/sys.h 中。# 首先調(diào)用C 函數(shù)find_empty_process(),取得一個進(jìn)程號pid。若返回負(fù)數(shù)則說明目前任務(wù)數(shù)組# 已滿。然后調(diào)用copy_process()復(fù)制進(jìn)程。.align 2_sys_fork:call _find_empty_process # 調(diào)用find_empty_process()(kernel/fork.c,135)。testl %eax,%eaxjs 1fpush %gspushl %esipushl %edipushl %ebppushl %eaxcall _copy_process # 調(diào)用C 函數(shù)copy_process()(kernel/fork.c,68)。addl $20,%esp # 丟棄這里所有壓棧內(nèi)容。1: ret#### int 46 -- (int 0x2E) 硬盤中斷處理程序,響應(yīng)硬件中斷請求IRQ14。# 當(dāng)硬盤操作完成或出錯就會發(fā)出此中斷信號。(參見kernel/blk_drv/hd.c)。# 首先向8259A 中斷控制從芯片發(fā)送結(jié)束硬件中斷指令(EOI),然后取變量do_hd 中的函數(shù)指針放入edx# 寄存器中,并置do_hd 為NULL,接著判斷edx 函數(shù)指針是否為空。如果為空,則給edx 賦值指向# unexpected_hd_interrupt(),用于顯示出錯信息。隨后向8259A 主芯片送EOI 指令,并調(diào)用edx 中# 指針指向的函數(shù): read_intr()、write_intr()或unexpected_hd_interrupt()。_hd_interrupt:pushl %eaxpushl %ecxpushl %edxpush %dspush %espush %fsmovl $0x10,%eax # ds,es 置為內(nèi)核數(shù)據(jù)段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax # fs 置為調(diào)用程序的局部數(shù)據(jù)段。mov %ax,%fs# 由于初始化中斷控制芯片時沒有采用自動EOI,所以這里需要發(fā)指令結(jié)束該硬件中斷。movb $0x20,%aloutb %al,$0xA0 # EOI to interrupt controller #1 # 送從8259A。jmp 1f # give port chance to breathe1: jmp 1f # 延時作用。1: xorl %edx,%edxxchgl _do_hd,%edx # do_hd 定義為一個函數(shù)指針,將被賦值read_intr()或# write_intr()函數(shù)地址。(kernel/blk_drv/hd.c)# 放到edx 寄存器后就將do_hd 指針變量置為NULL。testl %edx,%edx # 測試函數(shù)指針是否為Null。jne 1f # 若空,則使指針指向C 函數(shù)unexpected_hd_interrupt()。movl $_unexpected_hd_interrupt,%edx # (kernel/blk_drv/hdc,237)。1: outb %al,$0x20 # 送主8259A 中斷控制器EOI 指令(結(jié)束硬件中斷)。call *%edx # "interesting" way of handling intr.pop %fs # 上句調(diào)用do_hd 指向的C 函數(shù)。pop %espop %ds5.5 system_call.s 程序popl %edxpopl %ecxpopl %eaxiret#### int38 -- (int 0x26) 軟盤驅(qū)動器中斷處理程序,響應(yīng)硬件中斷請求IRQ6。# 其處理過程與上面對硬盤的處理基本一樣。(kernel/blk_drv/floppy.c)。# 首先向8259A 中斷控制器主芯片發(fā)送EOI 指令,然后取變量do_floppy 中的函數(shù)指針放入eax# 寄存器中,并置do_floppy 為NULL,接著判斷eax 函數(shù)指針是否為空。如為空,則給eax 賦值指向# unexpected_floppy_interrupt (),用于顯示出錯信息。隨后調(diào)用eax 指向的函數(shù): rw_interrupt,# seek_interrupt,recal_interrupt,reset_interrupt 或unexpected_floppy_interrupt。_floppy_interrupt:pushl %eaxpushl %ecxpushl %edxpush %dspush %espush %fsmovl $0x10,%eax # ds,es 置為內(nèi)核數(shù)據(jù)段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax # fs 置為調(diào)用程序的局部數(shù)據(jù)段。mov %ax,%fsmovb $0x20,%al # 送主8259A 中斷控制器EOI 指令(結(jié)束硬件中斷)。outb %al,$0x20 # EOI to interrupt controller #1xorl %eax,%eaxxchgl _do_floppy,%eax # do_floppy 為一函數(shù)指針,將被賦值實際處理C 函數(shù)程序,# 放到eax 寄存器后就將do_floppy 指針變量置空。testl %eax,%eax # 測試函數(shù)指針是否=NULL?jne 1f # 若空,則使指針指向C 函數(shù)unexpected_floppy_interrupt()。movl $_unexpected_floppy_interrupt,%eax1: call *%eax # "interesting" way of handling intr.pop %fs # 上句調(diào)用do_floppy 指向的函數(shù)。pop %espop %dspopl %edxpopl %ecxpopl %eaxiret#### int 39 -- (int 0x27) 并行口中斷處理程序,對應(yīng)硬件中斷請求信號IRQ7。# 本版本內(nèi)核還未實現(xiàn)。這里只是發(fā)送EOI 指令。_parallel_interrupt:pushl %eaxmovb $0x20,%aloutb %al,$0x20popl %eaxiret
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -