Linux KVM 虚拟化-春季班

(0评价)
价格: 690.00元

段机制从8086引入,解决16位地址访问20位的地址空间的问题,为了兼容就保留下来了

分段、分页机制对x86是都有的,段机制是必选的。

 

 

[展开全文]

x86体系结构

寄存器

objdump

MMU: 与cpu一起,把虚拟内存地址转换为物理内存地址 

段页机制是x86 MMU硬件设计时固定好的(虚拟[逻辑]地址->线性地址->物理地址),其中段机制是必选的,分页机制是可选。

操作系统如何应对硬件提供的这种机制(一些系统上不支持段机制, 如arm)。大多数操作系统绕过了段机制,只实现了分页机制。

GDT(全局描述符表): 只在启动时用

LDT(局部描述符表)

IDT(中断描述符表)

保护模式:段寄存器存放索引(选择符)

提供了四个特权级,0表示最高级,对应内核态;3表示最低级,对应用户态。

 

linux如何处理段机制?

将段基地址设置为0,启动时用到了GDT,启动之后就不会再用到段机制。

分页机制

虚拟地址=逻辑地址=线性地址

线性地址空间划分为若干个大小相等的页(page)

物理地址空间划分成与页大小相等的若干存储块 (page frame)

页的大小谁确定?

硬件设计人员与OS设计人员协商确定的,x86有4K、2M页等

页表是把线性地址映射到物理地址的一种数据结构,包含物理页面基地址、页的属性

4K的页,物理页面基地址需要20位表示,(4G/4K)

一级页表

二级页表

页目录、页表放在物理内存

页高速缓存(TLB)

三级页表

GCC手册

linux可执行文件ELF, ld从0x8000000开始安排程序代码段

i386体系结构

[展开全文]

Posix标准

GCC手册

GNU | GPL

订阅邮件列表

源码目录:/usr/src/kernel, 如果没有目录为空,需要执行:yum install kernel-devel;

头文件目录:/usr/src/kernels/3.10.0-514.2.2.el7.x86_64/include/linux

用户态头文件目录:/usr/include?

Makefile

kdebug | kdb | kgdb 

insmod | lsmod | rmmod

demsg

 

 

[展开全文]

Module signing

.只有签名被匹配的module才会被允许insmod到kernel,用于安全防范

.Enabled by CONFIG_MODULE_SIG

.Introduced in v3.7

 

fedora19->make menuconfig>Enable loadable module support>Module signature verification

 

.相关的编译选项

-CONFIG_MODULE_SIG_FORCE

-CONFIG_MODULE_SIG_ALL

-CONFIG_SIG_SHA1...CONFIG_SIG_SHA512

.手动kernel签名:

scripts/sign-file sha512 kernel-signkey.priv kernel \    -signkey.x509 module.ko

 

fedora19->vim [kernel path].config

 

sysctl

cat /proc/keys

 

Module operations

.lsmod

.insmod

.rmmod

.modprobe

.modinfo

 

VNC

 

fedora19->/lib/modules/3.14.0-rc1+/...

 

[展开全文]

实际项目里-可能有上万行代码,有很多的.c文件,有很多.h文件(有我们自己编写的,也有引用第三方提供给我们的库)

dmesg -c > /dev/null (不想让它占据太多屏幕)

 

避免因重复包含所产生的问题-预编译的方式

对于.h 

-> 当前目录#include "other.h"

-> 放在一个目录下

-> 引用第三方库的时候希望简单一点->将第三方的路径加载到当前路径下-kbuild提供的宏-EXTRA_CFLAGS=-I$(shell pwd}/include

 

make M=arch/x86/kvm

modinfo arch/x86/kvm/kvm.ko

module_param(参数(变量名字),参数类型,访问权限)

#standard types:...

#define module_param(name,type,perm)...

 

调用的函数由另外一个模块所提供-和模块的加载顺序有关系

cp ../m1/Module.symvers ./

先加载第一个模块后加载第二个模块

 

[展开全文]

Write a module

-只能使用内核导出的函数,不可使用用户空间的任何lib

-但是并不是kernel的函数你都能使用,只能用下面的符号导出的函数。

。EXPORT_SYMBOL /EXPORT_SYMBOL_GPL

。在.h中实现的函数-所有的实现都要在.h中,如果视线中包含了另外一个函数没有导出的话也是不能用的。

。虽然有这么多限制,但是kernel把一些常用的函数都导出来了。

-初始化与退出函数

。__init/__exit

module_init(minit)-钩子函数,模块加载的时候回去加载这个宏所定义的函数。

