Linux5.0系统调用过程分析实验

学号307
本实验来源 https://github.com/mengning/linuxkernel/

实验环境
Ubuntu虚拟机:运行环境,本次使用Parallels Desktop安装的Ubuntu18

QEMU:本次使用的模拟器,运行内核代码

gdb断点调试工作

一、实验过程

1.编译内核

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.1.tar.xz
xz -d linux-5.0.1.tar.xz
tar -xvf linux-5.0.1.tar //得到内核文件
cd linux-5.0.1

在这里插入图片描述make menuconfig
在这里插入图片描述
在这里插入图片描述

2.制作img文件
在linux-5.0.1目录下:

    mkdir rootfs
    git clone https://github.com/mengning/menu.git
    cd menu
    gcc -o init linktable.c menu.c test.c -m32 -static
    cd ../rootfs
    cp ../menu/init ./
    find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

3.虚拟机加载内核

make

在这里插入图片描述

  qemu-system-i386 -kernel bzImage -initrd rootfs.img

在这里插入图片描述
4.跟踪调试内核启动

qemu-system-i386 -kernel bzImage -initrd rootfs.img -S -s -append nokaslrcd linux-5.0.1
cd linux-5.0.1
gdb
(gdb)file linux-5.0.1/vmlinux
(gdb)target remote:1234
(gdb)break start_kernel
(gdb)c

在这里插入图片描述

5.测试用例
我的学号后2位是07,对应的系统函数是getslimit(int resource, struct rlimit *rptr),用于获得进程能够创建的各种系统资源的限制使用量。函数的每一次调用都会制定一个资源以及一个指向下列结构的指针,其结构如下:

struct rlimit{  
    rlim_t rlim_cur;   //soft limit: current limit  
    rlim_t rlim_max;  //hard limit: maximum value for rlim_cur  
}  

resource参数取下列值之一:
在这里插入图片描述
采用系统API和汇编两种方式调用该函数,在桌面上建立两个程序:glimit.c和glimitasm.c,如下:
glimit.c:

#include <stdio.h> 
#include <sys/resource.h> 
int main(void){ 
   struct rlimit memoryL;
   getrlimit(RLIMIT_AS,&memoryL);
   printf("%lu,%lu\r\n",(unsigned long)memoryL.rlim_cur,(unsigned long)memoryL.rlim_max);
}

glimitasm.c

#include <stdio.h> 
#include <sys/resource.h> 
int main(void){ 
        int i=0;
        int resource=RLIMIT_AS;
        struct rlimit memoryL;
        asm volatile(
        "mov $0,%%ebx\n\t"
        "mov $0x4c,%%eax\n\t"  /* 调用76号系统调用,即getrlimit*/
        "mov %1,%%ebx\n\t"
        "int $0x80\n\t"
        "mov %%eax,%0\n\t"
        :"=m"(i)
        :"c"(resource),"d"(&memoryL)
        );
        printf("%lu,%lu\r\n",(unsigned long)memoryL.rlim_cur,(unsigned long)memoryL.rlim_max);
 
}

分别编译运行,结果如下:
在这里插入图片描述
两个程序都可以获得进程可用内存最大字节数。

二、实验总结

1)系统调用可以通过编程语言的API和汇编代码实现
2)调用是一个用户态->内核态->用户态的过程
3)当调用一个系统调用时,CPU从用户态切换到内核态并开始执行一个system_call和系统调用内核函数。在Linux中通过执行int 0x80来触发系统调用,内核为每个系统调用分配一个系统调用号,用户态进程必须明确指明系统调用号,需要使用EAX寄存器来传递。
4)系统调用可能需要参数,但是不能通过像用户态进程函数中将参数压栈的方式传递,因为用户态和内核态有不同的堆栈,必须通过寄存器的方式传递参数。
5)普通情况下应用程序通过应用编程接口API,而不是直接通过系统调用来编程。
6)操作系统通常是通过中断从用户态切换到内核态。中断就是一个硬件或软件请求,要求CPU暂停当前的工作,去处理更重要的事情。
在x86机器上能够通过int指令进行软件中断。而在磁盘完毕读写操作后会向CPU发起硬件中断。
中断有两个重要的属性,中断号和中断处理程序。中断号用来标识不同的中断,不同的中断具有不同的中断处理程序。在操作系统内核中维护着一个中断向量表(Interrupt Vector Table)。这个数组存储了全部中断处理程序的地址,而中断号就是对应中断在中断向量表中的偏移量。
一般地,系统调用都是通过软件中断实现的,x86系统上的软件中断由int $0x80指令产生,而128号异常处理程序就是系统调用处理程序system_call()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值