571
社区成员
发帖
与我相关
我的任务
分享通过以下命令安装实验所需要的工具
sudo apt install build-essential gcc-multilib
sudo apt install qemu
sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev
利用老师所给的资料,通过给Linux内核打补丁的方式,让Linux内核执行我们自定义的内核程序,打补丁命令如下(Linux-5.4.34内核与补丁处于同级目录下,下列命令是在Linux-5.4.34/目录下执行):
patch -p1 < ../mykernel-2.0_for_linux-5.4.34.patch
通过以下命令对内核进行编译
make defconfig # Default configuration is based on 'x86_64_defconfig'
make -j$(nproc)# 编译完成后会生成系统镜像
下图是编译完成生成系统镜像的结果

通过Qemu运行上面生成的系统镜像
qemu-system-x86_64 -kernel arch/x86/boot/bzImage
运行结果如下

我们通过更改Linux内核入口执行点为我们自定义的my_start_kernel函数,其中my_start_kernel函数调用my_process函数,在my_process中完成进程切换,核心代码如下:
//将task[0].thread.ip设置为my_process的入口地址
task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process;
//执行完ret指令后,task[pid].thread.ip的值也就是my_process入口地址会赋值给rip
asm volatile(
"movq %1,%%rsp\n\t" /* set task[pid].thread.sp to rsp */
"pushq %1\n\t" /* push rbp */
"pushq %0\n\t" /* push task[pid].thread.ip */
"ret\n\t" /* pop task[pid].thread.ip to rip */
: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) /* input c or d mean %ecx/%edx*/
);
//实现进程切换的关键汇编代码
//通过我们定义的进程双向循环链表中的prev跟next指针完成进程切换
asm volatile(
"pushq %%rbp\n\t" /* save rbp of prev */
"movq %%rsp,%0\n\t" /* save rsp of prev */
"movq %2,%%rsp\n\t" /* restore rsp of next */
"movq $1f,%1\n\t" /* save rip of prev */
"pushq %3\n\t"
"ret\n\t" /* restore rip of next */
"1:\t" /* next process start here */
"popq %%rbp\n\t"
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
);
实验二所需要的工具,在实验一中已完成安装。按照老师所给的步骤,完成内核选项的配置:打开Debug、关闭KASLR。
计算机加电启动首先由Bootloader加载内核,BootLoader紧接着挂载内存根文件系统,所以现在需要通过Busybox制作一个根文件系统
cd busybox-1.28.1 #安装完成busybox后,进入busybox目录
make menuconfig #会出现一个图形化界面,将其中的Setting设置为Build static binary
make -j$(nproc) && make install #完成编译安装
下图显示编译安装完成

mkdir rootfs #在busybox1.28.1目录下生成rootfs目录
cd rootfs
cp ../_install/* ./ -rf
mkdir dev proc sys home
sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
然后在busybox-1.28.1/rootfs目录下添加一个init文件,文件内容如下:
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo "Wellcome SA21225330's OS!"
echo "--------------------"
echo "Copyright by mengning@ustc.edu.cn"
cd home
/bin/sh
#给init脚本添加可执行权限,在busybox-1.28.1/rootfs目录下执行
chmod +x init
#打包成内存根文件系统镜像,在busybox-1.28.1/rootfs目录下执行
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
#测试挂载根文件系统,看内核启动完成后是否执行init脚本
#在linux-5.4.34跟busybox-1.28.1文件同级目录下执行
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd ./busybox-1.28.1/rootfs.cpio.gz
下图显示init脚本成功执行

qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd ./busybox-1.28.1/rootfs.cpio.gz -S -s
执行完上述命令后,可以看到Qemu处于暂定状态。

再打开一个命令行窗口,启动gdb,把内核符号表加载进来,建立连接
cd linux-5.4.34/
gdb vmlinux
(gdb) target remote:1234
(gdb) b start_kernel
从下图中可以看到成功在Linux内核入口执行点start_kernel函数断点并显示信息

做完这两个实验,只能说浅浅入门了Linux内核。虽然孟老师给出了实验的运行代码和执行步骤,但是起初自己做的时候还是走了不少弯路,比如:
下面是学习Linux操作系统的一些收获和感想
由于之前对Linux内核了解的不多,所以实时上课的时候,很多内容当时听不懂,需要反复观看几遍录播才能明白
孟老师的mykernel目前只是简单实现了进程管理功能,对于内存管理和文件管理没有涉及。后面还是希望能看到孟老师能够给出这两部分的实验
Linux最本质的东西在于自由和开放,可以获取所有的源代码,侯捷老师说过”源码面前,了无秘密“。Linux内核上百万行的代码令学习曲线变的陡峭,不禁令人发憷。孟老师的mykernel从成千上万行的代码中抽丝剥茧,实现了一个精简版的进程调度功能,让我找到了一个着手点
开始用Source Insight阅读源代码的时候,自己会专注于一个子系统就一头扎到实际的代码行中去,但由于牵涉的知识很广,会碰到很多困难,容易产生挫败感,一个函数体中可能掺杂着其他各个子系统方面设计理念(多是大量相关的数据结构或者全局变量,用于支撑该子系统的管理工作)下相应的代码实现,这个时候看到这些东西,纷繁芜杂,没有头绪很难理解,会产生很多疑问
后来阅读了陈莉君老师所译的《Linux内核设计与实现》,整体上了解了Linux内核对进程、内存、文件的管理,阅读完后,只能说能够看懂一些源代码。这本书适合对Linux内核了解较少的学生阅读
后来又阅读了陈莉君老师所译的《深入理解Linux内核》部分内容,这本书很详细,但也是有难度的,需要反反复复看好几遍才能理解。纸上得来终觉浅,获得的都是一些理论知识,实践部分目前还是有些欠缺
经过一个学期的学习,只能说刚刚入门了Linux内核,越深入Linux内核,越发现设计者的厉害之处。我们只不过是站在巨人的肩膀上去学习前辈留下来的知识,只希望有一天能够爬上巨人的肩膀
作者:330