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


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

      添加sys_call_table表项:

    sys_iam,sys_whoami
    

      

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

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

    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)添加一行

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

      

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

    #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
    Tip:
    1.命令模式下/__NR ---->命令模式下  /+要查找的字符可以快速定位,n是下一个,N是上一个
    2.'  __NR  '的_是shift加-,这里有两个'_'
    

      然后添加:

    #define __NR_iam 72
    #define __NR_whoami  73
    

      

    然后在linux-0.11/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)!='') i++; if(i>23){ return -EINVAL; } printk("%d ",i); i=0; while((temp[i]=get_fs_byte(name+i))!=''){ i++; } return i; }
    int sys_whoami(char* name,unsigned int size) { int i=0; while (temp[i]!='') i++; if (size<i) return -1; i=0; while(temp[i]!=''){ 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的目录执行
    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地址的数据)
     
  • 相关阅读:
    RecyclerView与各种异步图片加载框架不兼容的问题
    课内上机实验3——括号匹配(栈)
    课内上机实验3——删除重复元素
    课内上机实验3——数组内移动0元素至末尾
    课内上机实验3——M集合问题(队列)
    递归实践1——Cnm组合数计算
    【转】Quine的编写
    【转】fork函数详解
    【转】Makefile详解
    VC++6.0程序安装
  • 原文地址:https://www.cnblogs.com/coderlynn/p/9127632.html
Copyright © 2020-2023  润新知