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
来初始化子进程的内核栈,设置pid
ret_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