深入理解系统调用
Posted cyh2czj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解系统调用相关的知识,希望对你有一定的参考价值。
实验内容
- 找一个系统调用,系统调用号为学号最后2位相同的系统调用
- 通过汇编指令触发该系统调用
- 通过gdb跟踪该系统调用的内核处理过程
- 重点阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及重点关注系统调用过程中内核堆栈状态的变化
准备环境
利用上次实验下载的linux内核,重新编译,再制作根文件系统,并准备好触发系统调用的程序。
首先配置内核编译选项
make defcon?g # Default con?guration is based on ‘x86_64_defcon?g‘ make menucon?g # 打开debug相关选项 Kernel hacking ---> Compile-time checks and compiler options ---> [*] Compile the kernel with debug info [*] Provide GDB scripts for kernel debugging [*] Kernel debugging # 关闭KASLR,否则会导致打断点失败 Processor type and features ----> [] Randomize the address of the kernel image (KASLR)
编译内核
make -j$(nproc) # nproc gives the number of CPU cores/threads available # 测试?下内核能不能正常加载运?,因为没有?件系统终会kernel panic qemu-system-x86_64 -kernel arch/x86/boot/bzImage # 此时应该不能正常运行
制作根文件系统
#下载 axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2 tar -jxvf busybox-1.31.1.tar.bz2 cd busybox-1.31.1 #制作根文件系统 make menucon?g #记得要编译成静态链接,不?动态链接库。 Settings ---> [*] Build static binary (no shared libs) #然后编译安装,默认会安装到源码?录下的 _install ?录中。 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/
准备init脚本文件放在根文件系统跟目录下(rootfs/init),添加如下内容到init文件。
复制代码 #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys echo "Wellcome TestOS!" echo "--------------------" cd home /bin/sh #给init脚本添加可执行权限 chmod +x init
我的学号后两位是17,对应的系统调用是pread函数,pread函数用于从打开文件的指定位置开始读取数据,函数原型如下:
#include <unistd.h> ssize_t pread(int filedes, void *buf, size_t nbytes, off_t offset);
返回值:若读取成功则返回实际读到的字节数,若已到文件结尾则返回0,若出错则返回-1。
参数:
1、filedes文件标识符;
2、*buf存放读出数据的缓冲区;
3、nbytes要读取的字节数;
4、offset文件指针。
#include<stdlib.h> #include<unistd.h> #include<fcntl.h> int main() { int fd,i,count; char buf[20]; fd=open("/home/world",O_RDWR); printf("use pread "); // pread(fd,buf,10,0); asm volatile( "mov $0x0, %%rcx " //参数4 "mov $0x0a, %%rdx " //参数3 "mov %2, %%rsi " //参数2 "mov %1, %%rdi " //参数1 "mov $0x11, %%eax " //传递系统调用号 "syscall " //系统调用 "mov %%rax, %0 " //结果存到count中 :"=m"(count) //输出 :"m"(fd),"p"(&buf)//输入 ); buf[20]=‘