用户态是用户程序执行时机器所处的状态,是具有较低特权的执行状态,它只能执行规定的指令,只能访问指定的寄存器和存储区。
核心态是操作系统管理程序执行时机器所处的状态。它具有较高的特权,能执行包括特权指令的一切指令,能访问所有寄存器和存储区。特权指令只能由操作系统内核使用,如IO指令、设置中断屏蔽指令、清内存指令、存储保护指令和设置时钟指令
划分核心态和用户态后,这两类程序以及各自的存储空间被严格区分。当用户态想要调用核心态程序时,可以通过系统调用,即执行访问核心态的命令,引起中断,由中断系统转入操作系统内的相应程序
注意,由于使用实验一的搭建的内核会出现很多莫名的错误,所以重新使用实验一下载好的tar压缩包重新解压搭建。另外需要的工具也与实验一一致,详见https://www.cnblogs.com/junljw/p/12878158.html
tar -xvf linux-5.4.34.tar
cd linux-5.4.34
make defcon?g
make menucon?g
选中Kernel hacking --->
再选中Compile-time checks and compiler options --->
勾选Compile the kernel with debug info 和 Provide GDB scripts for kernel debugging
返回上一页,勾选Kernel debugging
返回首页,选中Processor type and features ---->
关闭Randomize the address of the kernel image (KASLR)
保存后退出即可
make -j$(nproc)#时间较长,耐心等待
qemu-system-x86_64 -kernel arch/x86/boot/bzImage
此时内核不能正常加载属于正常
axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2
注意请下载在根文件目录,而不是linux-5.4.34内
tar -jxvf busybox-1.31.1.tar.bz2
cd busybox-1.31.1
make menucon?g
选中Settings --->
然后勾选Build static binary (no shared libs)
make -j$(nproc) && make install #编译安装
mkdir rootfs
cd rootfs
cp ../busybox-1.31.1/_install/* ./ -rf
mkdir dev proc sys home
sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo "Wellcome MengningOS!"
echo "--------------------"
cd home
/bin/sh
chmod +x init
?nd . -print0 | cpio --null -ov --format=newc | gzip -9 > ../ rootfs.cpio.gz #打包成内存根文件系统镜像
下面在根目录下用指令进入看是否成功
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz
由于我的学号尾数为40,首先查看了sendfile指令
但由于sendfile会触发read和write的系统调用,引发多次上下文切换,不易于跟踪,查看了140的系统调用为getpriority
getpriority函数原型为int getpriority( int which, int two );
该函数返回一组进程的优先级。参数 which 和 who 组合确定返回哪一组进程的优先级。which 的可能取值以及 who 的意义如下:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
int stat_val = 0;
int oldpri, newpri;
printf("nice study\n");
pid = fork();
switch( pid ) {
case 0:
printf("Child is running, Curpid is %d, Parentpid is %d\n",
pid, getppid());
oldpri = getpriority(PRIO_PROCESS, getpid());
printf("Old priority = %d\n", oldpri);
newpri = nice(2);
printf("New priority = %d\n", newpri);
exit(0);
case -1:
perror("Process creation failed\n");
break;
default:
printf("Parent is running,Childpid is %d, Parentpid is %d\n", pid, getpid());
break;
}
wait(&stat_val);
exit(0);
}
输出结果如下:
重新打包根文件目录
?nd . -print0 | cpio --nll -ov --format=newc | gzip -9 > ../ rootfs.cpio.gz
启动内核
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"
此时内核暂停于此,再另开一个终端进入gdb调试
·gdb vmlinux·
·target remote:1234·
查看得知系统调用入口为__x64_sys_getpriority,设置断点
b __x64_sys_getpriority
单步调试
显示步骤详情
getpriority函数内有两个参数,其首先将其压栈值RDI、RSI寄存器,然后发生中断,从__x64_sys_getpriority入口进入,最后获取的优先级返回。该过程与理论分析基本一致。
原文:https://www.cnblogs.com/junljw/p/12951862.html