linux课程设计指导文档 联系客服

发布时间 : 星期一 文章linux课程设计指导文档更新完毕开始阅读b08d5cda7f1922791688e89f

相应地返回。不一定是返回到用户进程。真正返回到用户空间时,要恢复环境(restore_all)。

2. 用户程序中系统调用的过程

在前面提到system_call会根据用户传进来系统调用号,在系统调用

表 system_call中寻找到相应偏移地址的内核处理函数,进行相应的处理。那么系统调用号怎么产生,在include/asm-i386/unistd.h中可以看到系统调用号的定义。

#define __NR_restart_syscall 0 #define __NR_exit #define __NR_fork #define __NR_read

1 2 3 4 5 6 7 8 9

#define __NR_write #define __NR_open

#define __NR_close #define __NR_waitpid #define __NR_creat #define __NR_link ??

#define __NR_mq_open

277

(__NR_mq_open+1)

#define __NR_mq_unlink

#define __NR_mq_timedsend (__NR_mq_open+2) #define __NR_mq_timedreceive #define __NR_mq_notify

(__NR_mq_open+3)

(__NR_mq_open+4)

#define __NR_mq_getsetattr (__NR_mq_open+5) #define __NR_sys_kexec_load 283 #define __NR_waitid

284

/* #define __NR_sys_setaltroot 285 */ #define __NR_add_key

286

287

#define __NR_request_key

11

#define __NR_keyctl

288

#define NR_syscalls 289

此处的代码是从2.6.11中的代码,其中系统调用号已到了288,并且与前面system_call中的相对应。每一个系统调用号前都是相应函数名加了__NR_。

内核跟用户程序的交互,其实有标准C库作为它们之间的桥梁。标准C库把

用户希望传递的参数装载到CPU的寄存器中,然后触发0X80中断。当从系统调用返回的时候(sys_call_exit),标准C库又接过控制权,处理返回值。

对于__NR_,标准C库会作相应处理。转换成相应函数。对于系统函数的调用,

有几个通用的宏在include/asm-i386/unistd.h中定义。

#define __syscall_return(type, res) \\ do { \\

if ((unsigned long)(res) >= (unsigned long)(-(128 + 1))) { \\

errno = -(res); \\ res = -1; \\

} \\

return (type) (res); \\

} while (0)

#else

# define __syscall_return(type, res) return (type) (res) #endif

#define _syscall0(type,name) \\ type name(void) \\ { \\

long __res; \\

__asm__ volatile (\

: \

12

: \

__syscall_return(type,__res); \\ }

这是无参函数调用的形式。

#define _syscall1(type,name,type1,arg1) \\ type name(type1 arg1) \\ { \\

long __res; \\

__asm__ volatile (\ : \

: \

__syscall_return(type,__res); \\ }

这是含一个参数的调用形式, ??

标准C库会把我们的调用如pause()转换成相应的形式。 pause() int pause(void) { long __res;

__asm__ volatile(“int $0x80”

:”=a”(__res) :””(__NR_pause));

__syscall_return(int,__res);

}

进入内核调用过程。

13

2.2. 添加新的系统调用(2.6.18内核)

1. 步骤1:准备

如果你安装的系统包含内核源文件,一般在/usr/src路径下可以看到,那么可以直接跳到步骤3进行内核修改。

为避免编译失败造成无法进入系统,最好先修改/usr/src/linux下的Makefile文件,将内核版本修改成自己的。 2.6.18中Makefile文件头几行为:

VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 18 EXTRAVERSION = .1

我们可以修改成自己版本(2.6.18.1-1):

VERSION = 2 PATCHLEVEL = 6

SUBLEVEL = 18 EXTRAVERSION = .1-1 2. 步骤2:下载源代码

如果系统不包含源文件,则需要在网站上下载系统源代码,(大概有四五十兆)。 网址: http://kernel.org

在官方网站上下到类似 linux-2.6.18.1.tar.gz的代码后(大概有四,五十兆),放在/usr/src/ 的目录下,

然后解压:[root@localhost linux-2.6.18.1]# tar -xvf linux-(按tab键) 解压后会出现文件夹 linux-2.6.18.1。

14