此次实验的基本内容是:在Linux-0.11 上添加两个系统调用,并编写两个简单的应用程序测试它们。
(1)iam()
第一个系统调用是iam(),其原型为
int iam(const char* name);
完成的功能是将字符串参数name的内容拷贝到内核中保存下来。要求name的长度不超过23个字符。返回值是拷贝的字符数。如果name的字符个数超过23,则返回“-1”,并置errno为EINVAL。
在kernel/who.c中实现此系统调用。
(2)whoami()
第二个系统调用是whoami(),其原型为:
int whoami(char* name,unsigned int size);
它将内核中由iam()保存的名字拷贝到name指向的用户地址空间中,同时确保不会对name越界访存(name的大小由size说明)。返回值是拷贝的字符数。如果size小于需要的空间,则返回“-1”,并置errno为EINVAL。
也是在kernel/who.c中实现此系统调用。
(3)测试程序
运行添加过新系统调用的linux-0.11,在其环境下编写两个测试程序iam.c和whoami.c,最终的运行结果是:
$ ./iam lizhijun
$ ./whoiam
lihzijun
(58条消息) ubuntu下 Linux 0.11 编译内核 - 实验环境搭建_~橘子~的博客-CSDN博客https://blog.csdn.net/qq_39557240/article/details/85336730
书接上回,话说bootsect.s将setup和sytem模块加载进内存中之后,就跳到了setup.s中执行程序,即将CPU控制权交给了setup模块。
根据名字就能猜到:setup将完成OS启动前的设置,主要是利用ROM BIOS中断读取机器系统数据(一些硬件参数),并将这些数据保存到0x90000开始的位置(覆盖掉了bootsect程序所在的地方),所取得的参数和保留的内存位置如下表所示:
然后setup会将system模块移动到物理地址为0的地方,然后设置CPU的控制寄存器CR0的PE位,使之从0变为1,表示系统进入32位保护模式,并且跳转到system模块最前面的部分的head.s程序继续运行。
值得注意的是,为了能让head.s在32位保护模式下运行,setup.s临时设置了中断描述符表(IDT)和全局描述符表(GDT),并在GDT中设置了当前内核代码段的描述符和数据段的描述符。
因为这只是临时设置的GDT和IDT,因此后面我们会看到head.s程序中会根据内核的需要重新设置这些描述符表。
因为boosect.s和setup.s都是在实模式下(16位)下运行的,因此使用的是16位汇编 ,汇编的语法是基于MINIX系统的汇编语言语法。而到了system模块,使用的就是32位汇编,汇编的语法是AT&T系统V的汇编语法,这两种语法之间是有区别的。
head.s里面会调用main函数,这个过程是在汇编程序中调用C函数,这是基于栈结构实现的。实质和C函数之间的调用没有区别。
进入main函数之后,会陷入死循环,即main函数正常情况下是永远不会返回的,因为操作系统这个程序需要一直运转来管理PC,如果main返回,就死机了。
至此,操作系统运转起来了。下面就可以介绍系统接口了。
系统接口就是函数调用,只是这个函数是系统提供的,因此叫做系统调用。
有时候用户程序要对内核区的代码和数据进行操作,但是内核里面都是操作系统的核心代码和数据,如果被随意操作甚至恶意破坏,计算机很可能就会崩溃。
但是用户程序在某些情况下又必须对内核进行操作,那么怎么让程序达到这个目的,而同时又使得操作系统不被恶意破坏呢?
这就是系统调用存在的意义。
这种隔离机制是由硬件提供的,这就实现了对内核的保护。
对于Intel x86,中断指令int是进入内核的唯一途径。
int指令将CS中的CPL改成0,就“进入内核”
四、实验步骤
1.首先打开linux-0.11/include/unistd.h文件,添加两个系统调用号,这些系统调用符号常数,被用作调用函数表中的索引值:
2.修改linux-0.11/kenel/system_call.s程序代码,这个程序实现了系统调用中断 int 0x80的入口处理过程。
对于系统调用(system call)这种软中断,其处理过程基本是首先为调用相应C函数处理程序做准备,将一些参数压入堆栈。
系统调用最多可以带3个参数,分别通过寄存器ebx,ecx,edx传入。然后调用C函数进行相应功能的处理,处理返回后再去检测当前任务的信号位图,对值最小的一个信号进行处理并复位信号位图中的该信号。
系统调用的C语言处理函数分布在整个linux内核代码中,由include/linux/sys.h头文件中的系统函数指针数组表来匹配,这个表的索引就是上面unistd.h定义的系统调用号。
讲了这么多,这里只需要修改系统调用的总数:
3.修改linux-0.11/include/linux/sys.h文件,将我们自己的两个系统调用函数添加进去。
该头文件列出了内核中所有系统调用函数的原型,以及系统调用函数指针表。需要修改的有两处,已标识
4.在linux-0.11/kernel目录下创建who.c文件,实现sys_iam和sys_whoami的系统调用处理函数。
#define __LIBRARY__
#include
#include /* 要求设置错误为EINVAL */
#include /* 使用put_fs_byte和get_fs_byte */
char temp[64]={0}; /* 存储sys_iam获取的字符串 */
int sys_iam(const char* name)
{
int i=0; /* 用户空间数据name长度 */
while(get_fs_byte(name+i)!='\0') i++;
if(i>23) return -EINVAL;
printk("%d\n",i);
i=0; /* 获取name至temp */
while((temp[i]=get_fs_byte(name+i))!='\0'){
i++;
}
return i;
}
int sys_whoami(char* name,unsigned int size)
{
int i=0; /* 内核空间数据temp长度 */
while (temp[i]!='\0') i++;
if (size
5.修改~/oslab/linux-0.11/kernel/Makefile文件,Makefile是make程序的配置文件,修改这个的目的是为了让我们写的who.c文件可以在使用make进行编译链接的时候生成目标文件kernel.o。
6.在~/oslab/linux-0.11/kernel目录下,执行make指令,只要不报错就行。成功后该目录下会生成who.o文件。
7.在~/oslab下面编写两个测试程序来调用这两个接口。
iam.c文件的代码,功能是调用iam系统将name写入内核,并且返回写入字符串的长度。
/ / iam.c
/* iam.c */
#define __LIBRARY__
#include "unistd.h"
_syscall1(int, iam, const char*, name);
int main(int argc, char** argv){
int wlen = 0;
if(argc < 1){
printf("not enougth argument\n");
return -2;
}
wlen = iam(argv[1]);
return wlen;
}
whoami.c文件代码,功能是调用whoami查出写入内核的name,并显示,返回值是字符串的长度。
/ / whoami.c
/* whoami.c */
#define __LIBRARY__
#include "unistd.h"
_syscall2(int, whoami,char*,name,unsigned int,size);
int main(int argc, char** argv){
char buf[30];
int rlen;
rlen = whoami(buf, 30);
printf("%s\n", buf);
return rlen;
}
8.添加到linux-0.11中的系统调用只能在bochs虚拟机中运行,不能在终端上运行,在oslab目录下打开终端,输入下面的命令:
sudo ./mount-hdc
9.然后将上面所有的修改都拷贝到hdc/root目录下,确保在bochs环境下所有修改生效。
cp /home/你自己的用户名/oslab/linux-0.11/include/unistd.h /home/你自己的用户名/oslab/hdc/usr/include/unistd.h
cp /home/你自己的用户名/oslab/linux-0.11/include/linux/sys.h /home/你自己的用户名/oslab/hdc/usr/include/linux/sys.h
cp /home/你自己的用户名/oslab/iam.c hdc/usr/root
cp /home/你自己的用户名/oslab/whoami.c hdc/usr/root
10.在~/oslab/linux-0.11目录下使用make all,编译链接,没报错就行。
11.运行内核,在内核使用gcc编译C,然后运行程序进行验证,编译没报错就行。
然后运行程序进行验证。 下面所示就是成功界面。
(63条消息) 哈工大操作系统实验二:系统调用的实现_哈工大操作系统系统调用_Deteriorate_Kr的博客-CSDN博客https://blog.csdn.net/weixin_53213086/article/details/124946785