参考了大佬的实验报告博客
之前一直实在Windows下使用bochs进行实验,一直各种不方便,后来辛辛苦苦在Ubuntu下安装了bochs和Linux0.11内核,操作过程真的天上地下啊,Windows的bochs要一个一个跳转文件目录,输代码也烦死人,Ubuntu下直接在文件夹下修改就该,代码文件也可以通过挂载,在Ubuntu环境中直接写好,简直美滋滋啊。话不多说,详述实验过程(其实比起Windows下的操作,Ubuntu下简直简单死了好吧)
1.直接在ubuntu文件夹oslab/linux-0.11/ include/linux 之中修改sys.h
添加iam和whoami&&添加sys_iam,sys_whoami
2.同理在文件夹linux-0.11/kernel 中修改system_calls.s,把 nr_system_calls 改为 74 ,其代表了中断函数的个数
3.接下来修改Makefile文件,Makefile里记录的是所有源程序文件的编译、链接规则。
我们要修改的是linux-0.11/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
4.注意Makefile修改后需要编译,但是我们需要先添加who.c文件不然编译会提示找不到源文件
在oslab/linux/kernel下添加who.c文件,并编写文件代码如下
#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include <asm/segment.h>
char temp[64]={0};
int sys_iam(const char* name)
{
int i=0;
while(get_fs_byte(name+i)!='\0')
i++;
if(i>23){
return -EINVAL;
}
printk("%d\n",i);
i=0;
while((temp[i]=get_fs_byte(name+i))!='\0'){
i++;
}
return i;
}
int sys_whoami(char* name,unsigned int size)
{
int i=0;
while (temp[i]!='\0')
i++;
if (size<i)
return -1;
i=0;
while(temp[i]!='\0'){
put_fs_byte(temp[i],(name+i));
i++;
}
return i;
}
5.在ubuntu系统下进入oslab/linux-0.11目录下再次编译
先make clean再make,编译成功后进行下一步
6.对unistd.h进行修改,需要注意unistd.h 不能直接在oslab直接修改,而且在ubuntu系统下是看不到usr内部文件的,我们可以通过挂载,实现在ubuntu系统下对Linux内部文件的修改。
在oslab中有一个mount-hdc脚本
sudo ./mount-hdc
可以把虚拟机硬盘挂载在oslab/hdc 目录下。我们可以直接在hdc文件夹内看到内部文件。在hdc/usr/include 目录下修改unistd.h 代码如下
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
#define __NR_iam 72
#define __NR_whoami 73
7.修改结束后我们只是对挂载的文件进行了修改,还需要同步到Linux内部文件中,因此我们可以通过解除挂载实现内部文件的更新(同理,内部文件更新后我们需要在外部先解除挂载,再重新挂载,此处有误,解不解除挂载没有影响,但是在内部修改文件后需要解除挂载再重新挂载才能看到更新,如果没有就等一会多试两次,怀疑系统对更新的写入比较慢。。。)
sudo umount hdc
8.最后我们需要在Linux内部文件/usr中写入whoami.c和iam.c文件,因为在挂载的hdc文件夹中似乎不能新建新文件,我们可以先运行bochs,进入/usr文件夹下
vi iam.c
vi whoami.c
在c文件中随意输入一些字符保存后退出,这样我们再次挂载后就能在hdc文件下看到我们添加的iam.c和whoami.c文件了,然后我们直接在ubuntu系统下编辑代码(比bochs下使用vi编译方便的多有没有)代码文件如下
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[])
{
if(argc>1){
if(iam(argv[1])<0){
printf("SystemCall Exception!\n");
return -1;
}
}
else{
printf("Input Exception!\n");
return -1;
}
return 0;
}
whoami.c
#define __LIBRARY__
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
_syscall2(int,whoami,char*,name,unsigned int,size)
int main()
{
int counter;
char buff[128]={0};
counter=whoami(buff,128);
if(counter < 0)
{
printf("SystemCall Exception!");
return -1;
}
else{
printf("%s\n",buff);
}
return 0;
}
修改完成后保存,然后解除挂载(不解除的话修改不会同步到Linux中)
9.最后我们运行bochs进入/usr文件夹下对whoami和iam文件进行编译
gcc -o iam iam.c
gcc -o whoami whoami.c
10.编译成功后运行效果如下
[/usr]# ./iam hello
5
[/usr]# ./whoami
hello
iam会返回字符串的字数,whoami会从系统中获得我们输入的字符串并输出