2020-2021-1 20209318《Linux内核原理与分析》第四周作业

MenuOS的构造

Linux内核源代码简介

操作系统“两把宝剑”:

  • 中断上下文——保护现场和恢复现场
  • 进程上下文

查看当前系统的Linux内核版本

$ cat /proc/version
或
$ uname -a

Linux内核源码目录结构

  • arch目录:与CPU体系结构相关的子目录列表
  • block目录:存放Linux存储体系中关于块设备管理的代码
  • crypto目录:存放常见的加密算法的C语言代码
  • Documentation目录:存放一些文档
  • drivers目录:驱动目录,里面分门别类地存放了Linux内核支持的所有硬件设备的驱动源代码
  • firmware目录:固件
  • fs目录:文件系统,列出了Linux支持的各种文件系统的实现。
  • include目录:头文件目录,存放公共的头文件
  • init:存放Linux内核启动时的初始化代码
  • ipc目录:IPC是进程间通信,ipc目录里面是Linux支持的IPC的代码实现
  • kernel目录:kernel意思是内核,这个文件夹存放内核本身需要的一些核心代码文件,包括进程号pid等
  • lib目录:公用的库文件
  • mm目录:内存管理
  • net目录:存放网络相关的代码

构造一个简单的Linux内核

$ cd ~/LinuxKernel/
$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

使用gdb跟踪调试内核

启动内核

$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 
#   -S CPU初始化之前冻结起来
#   -s 在1234端口上创建一个gdb-server 

启动gdb

(gdb)file linux-3.18.6/vmlinux 
#在gdb界面中target remote之前加载符号表

(gdb)target remote:1234
#用1234这个端口进行连接

(gdb)break start_kernel
#在start_kernel处设置断点

start_kernel()函数

函数分析

setup_arch(&command_line);   //设置与初始化硬件体系相关的环境并调用

sched_init()                 //初始化调度器,先于中断开始前

printk(boot_command_line);   //提取分析核心启动参数过程(从
bootloader 中传递)

trap_init();                  //自陷入口函数初始化,针对此版本arm中直接return

early_irq_init();              //中断初始化过程

init_IRQ();          

init_timers();                //初始化定时器,开启定时器软中断服务以及注册服务程序以及初始化各CPU中的tev_base等init_timers()->run_timer_softirq()->__run_timers() 

timekeeping_init(); 

time_init(); //设置定时器及返回当前时间
console_init() //初步的初始化控制台,此控制台只能打印出一些简单//的启动信息…

mem_init(); //初始化内存并计算可用内存大小

kmem_cache_init(); // 初始化SLAB缓存分配器

calibrate_delay(); //延迟校准,jiffy,记录系统的定时器的节拍数,每变化一次代表了系统定时器2个连续节拍时间的间隔。

fork_init(num_physpages); //初始化max_threads,init_task参数为fork()提供参考

buffer_init(); //初始化块设备读写缓冲区

vfs_caches_init(num_physpages);   //初始化虚拟文件系统 

inode_init() ->files_init() ->mnt_init()...

signals_init(); //初始化内核信号队列….

rest_init(); //最后实际进入reset_init()函数,包括所有剩下的硬件//驱动,线程初始化等过程…这也最终完成//start_kernel//的启动过程。

rest_init()函数

rest_init()新建kernel_init和kthreadd内核线程。
kthreadd函数的任务是管理和调度其他内核线程kernel_thread,所有的内核线程都是直接或间接以kthreadd为父进程。

遇到的问题和理解

本地虚拟机上装不上qemu

解决方法:

建立软连接

$sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu

"0"号进程和"1"号进程的理解

“0号进程”即idle进程,系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程。它创建了1号进程“kernel_init”和其他进程。

“1号进程”即init进程,是第一个用户态进程,通过rest_init()->kernel_init()->run_init_process生成。

参考博客

posted @ 2020-11-01 00:07  20209318赵姝  阅读(113)  评论(0编辑  收藏  举报