第4天--linux内核学习
驱动使用方式
1、编译到内核中 * make uImage
进入到系统后
mknod /dev/led c 500 0  创建设备节点
2、编译为模块 M make module
进入到系统后 
mknod /dev/led c 500 0 创建设备节点
insmod fs4412_led_drv.ko(驱动可执行程序) 加载驱动
uImage的编译
1、步骤
	make uImage -jNUM  NUM = 处理器数量*处理器核心数
2、流程
进入顶层目录下的Makefile 
找不到uImage 就去找include 
504 include $(srctree)/arch/$(SRCARCH)/Makefile    ==> arch/arm/Makefile  
 203 SRCARCH     := $(ARCH) =arm
进入arch/arm/Makefile
299 BOOT_TARGETS    = zImage Image xipImage bootpImage uImage
304 $(BOOT_TARGETS): vmlinux
305     $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@  ==> arch/arm/boot/uImage
make -p生成工程目录下的全局变量
 62 Q = @     272 MAKE = make    
Makefile中 @make $(build)    make -C build的路径  执行指定路径下的Makefile
291 boot := arch/arm/boot
233 MACHINE  := arch/arm/mach-$(word 1,$(machine-y))/   
155 machine-$(CONFIG_ARCH_EXYNOS)       += exynos   (在配置文件.config中) 
MACHINE=arch/arm/mach-exynos
make -C arch/arm/boot MACHINE=arch/arm/mach-exynos arch/arm/boot/uImage
进入arch/arm/boot/Makefile中
15 include $(srctree)/$(MACHINE)/Makefile.boot     ==> arch/arm/mach-exynos/Makefile.boot
  1    zreladdr-y   += 0x40008000   uImage的启动地址                                               
  2 params_phys-y   := 0x40000100	传参位置
obj 当前Makefile路径
78 $(obj)/uImage:  $(obj)/zImage FORCE  ==> 表示强制生成  uImage 生成需要zImage生成
54 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE zImage生成需要arch/arm/boot/compressed/vmlinux
51 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
 52     $(Q)$(MAKE) $(build)=$(obj)/compressed $@
make -C arch/arm/boot/compressed/ arch/arm/boot/compressed/vmlinux
进入arch/arm/boot/compressed/Makefile
185 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
186         $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
187         $(bswapsdi2) FORCE
vmlinux.lds 依赖于 vmlinux.lds.in 和 上层路径下的Makefile 和kconfig
 25 HEAD    = head.o    (由当前目录下的head.S生成)
  86 suffix_$(CONFIG_KERNEL_GZIP) = gzip    
  piggy.gzip.o 指的就是gzip压缩 压缩代码
195 $(obj)/piggy.$(suffix_y).o:  $(obj)/piggy.$(suffix_y) FORCE    
192 $(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE   piggy.gzip.o 生成是依赖于上层路径下的Image
addprefix 进行拼接路径
OBJS 需要的目标库文件(很多)
lib1funcs 功能相关库文件
148 lib1funcs = $(obj)/lib1funcs.o
154 ashldi3 = $(obj)/ashldi3.o 与工具链相关
160 bswapsdi2 = $(obj)/bswapsdi2.o 与压缩格式相关代码
回到arch/arm/boot/Makefile
 47 $(obj)/Image: vmlinux FORCE     表示的是顶层路径下的vmlinux
回到顶层路径下的Makefile
817 vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE    
809 vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)    
802 export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
803 export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y)   全部包含
804 export KBUILD_LDS          := arch/$(SRCARCH)/kernel/vmlinux.lds
530 init-y      := init/
 531 drivers-y   := drivers/ sound/ firmware/
 532 net-y       := net/
 533 libs-y      := lib/
 534 core-y      := usr/
head-y = head.o(arch/arm/kernel/head.S生成的文件) 启动的第一个文件
 KBUILD_LDS          := arch/$(SRCARCH)/kernel/vmlinux.lds    arch/arm/kernel/vmlinux.lds
