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中断及系统调用_第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学习笔记)