日期:2014-05-16  浏览次数:20780 次

linux内核--系统调用(四)

一. 概述

         系统调用是应用程序与内核交互的一种方式。系统调用作为一种接口,通过系统调用,应用程序能够进入操作系统内核,从而使用内核提供的各种资源,比如操作硬件,开关中断,改变特权模式等等。首先,系统调用是一个软中断,既然是中断那么一般就具有中断号和中断处理程序两个属性,Linux使用0x80号中断作为系统调用的入口,而中断处理程序的地址放在中断向量表里。

 

二. 过程

         基于linux-2.6.38,以read()系统调用函数为例进行说明。    

       在用户空间,read()函数的声明位于#include<unistd.h>,原型为:ssize_t read(int fd, void *buf, size_t count)。下面是read()函数在用户空间的定义的伪代码:

复制代码
 1 ssize_t read(int fd, void *buf, size_t count)
 2 {
 3        long res;
 4        %eax = __NR_read
 5        %ebx = fd 
 6        %ecx = (long)buf
 7        %edx= count
 8        int $0x80
 9        res = %eax
10        return res;
11 }
复制代码

         第4行,用eax寄存器保存read()的系统调用号,在/arch/x86/include/asm/unistd_32.h里定义(#define __NR_read  3);第5~7行,分别将三个参数放入三个寄存器(通过寄存器来传递参数);第8行,执行系统调用,进入内核;第9行,获取eax寄存器所保存的函数返回值。

       执行第8行后已经进入了系统内核,由于这是一个中断,因此程序进入到中断向量表中记录0x80号的中断处理程序,中断向量表的初始化在/arch/x86/kernel/traps.c中定义:

复制代码
 1 void __init trap_init(void)
 2 {
 3 ...................
 4 
 5    #ifdef CONFIG_X86_32
 6        set_system_trap_gate(SYSCALL_VECTOR, &system_call);
 7        set_bit(SYSCALL_VECTOR, used_vectors);
 8    #endif
 9 ...................
10 }
复制</div></div>


                        <div class=