linux操作系统分析(二):Linux内核5.0系统调用处理过程分析

学号239
原创作品,转载请注明出处。
本实验资源来源: https://github.com/mengning/linuxkernel/

一、 实验环境

Ubuntu 18
VMware workstation
实验要求:https://github.com/mengning/linuxkernel/blob/master/2019.md

二、linux5.0内核编译

1.下载linux5.0内核并解压
mkdir linuxkernel
cd linuxkernel
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.2tar.xz
xz -d linux-5.0.2.tar.xz
tar -xvf linux-5.0.2.tar
2.配置并编译Linux内核
cd linux-5.0.2
make i386_defconfig  #这步很重要
make menuconfig

此时出现问题
在这里插入图片描述
安装

sudo apt-get install ncurses-dev

之后再出现问题
在这里插入图片描述
安装

sudo apt-get install flex

出现问题
在这里插入图片描述
安装

sudo apt-get install bison

之后make menuconfig,找到kernel hacking,->Compile-time checks and compiler options,选择 [*]compile the kernel with debug info
在这里插入图片描述
在这里插入图片描述
然后make -j8,缺什么装什么

3.制作根文件系统
cd ~/Documents/linux-5.0.2
mkdir rootfs
git clone https://github.com/mengning/menu.git  
cd menu
gcc -o init linktable.c menu.c test.c -m32 -static –lpthread
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

启动Menu os

cd ~/Documents/linux-5.0.2
qemu-system-i386 -kernel arch/x86/boot/bzImage -initrd rootfs.img

在这里插入图片描述

4.跟踪调试内核启动
qemu-system-i386 -kernel linux-5.0.2/arch/x86/boot/bzImage -initrd rootfs.img -S -s -append nokaslr

打开一个新的终端输入

cd linuxkernel/linux-5.0.2
gdb vmlinux
(gdb) target remote:1234

可以看到内核被成功启动
在这里插入图片描述

三、跟踪系统调用

1.增加系统调用

学号后两位39,在/usr/include/asm/unistd_32.h中可查得#define __NR_mkdir 39,mkdir系统调用作用是新建一个目录
函数原型:

#include <sys/stat.h>
int mkdir(const char *pathname, mode_t mode);

mkdir()函数以mode方式创建一个以参数pathname命名的目录,mode定义新创建目录的权限。
更改menu-master/main.c代码:

int _mkdir(int argc, char *argv[])
{
        int returnValue = 0;
        char *dirName = "new dirAsm";
        mode_t mode = S_IRWXU;
        asm
        (
                "movl $39, %%eax\r\n" /*将39号系统调用号放到eax寄存器中*/
                "movl %1, %%ebx\r\n"/*将第一个参数文件名的地址,存入ebx寄存器*/
                "movl %2, %%ecx\r\n"/*将第二个参数文件夹的访问权限存入ecx寄存器*/
                "int $0x80\r\n"
                "movl %%eax,  %0"/*最后将返回值放入returnValue变量中*/
                :"=m"(returnValue)
                :"d"(dirName),"D"(mode)/*使用edx寄存器保存dirName的地址,edi保存mode*/
        );
       printf("%d\n",returnValue);
        return 0;
}
int main()
{
	...
	...
	MenuConfig("mkdir","creat new catalogue",_mkdir);
}

重新编译制作rootfs.img,并启动

qemu -kernel linux-5.0.2/arch/x86/boot/bzImage -initrd rootfs.img -s -S -append nokaslr

可以看到创建了一个新目录new dirAsm
在这里插入图片描述

2.跟踪系统调用
qemu-system-i386 -kernel linux-5.0.2/arch/x86/boot/bzImage -initrd rootfs.img -S -s -append nokaslr

打开一个新的终端输入

cd linuxkernel/linux-5.0.2
gdb vmlinux
(gdb) target remote:1234
(gdb)b sys_mkdir 
(gdb)c

在这里插入图片描述
在这里插入图片描述
可以看出,当调用一个系统调用时,CPU从用户态切换到内核态并开始执行一个system_call和系统调用内核函数。在Linux中通过执行int 0x80来触发系统调用,内核为每个系统调用分配一个系统调用号,用户态进程必须明确指明系统调用号,需要使用EAX寄存器来传递。
mkdir系统调用的流程是:
(1) 首先用户调用mkdir API
(2) 在API的具体实现里面会调用39号系统调用,使用int $80软中断进入内核态
(3) 此时会压入用户的栈顶地址,当前状态字,和CS:EIP。
(4) 然后使用SAVE ALL保存现场,内核进程根据用户的系统调用号,查找系统调用表(sys_call_table),找到中断处理子程序的地址,并且进入内核函数
(5) 完成调用中断处理子程序后,使用RESTORE ALL还原现场,返回调用的用户态空间
在这里插入图片描述

四、总结

1.系统调用是一个用户态到内核态再到用户态的过程
2. Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。用户可以通过系统调用命令在自己的应用程序中调用它们。从某种角度来看,系统调用和普通的函数调用非常相似。区别仅仅在于,系统调用由操作系统核心提供,运行于核心态;而普通的函数调用由函数库或用户自己提供,运行于用户态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值