就能生成我们所需的uImage
vmlinux.lds .lds链接脚本 生成vmlinux文件的工具
vmlinux 真正的内核程序
Image 经过第一次压缩
zImage 经过第二次压缩
uImage 使用了mkimage 添加头部,为了uboot的识别
vmlinux 60M (没有添加其他驱动,只是默认配置,实际添加过后应为70M左右)
Image   5M左右
zImage  2768232
uImage  2768296  uImage比zImage大64B  是由mkimage添加64B头部 此头部就是为了uboot进行识别来使用的头部(uboot的版本相关)
uboot加载内核后 uImage 读走头部 ——> zImage 进行decopressed Image ——> vmlinux (真正执行在开发板中的程序)
uImage的编译流程是启动流程的逆序
linux内核的启动流程
进入的是arch/arm/kernel/head.S
解压后进入内核执行(vmlinux) 说明了一些当前所处状态 0xc0008000是虚拟地址的起始位置 uImage执行位置0x40008000 
    __HEAD  开始位置
    thumb指令 使能thumb指令集
    CONFIG_的宏都在.config进行查找
    89     bl  __hyp_stub_install    设置异常向量表
    将arm的工作模式设置成为svc模式
    获取处理器id(真实处理器)  r9 = cpuid
     95     bl  __lookup_processor_type   比较当前处理器id和预置的处理器id,确定是否支持当前处理器  (返回信息r5=procinfo r9=cpuid   )
     		进入arch/arm/kernel/head-common.S   
     		153     adr r3, __lookup_processor_type_data    将__lookup_processor_type_data物理地址赋值给r3
     		174 __lookup_processor_type_data:     结构体                                                                                      
			175     .long   .
			176     .long   __proc_info_begin
			177     .long   __proc_info_end
			154     ldmia   r3, {r4 - r6}        r4 = .(当前虚拟地址位置)  r5 = __proc_info_begin(proc_info虚拟地址位置)  r6 = __proc_info_end(虚拟地址位置)
			155     sub r3, r3, r4          @ get offset between virt&phys  r3 = 虚拟地址与物理地址的差值
			156     add r5, r5, r3          @ convert virt addresses to     r5 = proc_info_begin真实物理地址
			157     add r6, r6, r3          @ physical address space   		r6 = proc_info_end 真实物理地址值
			proc_info_begin指明的是arch/arm/include/asm/procinfo.h  下proc_info_list结构体的开始位置
			 30     unsigned int        cpu_val;    cpu预设值                                         
 			31     unsigned int        cpu_mask;	cpu掩码
 			158 1:  ldmia   r5, {r3, r4}   r3 = cpu_val  r4 = cpu_mask(配置的cpuid)
 			159     and r4, r4, r9  r9(通过检测cp15协处理器得到真实cpu型号)  进行真实运行与配置的比较 r4 = 比较结果 
 			teq r3,r4   比较结果与对应值相比 
 			如果配置cpu的型号与当前运行的cpu型号相同,返回并此时r5 = proc_info_list结构体开始地址
