Linux实验总结:
运行mykernel
环境:ubuntu 18.04,实测21.04的默认GCC版本编译完无法生成bzImage
步骤
wget https://raw.github.com/mengning/mykernel/master/mykernel-2.0_for_linux-5.4.34.patch
sudo apt install axel
axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz
xz -d linux-5.4.34.tar.xz
tar -xvf linux-5.4.34.tar
cd linux-5.4.34
patch -p1 < ../mykernel-2.0_for_linux-5.4.34.patch
sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev
make defconfig # Default configuration is based on 'x86_64_defconfig'
make -j$(nproc) # 编译的时间比较久哦
sudo apt install qemu qemu-system-x86 # install QEMU
qemu-system-x86_64 -kernel arch/x86/boot/bzImage
结果

基于mykernel的极简内核
修改内核代码,使用时间片轮转调度多道程序
下载mykernel代码,并将mypcb.h; mymain.c; myinterrupt.c复制替换到Linux内核中的mykernel文件夹,重新编译
make defconfig
make -j$(nproc)
qemu-system-x86_64 -kernel arch/x86/boot/bzImage

Debug Linux Kernel
根据参考资料PPT上的步骤,在Linux内核文件夹编译内核make并make install,使用qemu验证无文件系统时的内核,会出现内核异常,之后配置根文件系统。

完成内存跟系统镜像后,不要手贱更新系统,否则将无法正常启动。

跟踪启动



start_kernel()静态创建0号进程init_task,最终成为idle进程,init_task进程的内核栈通过静态方式分配rest_init(),Linux内核初始化的尾声,做了很多剩下的初始化工作。调用kernel_thread(),通过fork创建内核进程,1号进程init和2号进程kthreadd,其中调用了kernel_init()kernel_init(),通过调用do_execve()来执行根文件系统的init文件,其中调用了run_init_process()run_init_process()通过execve()来运行init程序kthreadd用来管理系统的资源
跟踪系统调用
测试代码
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[]){
char buffer[80] = "/tmp/test";
int fd = open(buffer, O_RDONLY);
int size = read(fd, buffer, sizeof(buffer));
close(fd);
}
静态编译
gcc -g -static -o test_open test_open.c
使用gdb调试,使用disas命令查看汇编

可见在0x4488a0位置调用了open64,打开open64



跟踪fork
- 打断

- 跟踪


copy_process复制父进程信息wake_up_new_task将子进程加入调度队列等待分配CPU资源copy_process调用dup_task_struct复制父进程的数据结构、以及进行初始化、信息检查等工作copy_process调用copy_thread来初始化子进程的内核栈,设置pidret_from_fork结束。
动态链接库
装载时动态的shared lib
- 照着PPT创建
shlibexample.h/shlibexample.c,注意注释与中文符号 - 编译生成
.so文件gcc -shared shlibexample.c -o libshlibexample.so
运行时动态的dynamic lib
- 照着PPT创建
dllibexample.h / dllibexample.c,注意注释与中文符号 - 编译生成
.so文件gcc -shared dllibexample.c -o libdllibexample.so
测试动态链接
-
创建测试文件
main.c,(PPT上的代码不全,得看src文件夹里的源码)#include <stdio.h> #include "shlibexample.h" #include <dlfcn.h> int main() { printf("This is a Main program!\n"); /* 装载时动态链接 */ printf("Calling SharedLibApi() function of libshlibexample.so!\n"); SharedLibApi(); /* 运行时动态链接 */ void * handle = dlopen("libdllibexample.so",RTLD_NOW); if(handle == NULL) { printf("Open Lib libdllibexample.so Error:%s\n",dlerror()); return FAILURE; } int (*func)(void); char * error; func = dlsym(handle,"DynamicalLoadingLibApi"); if((error = dlerror()) != NULL) { printf("DynamicalLoadingLibApi not found:%s\n",error); return FAILURE; } printf("Calling DynamicalLoadingLibApi() function of libdllibexample.so!\n"); func(); dlclose(handle); return SUCCESS; } -
将
libshlibsxample.so复制到/usr/lib -
$export LD_LIBRARY_PATH=$PWD将当前目录加入默认路径,否则main找不到依赖的库文件,当然也可以将库文件复制到默认路径下。 -
编译
main.c并执行 -

总结
感觉课程中的Linux内核更偏向于嵌入式系统中的Linux,在我的理解中,Linux的组成部分包括:进程管理(切换、调度)、内存分配与管理、系统内进程通信与同步机制、时钟与中断、驱动程序与模块、文件系统、网络以及系统调用等
课程主要讲解了Linux系统的编译与启动过程、进程管理、程序执行与文件系统、时钟与中断、驱动程序与模块、中断与系统调用等。即使有的内容在好几个课都接触过,但是记不住确实还是记不住= =。
406
参考资料庖丁解牛Linux操作系统分析https://gitee.com/mengning997/linuxkernel
本文介绍使用mykernel在Ubuntu环境下编译Linux内核的过程,实现基于时间片轮转调度的多道程序运行,并通过QEMU进行测试。此外,还涉及系统调用跟踪、动态链接库的使用等内容。
1238

被折叠的 条评论
为什么被折叠?



