Linux内核配置编译及基本调试方法
一、Linux内核配置编译
1. 交叉编译设置:make ARCH=arm CROSS_COMPILE=arm-linux-
注:也可以直接修改顶层Makefile
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
2. 加载默认设置:make mini2440_defconfig
① make mini2440_config: 将arch/arm/configs目录下的mini2440_defconfig文件复制为.config
② make menuconfig: 对内核默认配置进行调整
3. 编译内核
① make zImage
② make modules
③ make uImage(uImage是在zImage基础上加了64Bytes的头信息)
④ make bzImage(内核最终镜像大于512KB)
4. 安装内核:
make install
make modules_install
5. 内核配置系统由以下3部分组成
① Makefile:
② Kconfig:
③ 配置工具:
注:使用make config、make menuconfig等命令后,内核顶层目录生成一个“.config‘’配置文件,该文件记录模块是否编译进内核、或者编译成模块
6. 运行make menuconfig时,配置工具首先分析与体系结构对应的arch/<arch>/Kconfig文件,该文件除本身包含一些与体系结构相关的配置项和配置菜单外,还通过sourse语句引入下一层的Kconfig文件
7. 在make menuconfig界面中选择“config ARCH_S3C2410”选项后内核会在配置文件".config"中添加
CONFIG_ARCH_S3C2440=y
同时在include/config目录中生成由.config得来的配置文件auto.conf,以及在include/linux目录中以C语言头文件给出的配置文件autoconf.h
8. 执行make zImage等生成内核镜像命令时,首先执行顶层Makefile,顶层Makefile又通过include指令导入特定体系架构或子目录中的Makefile
① 顶层Makefile:
include $(srctree)/arch/$(SRCARCH)/Makefile
② arch/arm/Makefile:
machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443
③ machine-y用于定义machdirs变量
machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
④ machdirs通过下面语句添加到core-y中(cory-y表示内核需要编译的核心文件)
cory-y += $(machdirs) $(platdirs)
9. 向内核中添加新的功能的步骤
① 将编写的源代码复制到Linux内核源代码相应目录
② 在目录的Kconfig文件中增加新源代码对应项目的编译配置选项
③ 在目录的Makefile文件中增加对新源代码的编译条目
10. 向内核中添加RTC驱动:
① 在drivers/rtc中包含S3C24XX处理器的RTC驱动源代码rtc-s3c.c
② 在drivers/rtc目录的Kconfig文件中包含RTC_DRV_S3C的配置项目
config RTC_DRV_S3C
tristate "Samsung S3C series SoC RTC"
depends on ARCH_S3C2410
help
RTC (Realtime Clock) driver for the clock inbuilt into the
Samsung S3C24XX series of SoCs. This can provide periodic
interrupt rates from 1Hz to 64Hz for user programs, and
wakeup from Alarm. The driver currently supports the common features on all the
S3C24XX range, such as the S3C2410, S3C2412, S3C2413, S3C2440
and S3C2442. This driver can also be build as a module. If so, the module
will be called rtc-s3c.
③ 在drivers/rtc目录的Makefile文件中添加关于RTC_DRV_S3C的条目
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
11. 内核中的Makefile
① 目标定义:目标定义用来定义哪些内容要作为模块编译,哪些要编译进内核
obj-y += foo.o
更常见的做法是根据auto.conf文件的CONFIG_变量来决定文件的编译方式,例如
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
② 多文件模块的定义:如果一个模块由多个文件组成,就应该采用模块名加-objs后缀或者-y后缀的形式来定义模块的组成文件。
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
rtc-core-y := class.o interface.o
多文件模块定义也可以按照下面的格式,
obj-$(CONFIG_ISDN) += isdn.o
isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o
③ 目录层次迭代:当CONFIG_EXT3_FS的值为y或m时,内核构建系统会将ext3目录列入向下迭代的目标中
obj-$(CONFIG_EXT3_FS) += ext3/
12. 内核中的Kconfig
① Kconfig的语法比较丰富,按功能可分为配置选项描述语句和菜单结构描述语句
② 配置选项描述:
(1)“config”关键字定义新的配置选项,之后的几行定义该配置选项的属性
(2) 配置选项的属性包括类型、数据范围、输入提示、依赖关系、帮助信息和默认值
(3) 每个配置选项都必须指定类型,类型包括bool、tristate、string、hex和int。其中,tristate和string是两种基本类型,其他都是基于这两种基本类型。
(4) 输入提示的一般格式:
prompt <prompt> [if <expr>]
(5) 默认值的一般格式:
default <expr> [if <expr>]
(6) 依赖关系的格式:
depend on(requires) <expr>
(7) 选择(反向依赖)的格式:
select <symbol> [if <expr>]
(8) 数据范围的格式:
range <symbol> <symbol> [if <expr>]
(9) 帮助信息格式如下:
help(---help---)
(10) 一个简单的配置选项示例
config MODVERSIONS
bool
prompt "Set version infomation on all module sysbols"
help
Usually, modules have to be recompiled whenever you switch to a new kernel③
③ 菜单结构
(1)一般菜单结构由menu......endmenu描述
menu "Network device support"
depends on NET
config NETDEVICES
...
endmenu
注:所有处于“menu”和“endmenu”之间的菜单入口都会成为“Network device support”的子菜单,而且所有子菜单入口都会继承父菜单的依赖关系。
(2)通过分析依赖关系生成菜单结构
config MODULES
bool "Enable loadable module support" config MODVERSIONS
bool "Set version information on all module symbols"
depend on MODULES
(3)除此之外,Kconfig中还可能使用“choices...endchoices”、“comment”、“if...endif”这样的语法结构
二、Linux内核调试技术
1. 源码级别的调试接口
① BUG()和BUG_ON():当调用BUG()时,内核通过调用panic()引发OOPS,导致函数调用栈的回溯和打印错误信息。
#ifndef HAVE_ARCH_BUG
#define BUG() do { \
printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
panic("BUG!"); \
} while ()
#endif #ifndef HAVE_ARCH_BUG_ON
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
#endif
注:内核还提供了WARN()和WARN_ON()用于警告作用。
② dump_stack():打印寄存器上下文和函数的跟踪线索。
if (!consistent_pte[]) {
printk(KERN_ERR "%s: not initialised\n", __func__);
dump_stack();
return NULL;
}
③ printk()内核格式化打印函数。
(1)几乎在任何地方、任何时候内核都可以调用它(中断上下文、进程上下文、持有锁时、多处理器处理时等)。
(2)在系统启动过程中和终端初始化之前无法调用。可以用以下方法打印调试信息:
* 通过底层调试接口,将调试信息输出到串口等输出设备(Kernel low-level debugging functions)
* 使用early_printk()
④ printk_ratelimit():限制输出速率
(1)printk_ratelimit()的典型用法
if(printk_ratelimit())
printk(KERN_NOTICE "The printer if still on fire\n");
(2)printk_ratelimit()的返回值取决于两个因素,分别定义于以下两个文件
* /proc/sys/kernel/printk_ratelimit
* /proc/sys/kernel/printk_ratelimit_burst
例如:printk_ratelimit = 5、 printk_ratelimit_burst = 10表示每打印10次就会有5s不会向控制台输出。
2. 使用printk()打印调试信息
① 日志等级
(1)printk()和printf()一个主要区别就是前者可以指定一个日志等级
#define KERN_EMERG "<0>" /* system is unusable */
#define KERN_ALERT "<1>" /* action must be taken immediately */
#define KERN_CRIT "<2>" /* critical conditions */
#define KERN_ERR "<3>" /* error conditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition */
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */
注:如果调用者未将日志等级提供给printk,系统就使用默认值:KERN_WARNING "<4>"
(2)/proc/sys/kernel/printk文件定义了当前使用的日志等级,4个数字分别表示控制台日志级别、默认消息日志级别、最小控制台日志级别和默认控制台日志级别。
/Test/TestOops # cat /proc/sys/kernel/printk
注:修改printk的值可以用如下命令
echo > /proc/sys/kernal/printk
② 日志缓冲区
(1)内核消息被保存在一个LOG_BUF_LEN大小的环形队列中。
(2)日志缓冲区的特点:
* 消息被读出到用户空间,此消息就从环形队列中删除
* 当消息缓冲区满时,再有printk()调用时,新消息将覆盖队列中的老消息
* 在读写环形队列时,同步问题很容易解决
③ syslogd/klogd
④ dmesg
⑤ 注意事项
(1)虽然printk()很健壮,但效率很低
(2)printk()的临时缓存printk_buf只有1KB,所以printk()函数一次只能记录小于1KB的信息到日志缓冲区,并且使用时注意是环形缓冲区。
3. 使用strace跟踪系统调用
① strace命令常用来跟踪进程执行时的系统调用和接受的信号
4. 使用OOPS调试系统故障
Linux内核配置编译及基本调试方法的更多相关文章
- Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装
原文:Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装 Linux内核分析(一) 从本篇博文开始我将对linux内核进行学习和分析,整个过程必将十分艰辛,但我会坚持到底 ...
- Linux内核@系统组成与内核配置编译
Linux系统由什么组成? 由用户空间(应用程序+GNU C标准库)和内核空间(系统调用接口+内核+内核架构代码)组成. Linux内核到底是什么?以及组成. ARM的七种操作级别? 内核网络协议栈( ...
- Linux 内核配置和编译
Linux 内核配置和编译 一.配置内核 (1). 为什么要配置内核 1. 硬件需求 2. 软件需求 选出需要的,去掉不要的 (2). 如何配置内核 1. make config 基于文本模式的交互 ...
- 【Linux内核】编译与配置内核(x86)
[Linux内核]编译与配置内核(x86) https://www.cnblogs.com/jamesharden/p/6414736.html
- linux内核空间与用户空间信息交互方法
linux内核空间与用户空间信息交互方法 本文作者: 康华:计算机硕士,主要从事Linux操作系统内核.Linux技术标准.计算机安全.软件测试等领域的研究与开发工作,现就职于信息产业部软件与 ...
- Linux内核配置浅析
1.Linux Kernel Kconfig系统的基本结构 Linux内核的配置系统由三个部分组成,分别是: 1>.Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Li ...
- Linux内核配置机制(make menuconfig 、Kconfig、Makefile)讲解【转】
本文转载自:http://www.codexiu.cn/linux/blog/34801/ 前面我们介绍模块编程的时候介绍了驱动进入内核有两种方式:模块和直接编译进内核,并介绍了模块的一种编译方式—— ...
- 【转】 Linux内核中读写文件数据的方法--不错
原文网址:http://blog.csdn.net/tommy_wxie/article/details/8193954 Linux内核中读写文件数据的方法 有时候需要在Linuxkernel--大 ...
- Linux 内核配置机制(make menuconfig、Kconfig、makefile)讲解
前面我们介绍模块编程的时候介绍了驱动进入内核有两种方式:模块和直接编译进内核,并介绍了模块的一种编译方式--在一个独立的文件夹通过makefile配合内核源码路径完成 那么如何将驱动直接编译进内核呢? ...
随机推荐
- vue v-for 渲染input 输入有问题 解决方案
v-for循环input标签的时候输入信息两个输入框一同显示输入信息 解决方案: <input :placeholder="items.title" v-model = &q ...
- Java并发编程实战 05等待-通知机制和活跃性问题
Java并发编程系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 Java并发编程实 ...
- 汉语分词工具包jieba
#分词pip install jieba import jieba str="你真的真不知道我是谁吗?" res1=jieba.cut(str) print(list(res1)) ...
- 利用js实现 禁用浏览器后退| 去除上一个历史记录链接
也是查找了好多资料才找到的,这种方式,可以消除 后退的所有动作.包括 键盘.鼠标手势等产生的后退动作. <script language="javascript"> / ...
- 容器技术之Docker基础入门
前文我们了解了下LXC的基础用法以及图形管理工具LXC WEB Panel的简单使用,有兴趣的朋友可以参考https://www.cnblogs.com/qiuhom-1874/p/12904188. ...
- 转义URL 含有中文和特殊符号
方法1: //这个方法被废弃了 NSString *urlString = @"https://www.cnblogs.com/huaida/#/程序员"; NSString* e ...
- Mac更新系统后提示xcrun error
更新mac os后无法运行git,gcc等命令,出现missing xcrun错误. 这是因为更新系统后会卸载xcode,重新安装后会缺失xcode的命令行工具(command line tools) ...
- Hystrix入门
hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,这与hystrix本身的功能不谋而合,因此Netflix团队将该框架命名为Hystrix,并使用 ...
- JSP页面基础用法和方法查询
导包jar:jstl.jar standard.jar jsp嵌套java代码,使用jsp脚本:1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 ...
- Parrot os KDE还是MATE版本
在经历了KDE桌面痛苦折磨后,准备转投MATE的怀抱,不得不说Parrot KDE的ram的占有和windows 10差不多,大量的图形化处理,让我本来不多的内存更加血上加霜. 所以,关于版本的推荐, ...