系统调用 -- 哈工大李治军操作系统实验2

 
 
实验环境是 实验楼的 地址https://www.shiyanlou.com/courses/115
 
 
首先解压oslab下的压缩包 执行 tar zxvf +压缩包名字
 
1.首先修改oslab/linux-0.11/include下的linux文件
 
  添加两个extern:
1
2
extern int sys_iaml
extern int sys_whoami

  添加sys_call_table表项:

1
sys_iam,sys_whoami

  

注:fn_ptr是函数类型指针
在include/linux/sched.h中定义
1
typedef int (fn_ptr*)();

  sys_call_table是中断服务程序调用系统调用要查的表。表项是函数指针,长度为4字节。中断服务程序执行call来调用系统调用:

1
call _sys_call_table(,%eax,4) //a(,%eax,4)=a+4*eax , 每个表项4字节所以第i个系统调用的偏移是i*4

  2.linux-0.11/kernel下的system_call.s,将nr_system_calls修改为74(添加了两个系统调用)

3.修改kernel下的makefile文件,修改两处
     1)添加who.o

     2)添加一行

 

1
2
3
4
who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h
 
//图错了!!!!
//图中who.o后面少了个冒号!!!!

  

4.系统调用编号使用的宏定义,例如在unistd.g中 :

 

1
#define NR_CLOSE 6   //close是sys_call_table第7个

  添加系统调用需要修改unistd.h文件,不能直接在机器中修改而是在虚拟机文件系统中修改

 

oslab下的hdc-0.11-new.img是0.11内核启动后的根文件系统镜像文件,相当于在bochs虚拟机里装载的硬盘。在Ubuntu上访问其内容的方法是
$ sudo ./mount-hdc
之后,hdc目录下就是和0.11内核一模一样的文件系统了,可以读写任何文件(可能有些文件要用sudo才能访问),卸载这个文件系统:
$ sudo umount hdc
 
所以切换到oslab目录下执行sudo ./mount-hdc,然后切换到hdc下就会看到和linux一样的文件目录结构了。
 
切换到hdc/usr/include下,vim unistd.h
1
2
3
Tip:
1.命令模式下/__NR ---->命令模式下  /+要查找的字符可以快速定位,n是下一个,N是上一个
2.'  __NR  '的_是shift加-,这里有两个'_'

  然后添加:

 

1
2
#define __NR_iam 72
#define __NR_whoami  73

  

然后在linux-0.11/kernel下添加who.c,包含两个 系统调用

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#define __LIBRARY__
#include <unistd.h>
#include <errno.h><br>#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;
 
}<br>
 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.然后编写iam.c和whoami.c 放在 hdc下的任意位置
     1)whoami.c:

 

     2)iam.c

 

然后执行  sudo umount hdc 解除挂载

 

最后切换到oslab下执行make
切换到oslab下执行./run运行虚拟机
切换到iam.c和whoami.c的目录执行
1
2
gcc iam.c -o iam
gcc whoami.c -o whoami

  

总结:
 

 

main将eax寄存器置72(系统调用编号),触发int 0x80中断 (实际是在库函数中做的)
 
int 0x80指令查IDT表(中断向量表,由内核初始化)发现DPL=3 ,而CPL = 3(用户态)可以执行
 
于是将这个IDT表项的段选择子CS  给CS寄存器(例如段选择子为8H=1000,后两位为CPL,特权级别CPL置0),入口函数偏移给IP寄存器
 
然后执行中断服务程序,中断服务程序调用sys_whoami
 
sys_whoami里此时可以访问内核态数据(访问100地址的数据)
 

 

 

 

 

 

posted @   CoderLynn  阅读(3806)  评论(0编辑  收藏  举报
编辑推荐:
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
阅读排行:
· Cursor预测程序员行业倒计时:CTO应做好50%裁员计划
· 想让你多爱自己一些的开源计时器
· 大模型 Token 究竟是啥:图解大模型Token
· 用99元买的服务器搭一套CI/CD系统
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争
点击右上角即可分享
微信分享提示