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号中断的中断描述符,附陷阱门描述符结构

linux0.11中断描述符,Linux0.11中断及系统调用_第1张图片

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 };

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

欢迎大家指正、讨论

你可能感兴趣的:(linux0.11中断描述符)