哈工大操作系统实验2系统调用

系统调用笔记

哈工大操作系统实验2系统调用_第1张图片
用户态只能通过系统调用去访问内核,即只能通过中断处理访问, INT 0X80
哈工大操作系统实验2系统调用_第2张图片
就是我们的C语言程序,调用一个在unistd.h定义的宏,_syscall*()*代表的是参数的个数,这个宏的意义差不多等于创建一个函数。这个函数只有一个代码就是int 0x80。

系统调用read,宏展开后(就是创建了一个read函数)
哈工大操作系统实验2系统调用_第3张图片
int 0x80是由main.c中sched_init()创建的。其实就是初始化好了IDT表
哈工大操作系统实验2系统调用_第4张图片
INT 0X80会根据进入内核,调用system_call. system_call 就会去根据__NR_##name去查表执行相应的处理函数
哈工大操作系统实验2系统调用_第5张图片

实验记录

实验要求我们添加两个系统调用,iam()和whoami()
运行结果

$ ./iam lizhijun
$ ./whoami
lizhijun 

1

首先是编写最外层的用户程序iam.c和whoami.c
注意 _syscall 要写在 #define __ LIBRARY __ #include下面

iam.c

哈工大操作系统实验2系统调用_第6张图片

whoami.c

哈工大操作系统实验2系统调用_第7张图片

2

有了用户程序,我们就要编写系统调用sys_iam和sys_whoami
在linux-0.11/kernel下添加who.c

#define __LIBRARY__
#include 
#include 
#include 
 
 
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 (sizetemp
i++;
    }
    return i;
}

3 修改相关的头文件

linux-0.11/include/linux/sys.h

这个头文件修改的意义是把 iam与whoami两个函数加到全局变量,和中断函数表中就可以了,中断被调用的时候,先查找中断向量表,
找到相应的函数名,调用其函数。
哈工大操作系统实验2系统调用_第8张图片

linux-0.11/kernel/system_call.s

这里要修个nr_system_calls 本来是72 也就是有72个系统调用函数,我们加了两个所以改成74
哈工大操作系统实验2系统调用_第9张图片

hdc/usr/include/unistd.h

unistd.h 不能直接在oslab直接直接修改,而需要在虚拟机中修改,在oslab中有一个mount-hdc脚本
运行sudo ./mount-hdc 可以把虚拟机硬盘挂载在oslab/hdc 目录下。
在hdc/usr/include 目录下修改unistd.h
哈工大操作系统实验2系统调用_第10张图片

4 就是修改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
Makefile修改后,和往常一样“make all”就能自动把who.c加入到内核中了。如果编译时提示who.c有错误,就说明修改生效了。所以,有意或无意地制造一两个错误也不完全是坏事,至少能证明Makefile是对的。

5 编译运行

编译必须在虚拟机下编译,因为你修改的unistd.h只在虚拟机生效

gcc iam.c -o iam
gcc whoami.c -o whoami

哈工大操作系统实验2系统调用_第11张图片

总结

添加一个系统调用主要是

1.编写用户程序,这个用户程序需要包含_syscall* 宏(创建一个函数),然后调用这个函数
2.编写系统调用函数放到linux-0.11/kernel
3.各种相关头文件的修改
linux-0.11/include/linux/sys.h添加extern int sys_xxx和添加syscall_table[]
linux-0.11/kernel/system_call.s 修改nr_system_calls(syscall_table中的系统调用函数个数)
hdc/usr/include/unistd.h 其实也就是编译的库文件 添加__ NR_xx 系统调用号
linux-0.11/kernel下的MakeFile修改OBJS和Dependencies

参考博客

https://blog.csdn.net/wangyi_lin/article/details/6921110
https://www.cnblogs.com/coderlynn/p/9127632.html

实验指导书

https://hoverwinter.gitbooks.io/hit-oslab-manual/content/sy2_syscall.html

实验环境:实验楼

你可能感兴趣的:(操作系统实验)