?? system_call.s
字號:
;/* passed;* linux/kernel/system_call.s;*;* (C) 1991 Linus Torvalds;*/.386p
.model flat
;/*;* system_call.s contains the system-call low-level handling routines.;* This also contains the timer-interrupt handler, as some of the code is;* the same. The hd- and flopppy-interrupts are also here.;*;* NOTE: This code handles signal-recognition, which happens every time;* after a timer-interrupt and after each system call. Ordinary interrupts;* don't handle signal-recognition, as that would clutter them up totally;* unnecessarily.;*;* Stack layout in 'ret_from_system_call':;*;* 0(%esp) - %eax;* 4(%esp) - %ebx;* 8(%esp) - %ecx;* C(%esp) - %edx;* 10(%esp) - %fs;* 14(%esp) - %es;* 18(%esp) - %ds;* 1C(%esp) - %eip;* 20(%esp) - %cs;* 24(%esp) - %eflags;* 28(%esp) - %oldesp;* 2C(%esp) - %oldss;*/;/*;* system_call.s 文件包含系統(tǒng)調(diào)用(system-call)底層處理子程序。由于有些代碼比較類似,所以;* 同時也包括時鐘中斷處理(timer-interrupt)句柄。硬盤和軟盤的中斷處理程序也在這里。;*;* 注意:這段代碼處理信號(signal)識別,在每次時鐘中斷和系統(tǒng)調(diào)用之后都會進(jìn)行識別。一般;* 中斷信號并不處理信號識別,因為會給系統(tǒng)造成混亂。;*;* 從系統(tǒng)調(diào)用返回('ret_from_system_call')時堆棧的內(nèi)容見上面19-30 行。;*/SIG_CHLD = 17 ;// 定義SIG_CHLD 信號(子進(jìn)程停止或結(jié)束)。R_EAX = 00h ;// 堆棧中各個寄存器的偏移位置。R_EBX = 04hR_ECX = 08hR_EDX = 0ChR_FS = 10hR_ES = 14hR_DS = 18hR_EIP = 1ChR_CS = 20hEFLAGS = 24hOLDR_ESP = 28h ;// 當(dāng)有特權(quán)級變化時。OLR_DSS = 2Ch;// 以下這些是任務(wù)結(jié)構(gòu)(task_struct)中變量的偏移值,參見include/linux/sched.h,77 行開始。state = 0 ;// these are offsets into the task-struct. ;// 進(jìn)程狀態(tài)碼counter = 4 ;// 任務(wù)運(yùn)行時間計數(shù)(遞減)(滴答數(shù)),運(yùn)行時間片。priority = 8 ;// 運(yùn)行優(yōu)先數(shù)。任務(wù)開始運(yùn)行時counter=priority,越大則運(yùn)行時間越長。signal = 12 ;// 是信號位圖,每個比特位代表一種信號,信號值=位偏移值+1。sigaction = 16 ;// MUST be 16 (=len of sigaction) // sigaction 結(jié)構(gòu)長度必須是16 字節(jié)。;// 信號執(zhí)行屬性結(jié)構(gòu)數(shù)組的偏移值,對應(yīng)信號將要執(zhí)行的操作和標(biāo)志信息。blocked = (33*16) ;// 受阻塞信號位圖的偏移量。;// 以下定義在sigaction 結(jié)構(gòu)中的偏移量,參見include/signal.h,第48 行開始。;// offsets within sigactionsa_handler = 0 ;// 信號處理過程的句柄(描述符)。sa_mask = 4 ;// 信號量屏蔽碼sa_flags = 8 ;// 信號集。sa_restorer = 12 ;// 返回恢復(fù)執(zhí)行的地址位置。nr_system_calls = 72 ;// Linux 0.11 版內(nèi)核中的系統(tǒng)調(diào)用總數(shù)。;/*;* Ok, I get parallel printer interrupts while using the floppy for some;* strange reason. Urgel. Now I just ignore them.;*/;/*;* 好了,在使用軟驅(qū)時我收到了并行打印機(jī)中斷,很奇怪。呵,現(xiàn)在不管它。;*/;// 定義入口點。
extrn _schedule:proc,_do_signal:proc,_math_error:proc
extrn _math_state_restore:proc,_math_emulate:proc,_jiffies:proc
extrn _do_timer:proc,_do_execve:proc
extrn _find_empty_process:proc,_copy_process:proc
extrn _do_floppy:proc,_unexpected_floppy_interrupt:proc
extrn _do_hd:proc,_unexpected_hd_interrupt:proc
extrn _current:dword,_task:dword,_sys_call_table:dword
public _system_call,_sys_fork,_timer_interrupt,_sys_execvepublic _hd_interrupt,_floppy_interrupt,_parallel_interruptpublic _device_not_available, _coprocessor_error
.code
;// 錯誤的系統(tǒng)調(diào)用號。align 4 ;// 內(nèi)存4 字節(jié)對齊。bad_sys_call: mov eax,-1 ;// eax 中置-1,退出中斷。 iretd;// 重新執(zhí)行調(diào)度程序入口。調(diào)度程序schedule 在(kernel/sched.c,104)。align 4reschedule: push ret_from_sys_call ;// 將ret_from_sys_call 的地址入棧(101 行)。 jmp _schedule;//// int 0x80 --linux 系統(tǒng)調(diào)用入口點(調(diào)用中斷int 0x80,eax 中是調(diào)用號)。align 4_system_call: cmp eax,nr_system_calls-1 ;// 調(diào)用號如果超出范圍的話就在eax 中置-1 并退出。 ja bad_sys_call push ds ;// 保存原段寄存器值。 push es push fs push edx ;// ebx,ecx,edx 中放著系統(tǒng)調(diào)用相應(yīng)的C 語言函數(shù)的調(diào)用參數(shù)。 push ecx ;// push %ebx,%ecx,%edx as parameters push ebx ;// to the system call mov edx,10h ;// set up ds,es to kernel space mov ds,dx ;// ds,es 指向內(nèi)核數(shù)據(jù)段(全局描述符表中數(shù)據(jù)段描述符)。 mov es,dx mov edx,17h ;// fs points to local data space mov fs,dx ;// fs 指向局部數(shù)據(jù)段(局部描述符表中數(shù)據(jù)段描述符)。;// 下面這句操作數(shù)的含義是:調(diào)用地址 = _sys_call_table + %eax * 4。參見列表后的說明。;// 對應(yīng)的C 程序中的sys_call_table 在include/linux/sys.h 中,其中定義了一個包括72 個;// 系統(tǒng)調(diào)用C 處理函數(shù)的地址數(shù)組表。 call [_sys_call_table+eax*4] push eax ;// 把系統(tǒng)調(diào)用號入棧。 mov eax,_current ;// 取當(dāng)前任務(wù)(進(jìn)程)數(shù)據(jù)結(jié)構(gòu)地址??eax。;// 下面97-100 行查看當(dāng)前任務(wù)的運(yùn)行狀態(tài)。如果不在就緒狀態(tài)(state 不等于0)就去執(zhí)行調(diào)度程序。;// 如果該任務(wù)在就緒狀態(tài)但counter[??]值等于0,則也去執(zhí)行調(diào)度程序。 cmp dword ptr [state+eax],0 ;// state jne reschedule cmp dword ptr [counter+eax],0 ;// counter je reschedule;// 以下這段代碼執(zhí)行從系統(tǒng)調(diào)用C 函數(shù)返回后,對信號量進(jìn)行識別處理。ret_from_sys_call:;// 首先判別當(dāng)前任務(wù)是否是初始任務(wù)task0,如果是則不必對其進(jìn)行信號量方面的處理,直接返回。;// 103 行上的_task 對應(yīng)C 程序中的task[]數(shù)組,直接引用task 相當(dāng)于引用task[0]。 mov eax,_current ;// task[0] cannot have signals cmp eax,_task je l1 ;// 向前(forward)跳轉(zhuǎn)到標(biāo)號l1。;// 通過對原調(diào)用程序代碼選擇符的檢查來判斷調(diào)用程序是否是超級用戶。如果是超級用戶就直接;// 退出中斷,否則需進(jìn)行信號量的處理。這里比較選擇符是否為普通用戶代碼段的選擇符0x000f;// (RPL=3,局部表,第1 個段(代碼段)),如果不是則跳轉(zhuǎn)退出中斷程序。 cmp word ptr [R_CS+esp],0fh ;// was old code segment supervisor ? jne l1;// 如果原堆棧段選擇符不為0x17(也即原堆棧不在用戶數(shù)據(jù)段中),則也退出。 cmp word ptr [OLR_DSS+esp],17h ;// was stack segment = 0x17 ? jne l1;// 下面這段代碼(109-120)的用途是首先取當(dāng)前任務(wù)結(jié)構(gòu)中的信號位圖(32 位,每位代表1 種信號),;// 然后用任務(wù)結(jié)構(gòu)中的信號阻塞(屏蔽)碼,阻塞不允許的信號位,取得數(shù)值最小的信號值,再把;// 原信號位圖中該信號對應(yīng)的位復(fù)位(置0),最后將該信號值作為參數(shù)之一調(diào)用do_signal()。;// do_signal()在(kernel/signal.c,82)中,其參數(shù)包括13 個入棧的信息。 mov ebx,[signal+eax] ;// 取信號位圖??ebx,每1 位代表1 種信號,共32 個信號。 mov ecx,[blocked+eax] ;// 取阻塞(屏蔽)信號位圖??ecx。 not ecx ;// 每位取反。 and ecx,ebx ;// 獲得許可的信號位圖。 bsf ecx,ecx ;// 從低位(位0)開始掃描位圖,看是否有1 的位,;// 若有,則ecx 保留該位的偏移值(即第幾位0-31)。 je l1 ;// 如果沒有信號則向前跳轉(zhuǎn)退出。 btr ebx,ecx ;// 復(fù)位該信號(ebx 含有原signal 位圖)。 mov dword ptr [signal+eax],ebx ;// 重新保存signal 位圖信息??current->signal。 inc ecx ;// 將信號調(diào)整為從1 開始的數(shù)(1-32)。 push ecx ;// 信號值入棧作為調(diào)用do_signal 的參數(shù)之一。 call _do_signal ;// 調(diào)用C 函數(shù)信號處理程序(kernel/signal.c,82) pop eax ;// 彈出信號值。l1: pop eax pop ebx pop ecx pop edx pop fs pop es pop ds iretd;//// int16 -- 下面這段代碼處理協(xié)處理器發(fā)出的出錯信號。跳轉(zhuǎn)執(zhí)行C 函數(shù)math_error();// (kernel/math/math_emulate.c,82),返回后將跳轉(zhuǎn)到ret_from_sys_call 處繼續(xù)執(zhí)行。align 4_coprocessor_error: push ds push es push fs push edx push ecx push ebx push eax
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -