2-内核的编译_uImag_zimage_设备树
2017-02-03 15:15
281 查看
内核的编译:
make uImage
1、在顶层目录下搜索uImage发现找不到,有可能uImage存在于其他的Makefile文件中
2、include arch/arm/Makefile
3、进入到arch/arm/Makefile中,寻找uImage目标
4、进入到arch/arm/boot目录下寻找uImage目标
如果需要生成uImage,必须依赖zImage
5、搜索目标zImage
6、在arch/arm/boot/compressed/Makefile中寻找vmlinux目标
进入到arch/arm/boot/Makefile,寻找Image目标
以Image为源文件,调用了gzip命令生成了piggy.gzip
ld链接器以5个.o文件为源文件生成了arch/arm/boot/compressed/vmlinux
7、返回到arch/arm/boot/Makefile,以arch/arm/boot/compressed/vmlinux调用objcopy命令生成了zImage
8、以zImage为源文件调用uimage命令生成uImage文件
总结:uImage的生成,顶层目录下生成vmlinux文件,通过vmlinux文件生成Image,Image调用gzip进行压缩最终生成了piggy.gzip,
调用ld链接器,以piggy.gzip.o和其它.o文件来进行链接生成了zImage,zImage调用uimage命令生成uImage文件
arch/arm/kernel/head.S内核的最初启动文件
1、设置特权模式并且屏蔽所有中断
因为我们需要初始化一些硬件并且调用协处理器指令,所以必须设置特权模式
中断代码还没有设置完成
2、判断u-boot给内核传递的参数是设备树还是tag结构体
我们3.14内核在和u-boot2013版本配合使用时默认使用了设备树
3、创建页表
虚拟地址和物理地址的关系.如果要理解这个关系必须先了解什么是页目录,页表,还有页。
虚拟地址32位,在32位中分成3个部分:10 + 10 + 12
页目录 页表 页
1024项 1024项 1024项
也就是说我们可以把上面的页目录,页表,页都看成是数组,而虚拟地址分成的三个部分就是这三个数组的下标
0x12345678
0001001000 1101000101 011001111000
4、使能并且开启MMU
5、进入到init/main.c中执行start_kernel函数
执行setup_arch();
==>setup_machine_fdt();接收了u-boot传递给内核的设备树地址然后去解析设备树内容
console_init()控制台初始化函数,如果在它之前调用printk则输入信息会被临时存放到缓存区中
vfs_caches_init()
==>mnt_init();
==>sysfs_init()初始化sysfs文件系统,它的作用在驱动中讲
rest_init()
==>kernel_thread(kernel_init,,);
kernel_init_freeable();
==>sys_open();//在应用层中的open调用了sys_open,sys_open()函数最终帮助我们找到了驱动接口
==>prepare_namespace();
==>mount_root();
==> mount_nfs_root()通过nfs服务来挂载rootfs文件夹的
在操作系统内核中驱动、设备、总线
总线上可以理解为既挂载了设备文件又挂载了驱动程序。总线帮助我们去匹配驱动和设备。
所以在使用总线的前提下我们要写一个驱动程序和一个设备程序。这两种程序都会被最终编译到uImage文件中。
设备树命名:.dts(设备树的源文件) .dtb(设备树的二进制文件) .dtsi(设备树的头文件)
设备树的基本语法:
节点和属性:
每个设备树文件都是从根节点开始的。其它的所有节点都必须包含于根节点。
根文件系统:
etc/:
inittab:每行都有4个域,用:分隔
域1:域2:域3:域4
在嵌入式中前两个几乎不用.第三个域是一种动作,第四个域是完成具体动作使用到的命令或者脚本
tmpfs、proc、sysfs都是文件系统类型,其中tmpfs可以被挂载多次,但是proc必须挂载到proc目录下,sysfs必须挂载到/sys目录下
mount命令只能临时挂载
fstab文件可以永久挂载
make uImage
1、在顶层目录下搜索uImage发现找不到,有可能uImage存在于其他的Makefile文件中
2、include arch/arm/Makefile
3、进入到arch/arm/Makefile中,寻找uImage目标
299 BOOT_TARGETS = zImage Image xipImage bootpImage uImage 304 $(BOOT_TARGETS): vmlinux(顶层目录下的) 305 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ boot := arch/arm/boot
4、进入到arch/arm/boot目录下寻找uImage目标
78 $(obj)/uImage: $(obj)/zImage FORCE 79 @$(check_for_multiple_loadaddr) 80 $(call if_changed,uimage) 81 @$(kecho) ' Image $@ is ready'
如果需要生成uImage,必须依赖zImage
5、搜索目标zImage
54 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE 55 $(call if_changed,objcopy)
6、在arch/arm/boot/compressed/Makefile中寻找vmlinux目标
185 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ 186 $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \ 187 $(bswapsdi2) FORCE 188 @$(check_for_multiple_zreladdr) 189 $(call if_changed,ld) 190 @$(check_for_bad_syms) // 如果要生成piggy.$(suffix_y).o,需要依赖 $(obj)/piggy.$(suffix_y) // 如果要生成$(obj)/piggy.$(suffix_y),要依赖$(obj)/../Image
进入到arch/arm/boot/Makefile,寻找Image目标
47 $(obj)/Image: vmlinux(顶层目录下的) 48 $(call if_changed,objcopy)
以Image为源文件,调用了gzip命令生成了piggy.gzip
ld链接器以5个.o文件为源文件生成了arch/arm/boot/compressed/vmlinux
7、返回到arch/arm/boot/Makefile,以arch/arm/boot/compressed/vmlinux调用objcopy命令生成了zImage
8、以zImage为源文件调用uimage命令生成uImage文件
总结:uImage的生成,顶层目录下生成vmlinux文件,通过vmlinux文件生成Image,Image调用gzip进行压缩最终生成了piggy.gzip,
调用ld链接器,以piggy.gzip.o和其它.o文件来进行链接生成了zImage,zImage调用uimage命令生成uImage文件
启动过程:
启动过程:涉及到汇编和c,代码都不需要记。我们需要做到的是用什么功能,了解某个部分的代码。arch/arm/kernel/head.S内核的最初启动文件
1、设置特权模式并且屏蔽所有中断
因为我们需要初始化一些硬件并且调用协处理器指令,所以必须设置特权模式
中断代码还没有设置完成
2、判断u-boot给内核传递的参数是设备树还是tag结构体
我们3.14内核在和u-boot2013版本配合使用时默认使用了设备树
3、创建页表
虚拟地址和物理地址的关系.如果要理解这个关系必须先了解什么是页目录,页表,还有页。
虚拟地址32位,在32位中分成3个部分:10 + 10 + 12
页目录 页表 页
1024项 1024项 1024项
也就是说我们可以把上面的页目录,页表,页都看成是数组,而虚拟地址分成的三个部分就是这三个数组的下标
0x12345678
0001001000 1101000101 011001111000
4、使能并且开启MMU
5、进入到init/main.c中执行start_kernel函数
执行setup_arch();
==>setup_machine_fdt();接收了u-boot传递给内核的设备树地址然后去解析设备树内容
console_init()控制台初始化函数,如果在它之前调用printk则输入信息会被临时存放到缓存区中
vfs_caches_init()
==>mnt_init();
==>sysfs_init()初始化sysfs文件系统,它的作用在驱动中讲
rest_init()
==>kernel_thread(kernel_init,,);
kernel_init_freeable();
==>sys_open();//在应用层中的open调用了sys_open,sys_open()函数最终帮助我们找到了驱动接口
==>prepare_namespace();
==>mount_root();
==> mount_nfs_root()通过nfs服务来挂载rootfs文件夹的
设备树:
设备树是干嘛的?设备树是描述硬件信息的。在操作系统内核中驱动、设备、总线
总线上可以理解为既挂载了设备文件又挂载了驱动程序。总线帮助我们去匹配驱动和设备。
所以在使用总线的前提下我们要写一个驱动程序和一个设备程序。这两种程序都会被最终编译到uImage文件中。
设备树命名:.dts(设备树的源文件) .dtb(设备树的二进制文件) .dtsi(设备树的头文件)
vi arch/arm/boot/dts/exynos4412-fs4412.dts
设备树的基本语法:
节点和属性:
每个设备树文件都是从根节点开始的。其它的所有节点都必须包含于根节点。
/{ model = "字符串";对平台或芯片的描述语句,这个属性不重要。 compatible = "fs4412,key";在驱动中的某个结构体成员内容也必须是"fs4412,key" reg = <寄存器首地址1 偏移量1 寄存器首地址2 偏移量2>; 节点@地址{ 为什么某些节点的后面会出现地址?这个地址为了区分同种设备中的不同子设备 }; 标号:节点{为什么会有标号?如果后面的设备需要调用当前设备的所有信息的话,只需要调用标号就可以了 }; interrupt-parent = <&gpx0>; 中断父节点,其中gpx0是某个头文件中一个标号,引用标号的方法要加& interrupts = <中断类型 中断号 中断触发方式> 中断类型:0代表SPI 1代表PPI 中断号:6代表了EINT[6]来索引中断号 触发方式:1上升沿触发 2下降沿触发 4高电平 8低电平 };
根文件系统:
etc/:
inittab:每行都有4个域,用:分隔
域1:域2:域3:域4
在嵌入式中前两个几乎不用.第三个域是一种动作,第四个域是完成具体动作使用到的命令或者脚本
tmpfs、proc、sysfs都是文件系统类型,其中tmpfs可以被挂载多次,但是proc必须挂载到proc目录下,sysfs必须挂载到/sys目录下
mount命令只能临时挂载
fstab文件可以永久挂载
相关文章推荐
- Zedboard上运行Linaro系统(三):编译内核和设备树
- linux设备驱动程序 源码 2.6 内核编译错误总结
- Linux字符设备驱动程序编译进入内核的方法
- linux设备驱动程序开发环境的建立(编译嵌入式内核)
- 【Linux高级驱动】平台设备驱动机制的编程流程与编译进内核
- 简单的LINUX字符设备驱动及编译进Linux内核…
- 喜羊羊系列【设备 - 驱动器 编译进内核】
- 简述编译进内核的平台设备是如何在内核注册的(by liukun3211咕唧咕唧)
- ubuntu下编译内核(驱动、设备)
- linux下编译新内核,解决无法找到eth0设备问题,安装eth0网卡驱动
- 编译时向内核添加新设备 模块的方式动态的将驱动加入内核,但这种方式加入的驱动程序,当系统重新启动时, 还需要重新用模块的方式进行插入,如果是系统内常用的设备驱动采用这种方式进行加载, 就会很不方便。
- Linux设备驱动程序学习--内核编译
- 内核子系统或设备驱动可以直接编译到内核,也可以编译成模块,如果编译到内核,可以使用前一节介绍的方法通过内核启动参数来向它们传递参数,如果编译成模块,则可以通过命令行在插入模块时传递参数,或者在运行时,
- 从给内核单独编译设备驱动模块,到使用模块
- 【原创】IP摄像头技术纵览(一)---linux 内核编译,USB摄像头设备识别
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响—linux2.4单独编译驱动模块
- 简单字符设备驱动编写,可传参,在内核之外编译
- 蜂鸣器驱动程序,应用程序控制(自动创建设备节点,内核目录之外编译)
- tony之linux driver_LDD3_scull字符设备驱动编译在新内核编译问题
- [linux设备驱动程序]scull字符设备驱动编译在新内核编译问题解决方案