回到arch/arm/kernel/head.S
r10 = r5
109     adr r3, 2f   r3 = 当前物理地址位置
110     ldmia   r3, {r4, r8}  r4 = 当前虚拟地址  r8 = PAGE_OFFSET
111     sub r4, r3, r4          @ (PHYS_OFFSET - PAGE_OFFSET)
112     add r8, r8, r4          @ PHYS_OFFSET
148 2:  .long   .  (  当前预置虚拟地址)                                                                                                         
149     .long   PAGE_OFFSET (虚拟地址页偏移)
为了创建页表做准备
117     /*
118      * r1 = machine no, r2 = atags or dtb (传参方式,uboot阶段确定的),
119      * r8 = phys_offset, r9 = cpuid, r10 = procinfo
120      */
121     bl  __vet_atags  (arch/arm/kernel/head-common.S  )    检测当前设备传参方式是那种 当前是设备树传参
检测创建页表的准备工作是否完成
128     bl  __create_page_tables  (创建页表)  
从0xc0008000开始虚拟地址完成一部分地址映射,完成的4M地址映射,目的是为了后续开启MMU、cache、TLBS做准备
arch/arm/mm/proc-v7.S 
Initialise TLB, Caches, and MMU state ready to switch the MMU on  完成了MMU、cache、tlb的初始化操作,为了开启mmu做准备
137     ldr r13, =__mmap_switched 要进行地址转换,但是前提是mmu开启
144 1:  b   __enable_mmu    
441     mcr p15, 0, r5, c3, c0, 0       @ load domain access register                                                      
442     mcr p15, 0, r4, c2, c0, 0       @ load page table pointer      进行CP15协处理器设置,进行使能mmu
444     b   __turn_mmu_on   mmu开启
		ldr r13, =__mmap_switched(arch/arm/kernel/head-common.S)  完成虚拟地址转换 
		81     adr r3, __mmap_switched_data
		82 
 		83     ldmia   r3!, {r4, r5, r6, r7}   
 		104     b   start_kernel(完成了各种初始化任务)
 							||
 							\/
 							init/main.c 
 							asmlinkage  表示进行编译器优化
 							初始化死锁hash表,对分区进行锁定;防止堆栈溢出;
 							使能中断;
 							509     setup_arch(&command_line);  (arch/arm/kernel/setup.c )
 							包含了所有传入参数的赋值,赋值给了machine_desc结构体(arch/arm/include/asm/mach/arch.h )
