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配合内核源码路径完成 那么如何将驱动直接编译进内核呢? ...
随机推荐
- scrapy实现数据持久化、数据库连接、图片文件下载及settings.py配置
数据持久化的两种方式:(1)基于终端指令的持久化存储:(2)基于管道的持久化存储 基于终端指令的持久化存储 在爬虫文件的parse方法中必须要return可迭代对象类型(通常为列表或字典等)的返回值, ...
- OpenResty高性能web平台
openresty高性能web平台安装使用 简介:OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库.第三方模块以及大多数的依赖项.用 ...
- ELK-日志管理平台
elk日志收集工具 1.日志在工作当中的重要性 1 分析日志的意义: 2 1.分析日志监控系统运行的状态 3 2.分析日志来定位程序的bug 4 3.分析日志监控网站访问流量 ...
- DevOps生命周期,你想知道的全都在这里了!
在大多数情况下,软件应用程序开发由于其规范性和复杂性而变得很耗时. 为了在短时间内交付高质量应用程序,软件开发人员正在遵循一套通用的实践,称为DevOps生命周期. 那么,DevOps在软件应用程序开 ...
- [编辑排版]小技巧---markdown 转 richText
Markdown 使用markdown,可以方便地编辑富文本,VSCode自带了对markdown的支持,编辑完成后可点击右上角预览,实时查看效果. 在github上有给账号,就可以使用GithubP ...
- [wordpress使用]001_环境安装
Wordpress强大的可扩展性和易用性等功能,使得越来越多的人选择它来建立自己的博客和网站.那么新手朋友该如何入手呢,今天制作这个教程就是旨在帮助新手朋友快速入门,从而为今后WP建站打下坚实的基础. ...
- [PHP自动化-进阶]003.CURL处理Https请求访问
引言:继前文<模拟登录并采集数据>,<模拟登录带有验证码的网站>,大家对CURL基本上已经有了认识,这一讲简单的说一下请求Https. 在很多的站点,如TalkingData, ...
- [注]一将功成万骨枯!App的七种死法
一将功成万骨枯,这种事在有泡沫的行业总是会发生的.移动互联网尤甚.从<愤怒的小鸟>到<植物大战僵尸>.<捕鱼达人>.<唱吧>.<陌陌>……一 ...
- [优文翻译]001.真正程序员该是什么样的(How To Be A Real Programmer)
01.Real Programmers don't write specs -- users should consider themselves lucky to get any programs ...
- Java动态代理与静态代理以及它能为我们做什么
相信我们在网上和平时学习和工作中或多或少都接触过Java的代理模式,经常听到什么静态代理.动态代理的一些名词.但我们是否真的很清楚这些呢?至少我在面试时,发现很多人并不很清楚. 首先代理比较好理解,就 ...