首页 > 系统服务 > 详细

跟踪分析Linux内核5.0系统调用处理过程

时间:2019-03-19 21:57:49      阅读:200      评论:0      收藏:0      [点我收藏+]

学号尾号:155

基于ubuntu kylin 18.10虚拟机

原创作品转载请注明出处https://github.com/mengning/linuxkernel/


实验准备

下载和编译内核

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.tar.xz # 下载内核

# 解压文件
xz -d linux-5.0.1.tar.xz
tar -xvf linux-5.0.tar.xz
cd linux-5.0

# 编译内核
make i386_defconfig

此处出现报错:
技术分享图片

执行以下命令

apt-get install flex

再次执行

make i386_defconfig

出现报错
技术分享图片

执行以下命令

apt-get install bison

再次执行

make i386_defconfig
make

出现报错
技术分享图片
执行以下命令

apt-get install libssl-dev

再次执行

make

等待一段时间后,控制台会输出如下信息,表示编译完成
技术分享图片

制作根文件系统

cd ..
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
gcc -pthread -o init linktable.c menu.c test.c -m32 -static

此处出现问题:
技术分享图片

apt install gcc-multilib
gcc -pthread -o init linktable.c menu.c test.c -m32 -static

再次出现问题
技术分享图片

apt-get install gcc-4.8 gcc-4.8-multilib g++-4.8 g++-4.8-multilib
gcc -pthread -o init linktable.c menu.c test.c -m32 -static

成功了
技术分享图片

cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

制作成功!
技术分享图片

启动MenuOS

cd ..
qemu -kernel linux-5.0/arch/x86/boot/bzImage -initrd rootfs.img

启动成功!
技术分享图片
---

跟踪系统调用

我的学号尾号是155,在查阅系统调用表后,发现155号系统调用是

#define __NR_sched_getparam 155

函数的原型是

#include <sched.h> 

//该函数用于根据进程号获取进程的调度参数,pid用于指定要获取调度参数的进程号,为0时表示获取当前进程的调度参数
//param用于存储获得的进程调度参数
//返回0时表示成功获得进程的调度参数,返回-1时表示出错,并设置errno
//errno有两种,EPERM:调用进程没有足够的权限来获取调度参数。ESRCH:进程pid不存在。
int sched_getparam(pid_t pid,struct sched_param * param);

struct sched_param
{
    int32_t  sched_priority;//获取调度参数时,此成员将反映分配给线程或进程的优先级
    int32_t  sched_curpriority;//获取调度参数时,此成员将设置为线程或进程当前运行的优先级。这是内核在进行调度决策时使用的值。
    union
    {
        int32_t  reserved[8];
        struct
        {
            int32_t  __ss_low_priority;
            int32_t  __ss_max_repl;
            struct timespec     __ss_repl_period;
            struct timespec     __ss_init_budget;
        }           __ss;
    }           __ss_un;
}

#define sched_ss_low_priority   __ss_un.__ss.__ss_low_priority
#define sched_ss_max_repl       __ss_un.__ss.__ss_max_repl
#define sched_ss_repl_period    __ss_un.__ss.__ss_repl_period
#define sched_ss_init_budget    __ss_un.__ss.__ss_init_budget

对于该系统调用,我们可以写出如下代码对其进行测试

//在menu文件夹中的test.c文件中加入如下代码
#include <sched.h> 
int test_get_param()
{
    struct sched_param param;
    sched_getparam(0,&param);
    
    printf("The original priority of the process is %d\n",param.sched_priority);
}

int main()
{
    PrintMenuOS();
    SetPrompt("MenuOS>>");
    MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
    MenuConfig("quit","Quit from MenuOS",Quit);
    MenuConfig("time","Show System Time",Time);
    MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
    MenuConfig("get_param","根据进程号获取进程的优先级",test_get_param);
    ExecuteMenu();
}

重新制作根文件系统

gcc -pthread -o init linktable.c menu.c test.c -m32 -static
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

使用gdb跟踪调试内核

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

此时启动的qemu窗口是stopped的状态
技术分享图片

另开一个shell窗口

gdb
file vmlinux # target remote之前加载符号表
target remote:1234 # 建立gdb和gdbserver之间的连接,按c让qemu上的Linux系统继续运行
b sys_sched_getparam # 打上断点

技术分享图片

在gdb窗口中输入

c

技术分享图片

在qemu窗口中输入

get_param

技术分享图片

在gdb窗口中输入

c

技术分享图片


系统调用分析

可以看到,sched_getparam系统调用的流程如下:

  1. 用户调用sched_getparam接口
  2. 将系统调用号155放入eax寄存器
  3. 执行int $0x80指令产生一个向量为128的编程异常,进入内核态
  4. 保护现场
  5. 根据系统调用号,查找系统调用表,找到中断处理程序的地址并执行中断处理程序
  6. 恢复现场,进入用户态

由此可以看出,用户态进程是无法访问内核的内存空间的,只有内核态进程才能访问内核。因此当执行系统调用时,必须要先将进程转换成内核态才能执行系统调用,执行完毕后再恢复到用户态。

跟踪分析Linux内核5.0系统调用处理过程

原文:https://www.cnblogs.com/jlcs/p/10561678.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!