Asembler w kodzie linuxa | ||
---|---|---|
<<< Wstecz | Przykłady | Dalej >>> |
Funkcje systemowe wywoływane są przy pomocy przerwania 0x80. W jądrze obsługa przerwania funkcji systemowych dla procesora Intel x86 znajduje się w pliku arch/i386/kernel/entry.S
role procedury obsługi przerwania pełni procedura system_call
ENTRY(system_call) pushl %eax # save orig_eax SAVE_ALL GET_CURRENT(%ebx) testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS jne tracesys cmpl $(NR_syscalls),%eax jae badsys call *SYMBOL_NAME(sys_call_table)(,%eax,4) movl %eax,EAX(%esp) # save the return value ENTRY(ret_from_sys_call) cli # need_resched and signals atomic test cmpl $0,need_resched(%ebx) jne reschedule cmpl $0,sigpending(%ebx) jne signal_return restore_all: RESTORE_ALL badsys: movl $-ENOSYS,EAX(%esp) jmp ret_from_sys_call ALIGN signal_return: sti # we can get here from an interrupt handler testl $(VM_MASK),EFLAGS(%esp) movl %esp,%eax jne v86_signal_return xorl %edx,%edx call SYMBOL_NAME(do_signal) jmp restore_all ALIGN v86_signal_return: call SYMBOL_NAME(save_v86_state) movl %eax,%esp xorl %edx,%edx call SYMBOL_NAME(do_signal) jmp restore_all |
Makro SAVE_ALL zachowuje zawartość rejestrów procesora na stosie. Następnie do rejestrów eax,es,ds kopiowany jest wskaznik do segmentu danych jądra.
#define SAVE_ALL \ cld; \ pushl %es; \ pushl %ds; \ pushl %eax; \ pushl %ebp; \ pushl %edi; \ pushl %esi; \ pushl %edx; \ pushl %ecx; \ pushl %ebx; \ movl $(__KERNEL_DS),%edx; \ movl %edx,%ds; \ movl %edx,%es; |
Makro GET_CURRENT ustawia rejestr ebx tak, że wskazuje on na początek struktury task_struct. Makro to wykorzystuje budowę struktury task_union - odległość między początkiem task_struct a początkiem stosu jest stała.
#define GET_CURRENT(reg) \ movl $-8192, reg; \ andl %esp, reg #define RESTORE_ALL \ popl %ebx; \ popl %ecx; \ popl %edx; \ popl %esi; \ popl %edi; \ popl %ebp; \ popl %eax; \ 1: popl %ds; \ 2: popl %es; \ addl $4,%esp; \ 3: iret; \ |
Następnie sprawdza się czy numer funkcji systemowej jest prawidłowy. Po sprawdzeniu tych warunków wywoływana jest odpowiednia funkcja systemowa. Wywolanie funkcji to skok do adesu zapisanego w odpowiedniej pozycji tablicy (ktorej numer jest w rejestrze eax ) sys_call_table. Po powrocie z funkcji systemowej sprawdzana jest wartość pola need_resched i w gdy jest ona rożna od zera to wywoływana jest funkcja reschedule
Na koniec sprawdza sie czy proces otrzymał sygnał, jeżeli tak to wysyła się go do procesu. Ostatnią czynnością jest przywrócenie poprzednich wartości rejestrów procesora.
Jak widac procedura obsługi przerwania procesora wymaga bezpośredniego operowania na rejestrach procesora, więc można ją napisać tylko w asemblerze.
<<< Wstecz | Spis treści | Dalej >>> |
Parametry funkcji systemowych | Początek rozdziału | Ładowanie systemu |