周子轩 原创作品转载注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
笔记:
- 冯诺依曼体系结构的核心思想是存储程序计算机。在计算机中有两种指令,一是用户指令,一是系统调用。
- Linux是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。
- 当内核运行的时候,系统以内核态进入内核空间执行。而执行一个普通用户程序时,系统将以用户态进入以用户空间执行。
- 在系统中运行的应用程序通过系统调用来与内核通信。
- 三个法宝:
存储程序计算机、函数调用堆栈、中断机制
两把宝剑:中断上下文、进程上下文的切换
- 当硬件设备想和系统通信的时候,它首先要发出-个异步的中断信号去打断处理器的执行,继而打断内核的执行。中断通常对应着一个中断号,内核通过这个中断号查找相应的中断服务程序,并调用这个程序响应和处理中断。
- Linux是一个可移植的操作系统。即大部分C代码与体系结构无关,在许多不同体系结构的计算机上都能够编译和执行。
博客目录:
-
-
冯诺依曼体系结构的核心思想是存储程序计算机。在计算机中有两种指令,一是用户指令,一是系统调用。
-
当用户使用计算机时,计算机根据其汇编的指令一步步运行,当使用系统调用完后,再返回用户模式,保证系统的稳定。
- 程序中执行call的堆栈变化
- 汇编基础
通用寄存器
16位 32位
AX eax 累加器
BX ebx 基址寄存器
CX ecx 计数寄存器
DX edx 数据寄存器
BP ebp 堆栈基址指针
SI esi 变址寄存器
DI edi 变址寄存器
SP esp 堆栈顶指针
-
-
函数调用约定
函数调用约定 | 参数传递顺序 | 负责清理参数占用的堆栈 |
__pascal |
从左到右 |
调用者 |
__stdcall |
从右到左 |
被调函数 |
__cdecl |
从右到左 |
调用者 |
-
三个法宝
存储程序计算机、函数调用堆栈、中断机制
-
两把宝剑
中断上下文、进程上下文的切换
-
- 计算机的启动过程概述
- x86 CPU启动的第一个动作CS:EIP=FFFF:0000H(换算为物理地址为000FFFF0H,因为16位CPU有20根地址线),即BIOS程序的位置。
- BIOS例行程序检测完硬件并完成相应的初始化之后就会寻找可引导介质,找到后把引导程序加载到指定内存区域后,就把控制权交给了引导程序。这里一般是把硬盘的第一个扇区MBR和活动分区的引导程序加载到内存(即加载BootLoader),加载完整后把控制权交给BootLoader。
- 引导程序BootLoader开始负责操作系统初始化,然后起动操作系统。启动操作系统时一般会指定kernel、initrd和root所在的分区和目录,比如root (hd0,0),kernel (hd0,0)/bzImage root=/dev/ram init=/bin/ash,initrd (hd0,0)/myinitrd4M.img
- 内核启动过程包括start_kernel之前和之后,之前全部是做初始化的汇编指令,之后开始C代码的操作系统初始化,最后执行第一个用户态进程init。
- 一般分两阶段启动,先是利用initrd的内存文件系统,然后切换到硬盘文件系统继续启动。
- initrd文件的功能主要有两个:
- 1、提供开机必需的但kernel文件(即vmlinuz)没有提供的驱动模块(modules)
- 2、负责加载硬盘上的根文件系统并执行其中的/sbin/init程序进而将开机过程持续下去
-
- system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,即由eax传递的系统调用号
- 一个应用程序调用fork()封装例程,那么在执行int $0x80之前就把eax寄存器的值置为2(即__NR_fork)
- 在系统调用号( eax)之外,参数的个数不能超过6个( ebx,ecx, edx, esi, edi, ebp)
- 当用户态进程调用一个系统调用时, CPU切换到内核态并开始执行一个内核函数。
- 在Linux中是通过执行int $0x80来执行系统调用的,这条汇编指令产生向量为128的编程异常
-
-
- 给MenuOS增加time和time-asm命令(四步操作命令)
- 进程的作用:将信号、进程间通信、内存管理和文件系统联系起来
- 操作系统的三大功能: 进程管理、内存管理、文件系统
- 内核通过唯一的进程标识PID来区别每个进程
- fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建
1号进程是所有用户态进程的祖先,0号进程是所有内核线程的祖先
-
-
- 进程切换在内核中实现的时机有以下三个时机:
-
-
中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();
-
内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;
-
用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。