Funkcje systemowe

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.