《Linux内核分析》期终总结&《Linux及安全》期中总结
《Linux内核分析》期终总结&《Linux及安全》期中总结
【李行之 原创作品 转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000】
前言 学习笔记目录
1.第一周:计算机是如何工作的 http://www.cnblogs.com/shadow135211/p/5219346.html
2.第二周:操作系统是如何工作的 http://www.cnblogs.com/shadow135211/p/5244213.html
3.第三周:构造一个简单的Linux内核MenuOS http://www.cnblogs.com/shadow135211/p/5259476.html
4.第四周:扒开系统调用的三层皮(上) http://www.cnblogs.com/shadow135211/p/5296363.html
5.第五周:扒开操作系统的三层皮(下) http://www.cnblogs.com/shadow135211/p/5325439.html
6.第六周:进程的描述与创建 http://www.cnblogs.com/shadow135211/p/5330762.html
7.第七周:可执行程序的装载 http://www.cnblogs.com/shadow135211/p/5362143.html
8.第八周:系统的一般执行过程 http://www.cnblogs.com/shadow135211/p/5388650.html
一、计算机是如何工作的
1.冯 诺依曼体系结构是指具有存储程序的计算机系统
硬件:CPU与内存通过主线连接;CPU上有一块寄存器叫做IP,该寄存器相当于指针,总是指向内存的代码段;CPU总是执行IP指向的指令然后IP自加一
软件(计算机如何识别指令):通过ABI(程序与计算机的接口界面
2.常见的寻址方式
- 寄存器寻址(操作的都是寄存器):将eax的值直接赋值给edx;
- 立即数寻址:将十六进制的数值123(这个立即数)直接放到edx中(和内存也没有关系);
- 直接寻址:将0x123这个地址所指向的内存数据放到寄存器edx中;
- 间接寻址:将ebx的值作为一个内存地址,这个地址所存储的数据放到edx中;
- 变址寻址:与间接寻址类似,是把ebx的值加上4作为地址
二、操作系统是如何工作的
1.计算机是如何工作的?(总结)——三个法宝
存储程序计算机工作模型,计算机系统最最基础性的逻辑结构;
函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能;函数参数传递机制和局部变量存储
中断,多道程序操作系统的基点,没有中断机制程序只能从头一直运行结束才有可能开始运行其他程序。
2.操作系统两把利剑
- 进程切换
- 中断上下文
三、构造一个简单的Linux系统MenuOS
1.创建及调试步骤:
- 下载安装完后,启动并使它一开始就停止:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
- 然后启动gdb调试,设置断点,单步运行等,这个在后面的学习过程中都会经常使用
2.分析这个内核的启动过程
x86 CPU启动的第一个动作CS:EIP=FFFF:0000H(换算为物理地址为000FFFF0H,因为16位CPU有20根地址线),即BIOS程序的位置;
BIOS例行程序检测完硬件并完成相应的初始化之后就会寻找可引导介质,找到后把引导程序加载到指定内存区域后,就把控制权交给了引导程序;
引导程序BootLoader开始负责操作系统初始化,然后启动操作系统。启动操作系统时一般会指定kernel、initrd和root所在的分区和目录;
内核启动过程包括start_kernel之前和之后,之前全部是做初始化的汇编指令,之后开始C代码的操作系统初始化,最后执行第一个用户态进程init(这里和讲解中以及实际的代码main.c是一致的);
一般分两阶段启动,先是利用initrd的内存文件系统,然后切换到硬盘文件系统继续启动。initrd文件的功能主要有两个:
(1)提供开机必需的但kernel文件(即vmlinuz)没有提供的驱动模块(modules)
(2)负责加载硬盘上的根文件系统并执行其中的/sbin/init程序进而将开机过程持续下去
3.init进程的解析——“道生一,一生二”
- start_kernel创建了cpu_idle,即0号进程
- 0号进程又创建了两个线程kernel_init和kthreadd
- kernel_init即1号进程,这个进程最终启动了用户态
四、用户态&内核态与系统调用的关系
1.用户态、内核态区别
- 在高级别的状态下,代码可以执行特权指令,访问任意的物理地址;一般在Linux中,0xc0000000以上的地址(指的是逻辑地址)空间只能在内核态下访问;
- 在相应的低级别执行状态下,代码的掌控范围会受到限制;
2.系统调用的意义
- 把用户从底层的硬件编程中解放出来
- 极大的提高了系统的安全性
- 使用户程序具有可移植性
3.中断处理程序
- 中断指令会在寄存器上保存一些寄存器的值放入内核堆栈,比如:用户态栈顶地址,标志寄存器,cs:eip。同时,将相关联的中端服务历程的入口加载到cs:eip,把当前的堆栈段esp也加载到CPU里面
- 中断发生之后第一件事就是保存现场;中断处理结束前的最后一件事情就是恢复现场
五、系统调用在内核代码中的工作机制和初始化
1.系统调用机制的初始化
trap_gate函数中,涉及到了系统调用的中断向量和system_call的汇编代码入口;一旦执行int 0x80,CPU直接跳转到system_call
2.简化后便于理解的system_call伪代码
- system_call的位置就在ENTRY(system_call)处;(其他中断的处理过程与此类似)
- syscall_table是系统调用表
- after_call之后,保存返回值
- 要exit的时候,会有一个syscall_exit_work,否则直接返回用户态
3.简单浏览system_call到iret之间的主要代码
- SAVE_ALL:保存现场
- syscall_call:调用了系统调用处理函数
- restore all:恢复现场(因为系统调用处理函数也算是一种特殊的“中断”)
- syscall_exit_work:如3.中所述
- INTERRUPT RETURN:也就是iret,系统调用到此结束
六、可执行程序的装载
1.装载可执行文件之前的工作
- 要先fork一个进程,不然会覆盖shell
- execlp加载一个程序
- shell程序-->execve-->sys_execve,然后在初始化新程序堆栈的时候拷贝进去
- 先传递函数调用参数,再传递系统调用参数
2.sys_execve的内部处理过程
- do_execve
- do_open_exec(filename)打开要加载的文件
- 命令行参数,结构体变量copy到bprm结构体中
- exce_binprm(bprm),关键代码是寻找能解析当前文件的处理模块
- register_binfmt($elf_format)注册这个格式到链表里,然后寻找能处理的模块
- ELF可执行文件默认映射到0x8048000这个地址
- 需要动态链接的可执行文件先加载连接器ld;否则直接把elf文件entry地址赋值给entry即可。
- start_thread(regs,elf_entry,bprm->p)会将CPU控制权交给ld来加载依赖库并完成动态链接;对于静态链接的文件elf_entry是新程序执行的起点
七、进程的切换和一般系统执行过程
1.进程调度的时机
- 中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule()(也就是说,用户态进程只能被动地调度);
- 内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;
- 用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。
2.正在运行的用户态进程X切换到运行用户态进程Y的过程
- 正在运行的用户态进程X
- 发生中断——
(1)save cs:eip/esp/eflags(current) to kernel stack;
(2)then load cs:eip(系统调用的起点,entry of a specific ISR) and ss:esp(point to kernel stack)
- 进入内核代码,SAVE_ALL //保存现场
- 中断处理过程中或中断返回前调用了schedule()(可能不发生,诺发生,则其中的switch_to做了关键的进程上下文切换)
- 标号1之后开始运行上一步中选中的用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行)
- restore_all //恢复现场
- iret - pop cs:eip/ss:esp/eflags from kernel stack
- 继续运行用户态进程Y
3.以ls命令为例,学习Linux系统执行指令的过程
- 在控制台输入ls命令
- Shell程序分析输入参数,确定这是ls
- 调用系统调用fork生成一个shell本身的拷贝
- 调用exec系统调用将ls可执行文件装入内存
- 从系统调用返回
- Shell和ls都得到执行
4.从CPU和内存角度看Linux系统执行
- 执行gets()函数;
- 执行系统调用,陷入内核;
- 等待输入,CPU会调度其他进程执行,同时wait一个I/O中断;
- 敲击ls,发I/O中断给CPU,中断处理程序进行现场保存、压栈等等;
- 中断处理程序发现X进程在等待这个I/O(此时X已经变成阻塞态),处理程序将X设置为WAKE_UP;
- 进程管理可能会把进程X设置为next进程,这样gets系统调用获得数据,再返回用户态堆栈
- 从内存角度看,所有的物理地址都会被映射到3G以上的地址空间:因为这部分对所有进程来说都是共享的
八、收获与遗憾
通过这几周的学习,使我对操作系统有了更加深入的了解。尤其是进程切换的堆栈变化让我印象深刻。系统调用的学习让我对内核的运行机制有了更深的了解与掌握,也认识到了linux与windows的众多不同,受益匪浅。
最大的收获:
- 在自己的动手配置kali虚拟机的过程中不断地发现与解决问题,将实践过程与知识完美结合;
最大的遗憾
- 课程课时有限,想学到的东西更多
《Linux内核分析》期终总结&《Linux及安全》期中总结的更多相关文章
- Linux内核分析——第一章 Linux内核简介
第一章 Linux内核简介 一.Unix的历史 1.Unix系统成为一个强大.健壮和稳定的操作系统的根本原因: (1)简洁 (2)在Unix中,很多东西都被当做文件对待.这种抽象使对数据和对设备的 ...
- Linux内核分析笔记 与Linux内核开发理论
http://www.cnblogs.com/hanyan225/category/308793.html
- 《Linux及安全》期中总结&《Linux内核分析》期终总结
[5216 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK NINE ...
- 《Linux内核分析》期终总结
作者:杨舒雯,原创作品转载请注明出处,<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 目录: 1.通过简 ...
- linux内核分析作业8:理解进程调度时机跟踪分析进程调度与进程切换的过程
1. 实验目的 选择一个系统调用(13号系统调用time除外),系统调用列表,使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 分析汇编代码调用系统调用的工作过程,特别是参数的传递的方 ...
- Linux内核分析作业7:Linux内核如何装载和启动一个可执行程序
1.可执行文件的格式 在 Linux 平台下主要有以下三种可执行文件格式: 1.a.out(assembler and link editor output 汇编器和链接编辑器的输出) ...
- linux内核分析作业6:分析Linux内核创建一个新进程的过程
task_struct结构: struct task_struct { volatile long state;进程状态 void *stack; 堆栈 pid_t pid; 进程标识符 u ...
- linux内核分析作业5:分析system_call中断处理过程
1.增加 Menu 内核命令行 调试系统调用. 步骤:删除menu git clone (tab) make rootfs 这就是我们将 fork 函数写入 Menu 系统内核后的效果, ...
- linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作
一.实验 使用gcc –S –o main.s main.c -m32 命令编译成汇编代码,如下代码中的数字请自行修改以防与他人雷同 int g(int x) { return x + 3; } in ...
随机推荐
- MySQL基本操作命令
数据库的基本操作命令 1.登录MySQL -- 进入数据库的方法一 mysql -uroot -pmysql # mysql 数据库密码(显示) -- 进入数据库的方法二 mysql -uroot - ...
- 4.92Python数据类型之(7)字典
目录 目录 前言 (一)字典的基本知识 ==1.字典的基本格式== (二)字典的操作 ==1.字典元素的增加== ==2.字典值的查找== ==3.字典的修改== ==4.字典的删除== ==5.字典 ...
- Spring boot 直接访问templates中html文件
application.properties 在浏览器中输入http://localhost:8080/index.html 会报一个 因为Spring boot 无法直接访问templates下的文 ...
- Reachability
一.Reachability中介绍了取得/检测网络状态的方法. 二.使用 1.添加源文件:Reachability.h和Reachability.m 2.添加framework———SystemCon ...
- Python getting started guide
Get up in the morning. The first thing is to write a blog, although it uses machine translation, it ...
- 简单Nginx下防跨站、跨目录安全设置,支持PHP 5.3.3以上版本
Nginx下存在跨站和跨目录的问题,跨站和跨目录影响同服务器/VPS上的其他网站. PHP在5.3.3以上已经增加了HOST配置,可以起到防跨站.跨目录的问题. 如果你是PHP 5.3.3以上的版本, ...
- JS的局部变量和全局变量
两段JS代码的区别: <script type="text/javascript"> var a = "Hello"; function test( ...
- Git安装与配置——详细教程1
1.下载Git客户端 想要安装Git首先要下载Git的安装包程序. Git安装包下载地址:https://git-scm.com/downloads/ 2.安装Git 双击安装程序进行安装: a. 欢 ...
- Qt 编程指南 3 信号和槽沟通
https://qtguide.ustclug.org/ 1 信号和槽 所谓信号槽,简单来说,就像是插销一样:一个插头和一个插座.怎么说呢?当某种事件发生之后,比如,点击了一下鼠标,或者按了某个按键, ...
- CentOS 7.x编译安装Nginx1.10.3+MySQL5.7.16+PHP5.2 5.3 5.4 5.5 5.6 7.0 7.1多版本全能环境
准备篇 一.防火墙配置 CentOS 7.x默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭firewall: systemctl stop firewalld.se ...