分配传入启动参数(bootargs参数);设置中断优先级;关闭中断原始优先级;初始化符号链接;
 							非法闯入报警;
 							581     console_init(); 串口显示,之前的打印内容将会保存到日志缓冲区中,初始化完成进行输出
 							652     rest_init();      
 							382     kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);  
 							||
 							\/
 							kernel_init
 							840     kernel_init_freeable(); 
 							926     if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
							927         ramdisk_execute_command = NULL;
							928         prepare_namespace();
												||
												\/
											init/do_mounts.c
											589     mount_root();
											509     if (ROOT_DEV(nfs机制是当做载体) == Root_NFS) {
											510         if (mount_nfs_root())  
											459         err = do_mount_root(root_dev, "nfs",root_mountflags, root_data);   
											362     int err = sys_mount(name, "/root", fs, flags, data);
						这样完成了nfs文件系统的挂载,而最后进入最终的文件系统,系统启动完成
内核启动过程中
汇编阶段:地址转换,完成物理地址转换为虚拟地址,开启MMU、cache、tlb
c语言阶段:各种初始化,初始化完成后,开启线程,准备用户空间,挂载文件系统
设备树简述
定义:Device Tree是一种描述硬件的数据结构
设备树文件书写格式
/{
	property(根节点)
	node1{(子节点)
	property
		child_node{
			property
		};
	};
node2{
};
};
节点中的内容就是需要的设备信息
dts 	设备树源文件
dtsi	设备树头文件      (由多款板子共用同一个头文件,与soc相关)
dtb		设备树的可执行文件
根节点属性(用来描述当前板级结构)
model :表示具体某一个machine 
compatible:表示支持的一系列machine
子节点属性(描述当前节点设备)
node标注的值是确定的(驱动)
compatible:用来绑定一个驱动和设备
reg:可寻址设备用来表示编码地址信息
其他节点属性:参考Documentation/devicetree/bindings
设备树与machine_desc的关系
在内核启动过程中设备树中的信息被转换为machine_desc结构体(setup_arch函数中完成了我们的赋值任务)
作业:实验9、实验10
第4天--linux内核学习的更多相关文章
- Linux 内核学习的经典书籍及途径
		from:http://www.zhihu.com/question/19606660 知乎 Linux 内核学习的经典书籍及途径?修改 修改 写补充说明 举报 添加评论 分享 • 邀请回答 ... 
- 关于Linux内核学习的误区以及相关书籍介绍
		http://www.hzlitai.com.cn/article/ARM9-article/system/1605.html 写给Linux内核新手-关于Linux内核学习的误区 先说句正经的:其实 ... 
- linux内核学习之二:编译内核
		在linux内核学习系列的第一课中讲述了搭建学习环境的过程(http://www.cnblogs.com/xiongyuanxiong/p/3523306.html),环境搭好后,马上就进入到下一环节 ... 
- linux内核学习之一:环境搭建--安装Debian7.3
		本系列文章假设读者已对linux有一定的了解,其实学习linux内核不需要有很深的关于linux的知识,只需要了解以下内容:linux基础知识及基本shell命令:现代操作系统的基本概念:C语言和gc ... 
- Linux内核学习笔记-2.进程管理
		原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ... 
- Linux内核学习笔记-1.简介和入门
		原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ... 
- Linux内核学习趣谈
		本文原创是freas_1990,转载请标明出处:http://blog.csdn.net/freas_1990/article/details/9304991 从大二开始学习Linux内核,到现在已经 ... 
- Linux 内核学习经验总结
		Linux 内核学习经验总结 学习内核,每个人都有自己的学习方法,仁者见仁智者见智.以下是我在学习过程中总结出来的东西,对自身来说,我认为比较有效率,拿出来跟大家交流一下. 内核学习,一偏之见:疏漏难 ... 
- Linux内核分析——Linux内核学习总结
		马悦+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核学习总结 一 ... 
- Linux内核学习笔记二——进程
		Linux内核学习笔记二——进程 一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ... 
随机推荐
- [游戏开发-学习笔记]菜鸟慢慢飞(九)- NGUI- UIPanel(官方说明翻译)
			我自己笔记是做在OneNote上,直接复制粘贴过来变成图片了,效果好像还可以. 机器翻译,我自己看了一下,改了一部分. 
- 图像抠图算法学习  -  Shared Sampling for Real-Time Alpha Matting
			一.序言 陆陆续续的如果累计起来,我估计至少有二十来位左右的朋友加我QQ,向我咨询有关抠图方面的算法,可惜的是,我对这方面之前一直是没有研究过的.除了利用和Photoshop中的魔棒一样的技术或者 ... 
- USACO . Greedy Gift Givers
			Greedy Gift Givers A group of NP (2 ≤ NP ≤ 10) uniquely named friends has decided to exchange gifts ... 
- HideFlag隐藏标识
			前言 如何让一个Gameobject的属性在运行时,不可以在属性面板上手动的修改呢? 文档:http://www.ceeger.com/Script/Enumerations/HideFlags/Hi ... 
- HTML 学习笔记 JQuery(DOM 操作)
			一般来说,DOM操作分为三个方面,即:DOM Core(核心), HTML_DOM 和 CSS_DOM. 1.DOM Core DOM Core 并不专属于JavaScript,任何一种支持DOM的程 ... 
- 分享基于EF+MVC+Bootstrap的通用后台管理系统及架构
			基于EF+MVC+Bootstrap构建通用后台管理系统,集成轻量级的缓存模块.日志模块.上传缩略图模块.通用配置及服务调用, 提供了OA.CRM.CMS的原型实例,适合快速构建中小型互联网及行业 ... 
- CCF 201512-4 送货(错误)
			直接用DFS深搜,检查了好久没能发现错误,贴上来以后慢慢看... /* DFS深度优先搜索 Edge保存边 u{v,been} cnt记录走过的街道 如果没有就return ;继续递归 */ #inc ... 
- 供销大集-JS修改
			aes("a123456") 1.搜索password 可以猜测 寻找匹配项 然后把密码 给t 2.也可以直接直接从这里往上,找到一个 encrypt函数下断点调试输出 funct ... 
- 【转】javascript浏览器参数的操作,js获取浏览器参数
			原文地址:http://www.haorooms.com/post/js_url_canshu html5修改浏览器地址:http://www.cnblogs.com/JiangXiaoTian/ar ... 
- 比较.NET程序集(DLL或EXE)是否相同
			如何比较两个.NET程序集(DLL或EXE)是否相同呢? 直接比较文件内容?当然没那么简单了,这个你可以去试试,去比较一下两次Build产生的程序集, 就算内容没有改变,产生的程序集的二进制文件也是不 ... 
