在unistd.h中可以看到现在Linux 0.11 支持3个参数的传递。添加参数的方法大概有3条
1. 可以采用ESI,EDI,EBP,ESP这几个寄存器传递参数。
2. 可以采用《Linux 0.11注释》中提到的系统调用门的办法。
3. 可以开辟一块用户态的空间,允许内核态访问,传递参数时,只需传递此空间的首地址指针即可。
向linux 0.11添加一个系统调用foo()的步骤:
首先。在内核中编写系统调用处理函数。
其次。在include/unistd.h中添加系统调用的功能号(#define __NR_foo **)
并且相应的在include/linux/sys.h中声明新的系统调用处理函数以及添加系统 调用处理程序指针数组表中该项的索引值。
在make file中添加新系统调用所在文件的编译、链接规则(依赖关系)。修改system_call.s中系统调用总数。
最后。在应用程序中提供接口,调用系统调用。
这次实验,需要改写unistd.h sys.h system_call.s makefile 4个文件,而且需要自己写出 who.c iam.c whoami.c 3个文件
(1)修改linux-0.11/include/linux/sys.h
根据Linux调用系统调用的过程,需要把 iam()与whoami()两个函数加到全局变量,和中断函数表中就可以了,中断被调用的时候,先查找中断向量表,找到相应的函数名,调用其函数。
分别添加声明到最下面和数组中:
声明分别为extern int sys_iam();extern int sys_whoami();sys_iam, sys_whoami
........................
extern int sys_setreuid();
extern int sys_setregid();
extern int sys_iam();//需要新增的地方
extern int sys_whoami();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid,.....................................
sys_setreuid,sys_setregid, ```sys_iam, sys_whoami```};//记得在中断向量表的最后填上系统调用
(2) 修改系统调用数:
system_call.s 在 linux-0.11/kernel 中
需要把nr_system_calls 由72改为 74 表示了中断函数的个数。
nr_system_calls = 74
(3)新增系统调用号:
unistd.h 不能直接在ubantu中修改,
而需要在bochs虚拟机中修改,
在oslab目录中有一个mount-hdc脚本
运行sudo ./mount-hdc 可以把虚拟机硬盘挂载在oslab/hdc 目录下。
(这个也可以实现文件共享)
在hdc/usr/include
目录下修改unistd.h
#define __NR_setup 0
...............//省略
#define __NR_setregid 71
#define __NR_iam 72 /*new system_call 72 and 73*/
#define __NR_whoami 73
增加iam,whoami系统调用号就完成了。
(4)新增who.c文件,实现系统调用的函数
将完成的who.c文件放入linux-0.01/kernel 目录下
#include <string.h>
#include <errno.h>
#include <asm/segment.h>
char msg[24];
int sys_iam(const char * name)
{
char tep[26];
int i = 0;
for(; i < 26; i++)
{
tep[i] = get_fs_byte(name+i);
if(tep[i] == '\0') break;
}
if (i > 23) return -(EINVAL);
strcpy(msg, tep);
return i;
}
int sys_whoami(char * name, unsigned int size)
{
int len = 0;
for (;msg[len] != '\0'; len++);
if (len > size)
{
return -(EINVAL);
}
int i = 0;
for(i = 0; i < size; i++)
{
put_fs_byte(msg[i], name+i);
if(msg[i] == '\0') break;
}
return i;
}
(5) 修改Makefile 文件
让我们添加的kernel/who.c可以和其它Linux代码编译链接到一起,必须要修改Makefile文件
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
Makefile修改后,和往常一样“make all”就能自动把who.c加入到内核中了
(6) 新增iam.c 跟whoami.c文件以测试是否添加系统调用成功:
iam.c
#define __LIBRARY__
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
_syscall1(int,iam,const char*,name)
int main(int argc,char* argv[])
{
iam(argv[1]);
return 0;
}
whoami.c
#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
_syscall2(int, whoami, char*, name, unsigned int, size);
int main(int argc, char ** argv)
{
char t[30];
whoami(t, 30);
printf("%s\n", t);
return 0;
}
注:这两个C文件是需要在你修改过的linux 0.11版本上编译的,如果嫌在 0.11 里面用vi写代码太烦,可以在虚拟机中写好, 在oslab中运行。
简便的方式是把虚拟机硬盘挂载在oslab/hdc 目录下。
sudo ./mount-hdc
然后再将文件复制到 oslab/hdc/user/root/下
/user/root/ 就是你的linux 0.11 开机后所在目录
cp iam.c,whoami.c oslab/hdc/user/root/
好了,运行
cd /home/fgx/oslab
./run
(7)编译 iam.c 跟 whoami.c
gcc -o iam iam.c
gcc -o whoami whoami.c
验证
[/usr/root]# ./iam zhangshan
[/usr/root]# ./whoami
zhangshan
原创作者:寒夏凉秋
链接:https://www.jianshu.com/p/5786cd42b152
来源:简书