1. 程式人生 > >Linux0.11中斷及系統呼叫

Linux0.11中斷及系統呼叫

中斷簡介

Linux0.11使用的Intel i386晶片共有256箇中斷,表現為中斷號0~255.

其中前0~31號中斷已經由Intel預定義,其餘中斷號為可程式設計中斷。

32~47號分別對應linux的16個硬體中斷訊號(包括時鐘、鍵盤、軟盤等)。

0x80中斷即128號中斷為linux系統呼叫軟中斷。

硬中斷和軟中斷

  • 軟中斷是執行中斷指令(int n,n為中斷號)主動產生的。而硬中斷則是由外部引發的,具有隨機性、突發性
  • 硬中斷中斷號由中斷控制器提供,而軟中斷中斷號直接由指令指出。

系統呼叫

系統呼叫int 0x80是一個軟中斷,是應用程式與Linux核心互動的介面。

系統呼叫初始化過程

在init/main.c初始化主程式main()中呼叫的sched_init()排程初始化函式中最後一行

set_system_gate(0x80,&system_call);

將0x80軟中斷與系統呼叫入口函式system_call聯絡起來。

---------------------------------------------------------------------------------------------------------------------------------------------

init/main.c : main() : line-132 -->kernel/sched.c : sched_init() -->set_system_gate(0x80,&system_call);

------------------------------------------------------------------------------------------------------------------------------------

set_system_gate()

為include/asm目錄中system.h檔案中的巨集函式

#define set_system_gate(n,addr) \
_set_gate(&idt[n],15,3,addr)
#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ ("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \
"movl %%edx,%2" \
: \
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"o" (*((char *) (gate_addr))), \
"o" (*(4+(char *) (gate_addr))), \
"d" ((char *) (addr)),"a" (0x00080000))

該函式即為設定0x80號中斷的中斷描述符,附陷阱門描述符結構


  • DPL為優先順序,3為使用者態,0為核心態
  • TYPE即為圖中第一行的8~11位
  • addr為中斷處理函式地址
  • idt為中斷描述符表,共256項,每項佔8位元組,在include/linux/head.h中定義
extern desc_table idt
typedef struct desc_struct {
unsigned long a,b;
} desc_table[256];

即把system_call函式的地址存入和優先順序、中斷型別的資訊存入中斷描述符表中0x80號中斷

--------------------------------------------------------------------------------------------------------------------------------------------

int 0x80  -->  kernel/system_call.s : 80 : _system_call  -->  include/linux/sys.h : 74 : sys_call_table[eax]()

------------------------------------------------------------------------------------------------------------------------------------

int 0x80在linux0.11中已經封裝好系統呼叫介面,見include/unistd.h檔案133~183行

共_syscall0、_syscall1、_syscall2、_syscall3四個巨集函式,分別為無參~含有三個引數的系統呼叫

這裡貼出無參的系統呼叫_syscall0程式碼

#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \                //將輸出賦給變數__res,"=a"表示強制使用ax暫存器
: "0" (__NR_##name)); \         //將__NR_name作為輸入(系統呼叫號,在include/unistd.h定義),"0"表示使用與上一行一樣的暫存器
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}

舉個呼叫該巨集函式的例子進行講解

在init/main.c:23    呼叫該函式

static inline _syscall0(int,fork)

呼叫該函式的作用為定義了一個

靜態(static) 內聯(inline) 返回型為int(對應巨集函式的type引數) 函式名為fork(對應巨集函式name引數) 的無參函式:static inline int fork(void){}

該函式使用了內聯彙編觸發0x80號中斷

--------------------------------------------------------------------------------------------------------------------------------------------

system_call

為C語言呼叫的彙編函式,在kernel/system_call.s第80行

主要作用為將程序從使用者態切換到核心態,然後呼叫該檔案94行的call  _sys_call_table(,%eax,4) 

這條指令的含義為跳轉到sys_call_table + eax*4地址去執行。

  • sys_call_table為在include/linux/sys.h定義的C語言-函式指標陣列,陣列中存放了72個系統呼叫函式指標。
  • eax為中斷號
  • *4是因為32位機每個指標佔四個位元組

即實際指令為跳轉到系統呼叫函式指標陣列中執行對應的系統呼叫。

以下為函式指標陣列的初始化

typedef int (*fn_ptr)();                //在include/linux/sched.h 38行
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid };

------------------------------------------------------------------------------------------------------------------------------------

歡迎大家指正、討論