module_exit(mexit)-模块卸载的时候被调用

对于一些永远只调用一次的函数,可以用init这样的一个宏来修饰。这个宏会把这个函数所对应的内存放到一个特定的地方,当它被调用完了之后就会把这块内存给free。

-Module License

。MODULE_LICENSE

。如果想要使用GPL导出的函数,也要去声明协议为GPL

-Other module info

。MODULE_AUTHOR

。MODULE_DESCRIPTION

。Others defined in <include/linux/module.h>

。modinfo main.ko

-进阶

。编译有多个源文件的module

。编译多个源文件位于不同目录的module

。指定include.h位置

。模块参数

。编写与编译module之间的依赖

[展开全文]

当前module版本和所跑kernel版本不一样->加载内核时提示错误信息

 

-它依赖当前运行内核的编译环境,例如.config, module info, include .h files......

-在发行版上可以安装kernel-devel(on fedora)包

yum search kernel-devel

 

。还可以自行安装一个全新环境

-推荐,因为可以自行修改内核

-下载内核:(使用git能获取所有源码修改信息)

-便于调试,修改源代码再加载内核查看修改效果

.git clone

git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

.load all the modules you need on your box

.make localmodconfig

.make -j6

.make modules modules_install install

.Change your grub and load the new kernel

fedora19

->/boot/grub2/grub.cfg

->做了优化,只要你安装了新内核,就会优先从你的新内核区启动。--如果不是-set default=0

 

git log

git blame [path/filename]

:line_number

git show [commit]

 

linux开发Tree都能在git.kernel.org上找到

 

Write a module Makefile

-指定模块的名字与源文件

.obj-m = <module_name>.o

-编译

.make -C <path_to_kernel_src> M=$PWD

-示例

 

module所编译的语法是由kernel的编译系统所定义的。kernel采用kbuild的系统来编译内核。每一个目录下面有一个kconfig和Makefile

cd /arch/x86/kvm

vi Makefile

vi ~/kvm/.config

 

ls -l /lib/modules/.../build ->对应到当前的kernel的source code

 

Makefile {

obj-m = main.o

all:

    make -C /lib/modules/`uname -r`/build M=`pwd`

clean:

    rm -f *.o *.ko *.mod.c modules.order Module.symvers

}

[展开全文]

模块签名是在3.7内核导入的feature->提高Linux系统安全性,用来防止一些危险的攻击。

 

-本质上module是一段内核代码,它运行在CPU的特权层(Ring 0 on x86),与内核代码具有相同的功能。

-它是kernel的动态扩展,在需要时被加载,在不需要时被移除,可减少内核的footprint

-便于驱动,文件系统等的二次开发。

[展开全文]

kvm.eric@gmail.com

Fedora 19

cat /etc/issue

使用的内核版本跟着KVM版本走

uname -an

 

内核基础

-内核模块

学会内核模块编写之后,就可以写代码验证学到的东西

-上下文介绍

原子环境、中断上下文、可睡眠环境...

-内核同步

内核中锁的使用-主要是信号量、自旋锁;一些原子操作(经常用在...)\内存屏障-优化锁的使用->性能调优

-常用的数据结构

主要是List

[展开全文]

进程调度算法:和管理中的考虑是一样的

 

时间片轮转调度算法:平均主义、公平

优先权调度算法:vip。非抢占:除非是我主动放弃CPU,否则你不能抢占。抢占:优先级高,把你从CPU上拉下来。

多级反馈队列调度: 时间片+优先权的结合?

实时调度:

提高交互式进程的优先级:ps看的时候TTY是?的是后台进程。

调度时机: {

sched.c

sched.h

schedule()-调度函数

为什么在这些时机返回?->调度一定是发生在内核态

}

2.4 {

need_resched:通知系统CPU已经空闲,是否真的发生调度有很多因素决定,并不是立马调度。

工程实践中的具体问题:时间片大小、优先级

基于大原则来改进

goodness(描述进程,描述进程地址空间)

内核代码是一个公共区(就绪队列)-会有很多锁

switch_to(prev,next,prev)-嵌入式汇编,放在/arch下

edsionte-2.6的进程调度分析

}

 

上下文指的是CPU的运行环境

 

fork()之后父进程执行还是子进程-不确定

fork()两个子进程-兄弟/父子孙

[展开全文]

OS是对硬件管理

进程概念源于对CPU的管理(管理者的角度)

 

这里讨论的是如何去管理系统数据段-我在这个阶段学的是什么东西?

为什么要引入进程的状态:进程诞生后就是一个活物,一个活物每一刻是不一样的。从生存到死亡这样一个生命历程里怎么去管理它?对一个连续的事情抓住它的点-用状态来描述它。

