Linux系统调用与实例分析 下载本文

内容发布更新时间 : 2024/12/25 16:52:07星期一 下面是文章的全部内容请认真阅读。

Linux系统调用与实例分析

计算机961班 林霁 9615018

一. 系统调用的基本概念

通常,在OS的核心中都设置了一组用于实现各种系统功能的子程序(过程),并将它们提供给用户调用。每当用户在程序中需要OS提供某种服务时,便可利用一条系统调用命令,去调用系统过程。它一般运行在核心态;通过软中断进入;返回时通常需要重新调度(因此不一定直接返回到调用过程)。

系统调用是沟通用户(应用程序)和操作系统内核的桥梁。

二. Linux的系统调用

Linux系统调用的流程非常简单,它由0x80号软中断进入系统调用入口,通过使用系统调用表保存系统调用服务函数的入口地址来实现。

2.1 Linux系统调用的数据结构

在文件“arch/i386/entry.S”中定义了系统调用表(sys_call_table),该表保存了Linux的所有基于Intel x86系列体系结构的计算机的166个系统调用入口地址(其中3个保留,Linux开辟的系统调用表可容纳256项),其中每项都被说明成 long型。下面是其中几项:

.data

ENTRY(sys_call_table)

.long SYMBOL_NAME(sys_setup) .long SYMBOL_NAME(sys_exit) .long SYMBOL_NAME(sys_fork)

1

/* 0 */

…… ……

.long SYMBOL_NAME(sys_nanosleep) /* 162 */ .long SYMBOL_NAME(sys_mremap) .long 0,0

.long SYMBOL_NAME(sys_vm86) .space (NR_syscalls-166)*4

NR_syscalls是在“include/linux/sys.h”文件中定义的宏,其值为256,表示x86微机上最多可容纳的系统调用个数。

在文件“include/asm-i386/ptrace.h”中定义了一种寄存器帧结构 struct pt_regs { };

2

long ebx; long ecx; long edx; long esi; long edi; long ebp; long eax;

unsigned short ds, __dsu; unsigned short es, __esu; unsigned short fs, __fsu; unsigned short gs, __gsu; long orig_eax; long eip;

unsigned short cs, __csu; long eflags; long esp;

unsigned short ss, __ssu;

该帧结构定义了各寄存器在系统调用时保存现场的堆栈结构。

2.2 设置0x80 软中断

Linux的系统调用由0x80号软中断进入,中断向量表的初始化在系统启动时进行,各种trap入口start_kernel()函数(init/main.c)中通过调用trap_init()(

arch/i386/kernel/traps.c

set_system_gate(0x80,&system_call)设置了0x80号软中断。

“set_system_gate()”是一个宏,它在“include/asm-i386/system.h”中被定义。调用该宏,将使addr地址值置入gate_addr中的地址值所指向的内存单元中,以上过程,使中断向量描述表中的第128项(即16进制第80项)保存了0x80号中断的中断服务程序,即system_call的入口地址。

2.3系统调用入口

在头文件“include/asm-i386/unistd.h”中,定义了一系列的与系统调用有关的宏,包括系统调用序号,如:

#define __NR_setup #define __NR_exit #define __NR_fork #define __NR_read

还定义了设置系统调用入口的宏,_syscallX(),其中X表示系统调用的参数个数,Linux定义的各种系统调用的参数个数不超过5个,因此,在5)。

下面以_syscall2()为例:

#define _syscall2(type,name,type1,arg1,type2,arg2) \\ type name(type1 arg1,type2 arg2) \\ { \\

3

0 1 2 3

该文件中,共定义了6个宏

(_syscall0(type,name),……,_syscall5(type,name,type1,arg1,……,type5,arg