系统移植
操作系统的移植:
引导系统:BIOS/bootloader--->引导内核程序
系统核心:win核心、linux核心(kernel)这个程序不会死,会一直运行(挂载文件系统)
注:在系统启动的最后阶段会创建一个新的内核线程来完成文件系统的挂载;挂载的方式有多种(nfs文件系统、硬盘的某个扇区来完成文件系统的启动)
文件系统:对存储器进行格式化的动作,将其变成某种格式,我们可以使用的就是预留空间
驱动:linux内核提供(修改和配置)
默认配置:make exynos_defconfig
个人配置:make menuconfig
注:--->配置修改的是.config,改的是其中CONFIG_变量的赋值内容y m 数字 字符串 未设置;其中设置修改的方式是通过一个Kconfig文件的修改添加
--->对应目录下Makefile
应用程序
内核调试:
1、点灯法
在未进行串口初始化时,显示信息使用点灯的方式
2、串口输出
putstr 内核解压前 (uImage 3/4M)
printascii 串口初始化前 (当前信息不会立刻输出,会在串口初始化后进行显示,之前会保存在串口缓冲区中 用在内核中汇编程序中)
printk 内核解压后(调试驱动,调试系统功能,均使用当前的打印函数)
函数原型、实现kernel/printk/printk.c
printk 打印内核信息
1674 asmlinkage int printk(const char *fmt, ...)
printf("dasdasd %s-----%d\n",buf,num);
492 printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf);
include/linux/kern_levels.h
7 #define KERN_EMERG KERN_SOH "0" /* system is unusable */ 系统不可用
8 #define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */
动作必须立刻被执行
9 #define KERN_CRIT KERN_SOH "2" /* critical conditions */
严重的状况
10 #define KERN_ERR KERN_SOH "3" /* error conditions */
错误情况
11 #define KERN_WARNING KERN_SOH "4" /* warning conditions */
警告情况
12 #define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */
正常但是需要注意的情况
13 #define KERN_INFO KERN_SOH "6" /* informational */
信息性质的
14 #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
调试级别的信息
此处表示的是当前这条信息的打印级别,对照的还有一个叫系统输出级别的信息
注:这里的系统输出级别表示就是一个过滤器的级别,过滤的是不重要的信息
492 printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf);
打印级别有0-7 八个打印级别
输出级别有7个 1-7
/proc/sys/kernel/printk 此文件就是设置系统的输出级别文件
4 4 1 7
当前的输出级别 系统默认级别 最小 最大
如果打印级别小于输出级别则当前的打印信息能被显示
出现原因:就是为了过滤掉一些不那么重要的命令,为了凸显显示信息的重要性
printk(对可变参数的处理 args)---->vprintk---->syslog(系统日志)---->console(串口输出)
ctags 使用
ctags -R 生成索引文件 tags
使用ctrl+ ] 变量
3、oops机制
oops信息
[ 1.250000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[ 1.260000] pgd = c0004000
[ 1.260000] [00000000] *pgd=00000000
[ 1.265000] Internal error: Oops: 805 [#1] PREEMPT SMP ARM
[ 1.270000] Modules linked in:
[ 1.275000] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 3.14.0 #12
[ 1.280000] task: ee8a0000 ti: ee8a4000 task.ti: ee8a4000
[ 1.285000] PC is at dm9000_probe+0x1c/0x8f0
[ 1.290000] LR is at platform_drv_probe+0x18/0x48
[ 1.295000] pc : [<c0277cc8>] lr : [<c0247f7c>] psr: 60000153
[ 1.295000] sp : ee8a5e48 ip : 00000000 fp : 00000000
[ 1.305000] r10: c052a4fc r9 : 00000000 r8 : c0591e98
[ 1.310000] r7 : 00000000 r6 : ee97c810 r5 : ee97c800 r4 : 00000000
[ 1.315000] r3 : 000000ff r2 : 00000000 r1 : ee8a5de8 r0 : ee97c800
当前记录下系统崩溃时的状态,而其中pc寄存器中的地址尤为关键
(1)反汇编 objdump -d test(elf)
使用arm-none-linux-gnueabi-objdump -d vmlinux >vmlinux.dis
在反汇编文件中查询对应地址 ---> 当前执行的函数标号
grep
(2)addr2line c0277cc8 -e vmlinux -f
表示指定可执行程序 进行显示
dm9000_probe
/home/lf/sys/linux-3.14-OK.bak/drivers/net/ethernet/davicom/dm9000.c:1414
定位当前地址对应的代码位置
文件系统:保存文件的这样的一种系统(逻辑形式)
我们有不同类型的文件系统
linux系统文件系统开始 / 根目录
使用的是树的形式来保存的,需要与对应系统内核进行匹配
根文件系统:存各种系统需要的文件
文件系统包含内容有规范:
1. 文件系统中每个区域的用途
2. 所需要的最小构成的文件和目录
如果制作文件系统?
(1)了解文件系统需要哪些文件和目录
bin:二进制可执行程序(系统级命令)
dev:设备文件(我们所有硬件设备都以文件的形式存储在系统中,操作设备修改是文件)
etc:配置文件(以下四个配置文件是系统必须有的)
├── fstab
├── init.d
│ └── rcS
├── inittab
└── profile
lib:系统库文件目录 (gcc编译最后一步链接 链接库文件)
mnt:挂载点
proc:进程相关目录
sbin:超级用户对的可执行程序
sys:sys子系统文件
tmp:临时文件
usr:普通用户可执行程序、头文件、库文件··
var:可变文件存放位置
(2)创建这些文件和目录
a、创建这些文件夹
mkdir 。。。
b、得到系统可执行命令文件/程序
使用busybox工具来制作得到这些命令程序
busybox工具就制作出了一个可执行程序busybox,我们使用不同的链接文件(ls cd...)最终都会执行的是busybox,busybox会响应用户的不同输入请求,然后进行不同的反馈执行
d、得到系统的库文件
库文件是在链接的时候使用,动态库在调用的时候进行链接调用(应用程序的编译方法必须与库文件的编译方法一致)
因此我们的lib从交叉编译工具中得到,将交叉编译工具链中的库文件拷入我们制作的文件系统目录
d、添加四个配置文件
├── fstab
1 #device mount-point type options dump fsck order
2 proc /proc proc defaults 0 0
3 tmpfs /tmp tmpfs defaults 0 0
4 sysfs /sys sysfs defaults 0 0
5 tmpfs /dev tmpfs defaults 0 0
规定对应的不同类型的文件应该挂载到那个目录下,这种创建文件的方式是在内核执行过程中完成的
注:当前文件仅仅是描述性文件,只描述,不执行也不生效
├── init.d
│ └── rcS
1 #!/bin/sh
2 #This is the first script called by init process
3 /bin/mount -a 挂载fstab中提供的挂载内容
4 echo /sbin/mdev > /proc/sys/kernel/hotplug 将mdev可执行程序输入到hotplug管道中
5 mdev -s 然后执行mdev表示将hotplug生效
注:当前是系统启动的第一个脚本程序,我们可以人为的添加自己想要在系统启动时就开始执行的命令
├── inittab系统初始化配置文件
1 ::sysinit:/etc/init.d/rcS 文件系统初始化执行的脚本文件
2 ::askfirst:-/bin/sh 第一个调用的程序类型
3 ::restart:/sbin/init 重启开发板时执行的是哪个程序
4 ::ctrlaltdel:/sbin/reboot ctrl+alt+del组合键所调用的程序
└── profile
1 #!/bin/sh
2 export HOSTNAME=farsight
3 export USER=root
4 export HOME=root
5 export PS1="[$USER@$HOSTNAME \W]\# "
6 PATH=/bin:/sbin:/usr/bin:/usr/sbin
7 LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
8 export PATH LD_LIBRARY_PATH
附:export表示导出为全局变量
当前文件就是赋值了一些全局变量,其中PS1表示终端显示名称的变量
PATH LD_LIBRARY_PATH表示全局的可执行程序,全局的库文件的系统目录
文件系统的使用:
(1)网络文件系统进行挂载(nfs)
对应uboot中的bootargs参数
setenv bootargs root=/dev/nfs nfsroot=192.168.4.100:/source/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.4.200
开发模式下参数设置
(2)产品模式(EMMC/内存来保存文件系统)
内存文件系统的使用
自启动命令 内核uImage 设备树可执行程序 ramdisk.img
setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;tftp 43000000 ramdisk.img\;bootm 41000000 43000000 42000000
自启动顺序
将上述三个程序在内存中执行
此处内存文件系统大小有限制
将文件系统放入对应emmc某块扇区中
setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;bootm 41000000 - 42000000
set bootargs console=ttySAC2 root=/dev/mmcblk0p2 init=linuxrc rootfstype=ext3
root从对应blk2的扇区启动
文件系统类型:
CRAMFS 只读文件系统
YAFFS2、JFFS2用于Nand/nor flash的文件系统类型
EXT2 非日志文件系统
EXT3/EXT4 日志文件系统
ramdisk 内存文件系统
internal(SOC片中)
针对于exynos4412的启动过程
上电--->IROM(厂商固化程序)--->IRAM(bl1 bl2)--->SRAM(uboot-fs4412.bin)--->SRAM(uImage)--->创建内核线程--->挂载文件系统--->内核规定第一个init的程序(bootargs中设定的init)--->linuxrc--->busybox--->/sbin/init(系统启动的第一个进程)
|______>inittab配置文件的初始化(系统启动的自启动脚本rcS)