绑定中断向量0x80与system_call (陷阱门设置)

1, linux-2.6.11.12\arch\i386\kernel\traps.c:

#define SYSCALL_VECTOR          0x80
trap_init-> set_system_gate( SYSCALL_VECTOR,& system_call);
陷阱门是在trap_init中设置)    
2,linux-2.6.11.12\arch\i386\kernel\traps.c:
#define GDT_ENTRY_KERNEL_BASE       12
#define GDT_ENTRY_KERNEL_CS          (GDT_ENTRY_KERNEL_BASE + 0)
#define __KERNEL_CS                          (GDT_ENTRY_KERNEL_CS * 8)

在保护模式下,中断向量表中的表项由8个字节组成,中断向量表也叫做中断描述符表IDT(Interrupt Descriptor Table,idt_table):
struct  desc_struct {
     unsigned long a,b;
};
struct desc_struct  idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };

Intel i386共有256个中断,每个中断都有一个0~255之间的数来表示,Intel将前32个中断号(0~31)已经固定设定好或者保留未用。中断号32~255分配给操作系统和应用程序使用。在Linux中,中断号32~47对应于一个硬件芯片的16个中断请求信号,这16个中断包括时钟、键盘、软盘、数学协处理器、硬盘等硬件的中断。系统调用设为中断号128,即0x80。

idt_table门结构:

116-3116位是中断处理程序所在的段选择符。

20-15位和48-64位组合起来形成32位偏移量,也就是中断处理程序所在段(16-31位给出)的段内偏移。

34043位共4位表示描述符的类型。(0111:中断描述符,1010:任务门描述符,1111:陷阱门描述符)

44546两位标识描述符的访问特权级(DPL,Descriptor Privilege Level)

547位P标识段是否在内存中。如果为1则表示段当前不再内存中。

3, linux-2.6.11.12\arch\i386\kernel\traps.c:
_set_gate设置门的具体指:

宏_set_gate()有四个参数:(1)gate_addr:描述符desc_struct结构类型的指针,指定待操作的描述符,通常指向数组idt_table中的某个项。(2)type:描述符类型,对应于门格式中的Type字段。(3)dpl:该描述符的权限级别;(4)addr:中断处理程序入口地址的段内偏移量,由于内核段的起始地址总是为0,因此中断处理程序在内核段中的段内偏移量也就是中断处理程序的入口地址(即核心虚地址)。(5)seg指示内核代码段。

根据上述设置:
1), DPL=3为陷阱门, 用于系统调用,DPL为3,允许用户态直接使用int指令访问,这样才能通过int 0x80访问系统调用;
2), type=15=0b111表示陷阱门;
3), 0x8000用于设置第47位P=1,表示段当前不在内存中;
4), seg<<16,即__KERNEL_CS<<16写入 中断处理程序所在的段选择符(SEGMENT SELECTOR), 由于Linux内核代码均在段选择子__KERNEL_CS 所指向的内核段中,因此门中的Segment Selector字段总是等于 __KERNEL_CS
5), (char *)addr( system_call 写入OFFSET[0-15],OFFSET[16-31];

4 linux-2.6.11.12\arch\i386\kernel\traps.c:
定义了系统调用system_call,用于调用具体的系统调用。
asm linkage int system_call(void);
system_call的是在arch\i386\kernel\entry.S中用汇编实现:
# system call handler stub
ENTRY(system_call)
pushl %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation
testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(nr_syscalls), %eax
jae syscall_badsys
syscall_call:
call *sys_call_table(,%eax,4)
movl %eax,EAX(%esp) # store the return value

sys_call_table每一项占用4个字节。system_call函数可以读取eax寄存器获得当前系统调用的系统调用号,将其乘以4生成偏移地址,然后以sys_call_table为基址,基址加上偏移地址所指向的内容即是应该执行的系统调用服务例程的地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值