从技术上说 linux 是一个内核
“内核”指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。一个内核不是一套完整的操作系统。
通常我们使用的 linux 系统是一个集 linux 内核、工具集、各种库、桌面管理器、应用程序等一体的一个发布包 (发行版)
目前linux系统采用 A.B.C.D 的版本号管理方式
A 表示linux的主版本号
B 表示linux的次版本号,B 为偶数表示稳定版本,奇数表示开发中的版本
C 表示linux的发行版本号
D 表示更新版本号
主版本(X.Y)
1.0 2.0 2.2 2.4 2.6 3.x
linux官网网址 https://www.kernel.org/
linux采用时间片的形式进行内核调度,并不是真正意义上的实时系统。相对应的 VxWork系统是实时操作系统,采用抢占式内核调度和中断管理。
进程管理
内存管理
文件系统
网络协议
设备管理
注意要把 linux源码 拷贝到 Ubuntu中 解压, 因为 源码中会有一些软件链文件, 这些文windows文件系统 不能识别
tar -xvf ***.tar.xz
配置交叉编译工具链:
1.export PATH=/自己的路径/gcc-4.6.4/bin:$PATH
2. 写到启动脚本中 /etc/profile 或者 .bashrc
修改 源码顶层目录的 Makfile
ARCH ?= arm
CROSS_COMPILE ?= arm-none-linux-gnueabi-
注意,编译工具与内核要配套使用。
编译内核
make uImage
编译设备树
make dtbs
设备树: 用于描述硬件设备信息。
低版本内核的设硬件备信息,是存放在linux源码中的
高版本是写到 设备树文件中
提醒: 如果想启动内核,还需要配置一下网络
网络配置学习视频
系统移植之网络配置 http://e.vhall.com/102020226
☆ arch 不同CPU体系结构的差异代码
-> arm 不同板子板子的源码
-> boot uImage zImage
-> dts 设备树
☆ driver 驱动目录
-> net 网络驱动 (与设备相关)
kernel 内核调度算法
net 网络协议 (与设备无关的)
block 块设备相关驱动
fs 文件系统
include 头文件存放目录
Documentation 帮助文档
tools 工具
scripts 编译内核时使用的脚本
ipc 进程间通信
mm 内存管理
启动 u-boot -> kernel -> rootfs(root filesystem) 启动脚本 /etc/init.d/rcS 自启动应用 Starting kernel ... 属于 uboot的打印 重点理解 uboot 启动流程(面试出现频率高) 内核启动流程 a. 自解压 decompess (arch/arm/boot/compressed/head.S) 汇编 b. 检测合法性 入口 stext (arch/arm/kernel/head.S) (CPU 类型 机器类型) c. 运行 C代码 start_kernel (init/main.c) d. 挂在 rootfs e. 运行第一个应用程序 linuxrc
与上面的对照分析着看 更易理解
cat /proc/sys/kernel/printk 显示 4 4 1 7
echo "7 4 1 7" > /proc/sys/kernel/printk
cat /proc/sys/kernel/printk 显示7 4 1 7
8个打印级别
#define KERN_EMERG "<0>" /*紧急事件消息,系统崩溃之前提示,表示系统不可用*/ #define KERN_ALERT "<1>" /*报告消息,表示必须立即采取措施*/ #define KERN_CRIT "<2>" /*临界条件,通常涉及严重的硬件或软件操作失败*/ #define KERN_ERR "<3>" /*错误条件,驱动程序常用KERN_ERR来报告硬件的错误*/ #define KERN_WARNING "<4>" /*警告条件,对可能出现问题的情况进行警告*/ #define KERN_NOTICE "<5>" /*正常但又重要的条件,用于提醒。常用于与安全相关的消息*/ #define KERN_INFO "<6>" /*提示信息,如驱动程序启动时,打印硬件信息*/ #define KERN_DEBUG "<7>" /*调试级别的消息*/
init/main.c - start_kernel
第一次编译内核代码会比较长时间
如果修改或者添加源文件,再次编译,只会编译变化的部分 会快一些
将新编译的uImage存入tftp文件夹,运行开发板。
测试printk成功。
pc : 程序计数器
arm-none-linux-gnueabi-addr2line pc地址 -e vmlinux -f
在源码中显示具体出错的位置
范例:
修改drivers/char/fs4412_led_drv.c
在s5pv210_led_init函数中int ret=0;下增加下面语句: int *ptr = NULL; *ptr = 0xff;
linux-3.14-fs4412/drivers/char/Makefile 这里需要修改下,不然编译的时候不会编译到该文件。
[ 1.165000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[ 1.170000] pgd = c0004000
[ 1.175000] [00000000] *pgd=00000000
[ 1.175000] Internal error: Oops: 805 [#1] PREEMPT SMP ARM
[ 1.180000] Modules linked in:
[ 1.185000] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.14.0 #25
[ 1.190000] task: ee8a0000 ti: ee8a4000 task.ti: ee8a4000
[ 1.195000] PC is at s5pv210_led_init+0x18/0x180
[ 1.200000] LR is at do_one_initcall+0x30/0x144
[ 1.205000] pc : [<c024225c>] lr : [<c00087b4>] psr: 60000153
[ 1.205000] sp : ee8a5ef8 ip : c059afac fp : 00000000
[ 1.215000] r10: c052d4fc r9 : c0564b80 r8 : c0242244
[ 1.220000] r7 : c05a3400 r6 : c055134c r5 : 00000000 r4 : ee8a4000
[ 1.230000] r3 : 00000055 r2 : c04c0430 r1 : 00000001 r0 : 1f400000
[ 1.235000] Flags: nZCv IRQs on FIQs off Mode SVC_32 ISA ARM Segment kernel
[ 1.245000] Control: 10c5387d Table: 4000404a DAC: 00000015
[ 1.250000] Process swapper/0 (pid: 1, stack limit = 0xee8a4240)
[ 1.255000] Stack: (0xee8a5ef8 to 0xee8a6000)
根据PC is at s5pv210_led_init+0x18/0x180 知道出错的函数是s5pv210_led_init
根据pc : [<c024225c>] 知道出错的位置
#arm-none-linux-gnueabi-addr2line c024225c -e vmlinux -f 在源码中会显示具体出错的位置