进程什么时候运行不是你控制的,是调度程序控制的(调度程序也要有一定规则)。

三种基本状态-其他OS衍生的状态是根据三种基本状态衍生来得。

父进程和子进程有各自的地址空间。

Linux-task_struct->这样的数据结构被叫做进程控制块PCB(process control block)-PCB是进程存在和运行的惟一标志。

sched.h

kernel coding style

进程控制块-信息分类

如果是我自己去设计,去描述进程;我怎么描述?

把人和进程对应起来。把进程学活,技术这个东西一定要搞活了。思维活了,很多信息就关联起来了。OS的复杂就复杂在各种关系。

 

上下文环境:各种寄存器。进程执行过程中被中断了或者发生调度了,要把上下文保存下来,把各种寄存器信息压栈。把它和我们生活环境联系起来。

 

2.4:8个状态(应对变中的不变-3个基本状态)

状态的转化和进程调度密切相关

你怎么样去描述一个进程的状态?

写应用程序代码像内核代码学习-用了长整型,设计目标是想用位操作。逻辑运算和算数运算间肯定逻辑运算快。

看源码-找到切入点-不要找难的,要找简单的。把层次关系理清楚,搞清楚为啥要形成这个代码才有意义。找到变的规律在什么地方。

通过位图来管理pid

UID、GID-权限管理(安全)

task_struct-人类的虚拟化描述,用代码来演戏。

PCB放在什么地方(空间存储的问题):在内核空间的数据段存放

性能问题:进程访问的问题,栈是从高地址到低地址。栈从下到上访问,PCB从下到上访问,内核栈和PCB要是碰上了也是中间给碰上了,公用一段内存空间。

代码设计上并不是那么简单,一定是要讲时效的。

系统多进程怎么组织(组织关系的问题)

 

cd /proc

OS启动时候这个目录不存在,cd或者执行ps命令的时候,这个文件系统就产生了。

虚(伪)文件系统->存放内核执行过程中所有有关进程的信息。给每个进程的进程号建了目录(每个目录对应一个pid)->为什么要以文件系统的方式来组织数据呢? 一般怎么样才能把内存的数据读出来呢?->写代码读出/用文件的方式来组织的时候,可以直接用查看文件的方式查看它。(coredump)

ps很多信息都是从/proc下面捞的

 

cd /proc

cat filesystems

 

如何快速地通过pid找到进程:哈希-不同的组织方式是为了管理的方便。

 

等待队列(include/linux/wait.h)

http://edsionte.com/techblog/

 

 

[展开全文]

段机制的引入->解决由16位地址能访问到20位地址的问题。后来为了兼容,段机制就延续下来了。-从用户的角度

保护模式->保护操作系统在自己的地址空间里/多任务系统-每一个进程在自己的地址空间。

分页机制->为了虚拟内存管理-对程序员来说是感觉不到的

 

在页里面才控制读写权限

段的保护主要是特权级的保护,而不是读写的保护-在硬件层支持(保护模式在段这一层)

程序报的段错误是指针出现问题。

 

保护模式真正含义

 

一般系统LDT不用,GDT用于启动过程,启动后,GDT也不用了,IDT在整个系统执行过程中一直在用。整个系统运行时,每个设备驱动都对应一个中断,需要在IDT中去注册。IDT是一个动态分配和回收的过程。

 

逻辑上段长为4G,其实地址为0。主要是为了绕过段机制,没有实际含义。真正给用户态空间为0-3G,内核为3-4G

 

页转换的时候用的是TLB,OS不管它

 

系统初始化:没有进程,所有硬件-时钟、内存都要初始化。初始化就是定义了一堆数据结构要给初值,要是硬件的话给寄存器也设初值,给表都填初值。

页表在什么时候被创建:进程起来以后->缺页机制-往内存装的时候就要建立页表。

 

kernel API

{

内核开辟了一块Public的地方,导出的这些函数是有限的,这些函数专门给模块调用,写内核模块时可以调用这些函数。

模块和内核通过内核函数形成衔接关系。

}

 

64位系统中的分页-对64位系统不同体系架构的分页级别是不一样的-ia64是3级,x86_64是4级,...现在Linux分页已经变成一个四级分页。

64位体系和32位改变大吗?-arch目录下代码都要改变,不变的是和体系结构无关的代码。

[展开全文]

虚拟内存管理的硬件机制

内存寻址的演变

段机制

分页机制

Linux中的分页机制

Linux中的汇编语言

Linux系统地址映射示例

 

