发布时间 : 星期一 文章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