Linux系统调用过程(Linux0.11内核实验)

什么是系统调用呢?

系统调用和普通函数调用得区别:
普通函数调用:调用自定义函数是通过call指令直接跳转到该函数的地址,继续运行。
系统调用:调用一个系统得API(Application programming Interface)应用程序接口,通过API调用真正的系统调用;


API调用系统调用的过程:
   1. 把系统调用的编号存入EAX
   2. 把函数参数存入其它通用寄存器
   3. 触发0x80号中断(int 0x80)

有点迷糊了吧,来看一下实验;


首先,需要将两个函数原型改变一下:

int iam(const char * name);
int whoami(char* name, unsigned int size);

变成:

_syscall1(int,iam,char*,name);
_syscall2(int,whoami,char*,name,int,size);

以便于_systemcall*宏展开;

 

 

不知道什么是_system*宏展开;那就来看一下unistd.h中定义的_system1宏:

#define _syscall1(type,name,atype,a) \
type name(atype a) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(a))); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}


这里先定义了一个long变量__res;
之后把中断号__NR_##name(name是参数要替换)传入寄存器EAX,参数a存入寄存器EBX,__res用来承载中断返回值,int 80就是我们熟知的中断调用,后面就是返回值分析判断;

因此,我们需要在unistd.h中添加中断号的宏的定义,在开头写入:

#define __NR_iam    72
#define __NR_whoami 73

之后,我们就进入了int 80所进入了系统调用,经过一重重调用啊我们终于到了system_call.s文件,也就是我们的系统调用处理到达我们需要的函数得代码,纯汇编啊,看起来很蛋疼;

看啊看;看到一句:

nr_system_calls = 72

这个是什么?系统调用总数啊,一句话改之~~~~

之后:

system_call:
...
call sys_call_table(,%eax,4)
...

这句话就很牛逼了,翻译过来就是
call sys_call_table + 4 * %eax
记不记得,EAX是我们之前在宏展开时存放中断号的地方,这里乘以4后加上一个值,其实就是在计算函数指针的地址啊!!!!
而sys_call_table是什么值呢?


我们看sys.h中,发现了吗?中断函数表,那上面的语句就是很明显在通过数组首地址计算数组元素的地址了,也就是函数指针的地址。
这样,我们在数组中添加:

fn_ptr sys_call_table[] = { ...,sys_iam,sys_whoami};

因为函数原型不知在这里申明的,之前需要加上:

extern int sys_whoami();
extern int sys_iam();

这样,编译器就会去别的文件中寻找函数定义。

其实到这步,我们依旧没有定义函数,现在去编译的话,就会出错。

接下来,就该我们写实实在在的函数来实现了,只要名字是sys_whoami(),int sys_iam();编译器就会找到,当然,前提是要编译到内核中。


新建who.c文件到kernel文件夹引入一大堆头文件后就可以开始写了,和一般的函数基本上一样不过要时刻记住在内核中运行;
写完:sys_iam,sys_whoami后就可以开始编译了;

但是怎么把我写得who.c编译到内核中呢?

主要就是要修改makefile文件这样的话,执行make命令之后,makefile文件会指向你想要得文件,就可以编译到内核了。
但是至今没看懂,就抄一下代码:

我们要修改的是kernel/Makefile。需要修改两处。一处是:

OBJS  = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o

改为:

OBJS  = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o who.o

另一处:

### Dependencies:
exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h

改为:

### Dependencies:
who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h
exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h











posted @ 2011-11-05 23:36  chengzheqiao  阅读(1614)  评论(0编辑  收藏  举报