P9

 

看代码一定要知道原理、模板

/arch/x86/include/asm-于汇编相关的代码

.segment.h-和体系结构相关的代码

 

4位-硬编码绝地地址,程序员没有被解放

16位-段的引入是为了扩大寻址空间

24位-引入保护模式

32位-解放了软件工程师

 

IA32寄存器简介

 

用于分页机制的控制寄存器

CR0最低位:实模式->保护模式

CR0最高位:支持分页机制(允许分页)

CR0最高位和最低位置一:支持分页机制

 

objdump -d [executable file]

 

intel开发手册(硬件)

 

地址之间的转换-保护模式下的寻址 //分段和分页一定要有硬件的支持-MMU机制

 

段机制

-三个方面:段基址、界限、保护属性

-虚拟-线性地址的装换

 

段描述符表:段表->段地址转换到线性地址

端描述符的一般格式:...

保护模式下的其他描述符表简介

 

保护模式下段寄存器中存放什么->存放索引或叫段号

RPL->出于安全性考虑(访问者、被访问者)

保护模式提供了四个特权级,用0~3四个数字表示

多任务的情况下,保护内存地址的访问

TI-全局/局部

 

Linux绕过了段机制->基地址=0,启动时采用全局描述符表

 

为什么进行分页? - 书如果一行、一字来管理?内存如果用字节来管理?

 

分页机制-页

-将线性地址空间划分为若干大小相等的片,称为页(Page)

-物理地址空间分成与页大小相等的若干存储块,称为(物理)块或页面(Page Frame)

-页的大小应该为多少?由谁确定?

 

分页机制-页表

分页机制-页表项结构

分页机制-两级页表

分页机制-线性地址结构

分页机制-硬件保护机制

分页机制-线性地址到物理地址的转换

 

objdump -d [file]

 

二级页表需要多次读取内存的,需要加页面高速缓存(TLB)。为什么需要二级页表?

Linux的3级页表

 

Linux中的C语言和汇编语言

-GNU的C语言

http://www.faqs.org/docs/learnc/

-AT&T的汇编:参见书

-GCC嵌入式汇编

 

Linux内核情景分析

 

P45

[展开全文]

认识操作系统

.从程序执行看

.从设计者角度看(管理的角度/服务的角度)

计算机的MBA

操作系统的定义

操作系统的组成

操作系统的发展

.硬件发展/软件发展

.讲究效率的单模块操作系统

.追求简洁的微内核操作系统(Mach)

 

开放源代码的Unix/Linux操作系统

。诞生于学生之手

。成长于Internet

。壮大于自由而开放的文化

 

用户态进程?-穿衣服和设计衣服

 

Linux得以流行的原因之一——遵循POSIX标准

Linux的肥沃土壤——GNU

GPL——开源软件的法律

Linux系统或发布版

开放与协作的开发模式

Linux内核

Linux内核的技术特点

整个系统的核心——内核

和用户态程序有什么区别?

Linux内核版本树

Linux内核源代码

。内核源代码结构

Linux内核源代码分析工具

Linux内核模块编程入门

insmod

dmesg

lsmod

rmmod

 

新手邮件列表

 

Linux内核中链表的实现及应用

 

/usr/src/linux-header-3.2.0-23

-./include/linux(编译程序的时候在这个位置下找文件)

vim+ctext

POSIX标准/gcc手册

[展开全文]

引言:

为什么要讲链表

Data structure two key points->store and organization

 

struct my_list {

    void *mydata; //可以代表任意的数据类型

    struct my_list *next;

    struct my_list *prev;

}

/usr/src/include/list.h

内核链表之插入

前面加双下划线为内核内部函数,如果不export,编写的模块无法使用该代码。

代码简单,设计思想不简单。

用户态下使用->LIST_POSITON1(2)=0

通常是通过结构体位置来查找字段,现在是通过字段来找结构体位置->知道儿子的位置要找父亲

内存地址编址是以字节编址的

内存地址编址以字节来编址

 

我们刚才一路走来,发现其实内核并不是我们想象的那么难,只是我们感悟其思想,赏析其源码,定能深入内核!内核所用的C语言也不是我们想象的那么难懂,也是我们平时所用到的C语言而已。

通过这样的讲解希望大家在平时要注意这些我们不屑一顾的数据结构,因为很多计算机科学问题最终的实现都会落在这些数据结构上。

 

19页例子

[展开全文]

QQ客服: 810476411

QQ咨询: 810476411

QQ吐槽: 810476411

服务时间: 9:00 - 21:00

刘老师: 18516031455

微信公众号:开源力量