一、KConfig、Make
三者之间的关系如下:当我们在内核源码目录下输入make menuconfig时,在出现的菜单界面中选择一项时,它会自动更新.config相应项的值。如果我们没有选择,则会在.config问下插入一行注释。类似于# CONFIG_SERIAL_NONSTANDARD is not set,当我们输入make时,根据makefile文件来编译,makefile文件中的变量值则由.config来进行赋值操作。仅仅只在kconfig中添加选项,只会在菜单界面中显示,即使此时选择y或m,也不会编译文件。还需要在makefile文件中按照规定添加相应行才能进行编译。简单图解如下:
kconfig------->.config---------->makefile
1、内核中加入自己的模块
编写了 mytest.c 的文件,这里不关心 mytest.c 的内容。如果想把 mytest.c 编译到内核中,需要按照以下的步骤来完成:
- 将 mytest.c 放到任何一个目录中,这个目录只要求已存在 Kconfig 和 Makefile 中,比如源码根目录 /arch/arm/ 目录中。
- 在这个目录的 Kconfig 中添加
config MY_TEST bool “My Test”
- 在 Makefile 中添加
obj-$(CONFIG_MY_TEST) += mytest.o
- 在 .config 中可以添加 CONFIG_MY_TEST = y 来选中或者在执行 make menuconfig 时,找到显示名为 My Test 的选项,使用空格选中
总而言之,就是如果需要向系统内核中添加一个功能,那么首先定义一个配置项对应于这个功能,添加到特定的 Kconfig 文件中。然后在 Makefile 里,定义这个配置项需要编译哪些文件。最后就可以通过 make menuconfig 或者直接修改 .config 来使能这个配置项。
二、uboot
git clone https://source.denx.de/u-boot/u-boot.git
uboot研读笔记 | 01 - 下载uboot源码并使用VSCode远程查看源码、编译uboot(2012.04.01版本)
环境变量的优先级
命令传参>环境变量>uboot源码中的设置
史上最全的Uboot常用命令汇总(超全面!超详细!)收藏这一篇就够了
三、Linux内核
1、内核下载
2、错误解决
【错误记录】编译 Linux 内核报错 ( Unable to find the ncurses package. )
make menuconfig错误: /bin/sh: 1: flex: not found 和 /bin/sh: 1: bison: not found
fatal error: libelf.h: No such file or directory 解决方案
【问题解决】fatal error: openssl/xxx.h: 没有那个文件或目录
Linux内核编译错误:make[1]: *** 没有规则可制作目标“debian/canonical-certs.pem”,由“certs/x509_certificate_list” 需求。 停止
Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev
3、docker ubuntu环境
sudo apt-get install make
4、GDB
sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get -y --force-yes install gdb gdb -v sudo apt-get -y --force-yes install gdbserver sudo add-apt-repository --remove ppa:ubuntu-toolchain-r/test sudo apt-get update
5、QEMU
6、vscode
在windows通过VS Code开发Linux内核驱动程序
linux驱动之调试技巧— 应用程序远程gdb+vscode调试应用程序, 串口kgdboc调试.ko驱动程序
vscode + gdb 远程调试 linux 内核源码(附视频)
{ "files.exclude": { "**/.git": true, "**/.svn": true, "**/.hg": true, "**/CVS": true, "**/.DS_Store": true, "**/Thumbs.db": true, "arch/[^ix]*": true, "arch/i[a-z]*": true, "arch/x[a-z]*": true, "arch/x86*": true, "include/asm-[^ixg]*": true, "include/asm-i[a-z]*": true, "include/asm-x[a-z]*": true, "include/asm-x86*": true, "Documentation": true }, "search.exclude": { "**/node_modules": true, "**/bower_components": true, "**/*.code-search": true } }
7、实战步骤
(1) 内核配置
make menuconfig 配置好的文件保存为.config文件,直接以当前运行的X86平台的配置作为参考(cp /boot/config-2.6.18.el5 .config),若要配置2440开发板,则可以参考arch/arm/configs/s3c2410_defconfig 将其拷贝到内核源代码根目录(cp arch/arm/configs/s3c2410_defconfig .config)
注意:就算你完全用别的配置文件,也要执行make menuconfig,就算你什么也不改变,退出时也要记得选保存,这样才会有.config文件
开始内核调试
Kernel hacking
=> Compile-time checks and compiler options
=> Debug information
=> Rely on the toolchain’s implicit default DWARF version
选择 Rely on the toolchain’s implicit default DWARF version 打开调试
(2) 内核映像文件制作
关于bzImage、vmlinux、vmlinuz等内核映像文件
zImage、bzImage、uImage、vmlinuz、vmlinux
# 制作RamFs(RootFs文件夹,主要为busybox和init文件) ├── bzImage ├── initramfs.img ├── Makefile └── rootfs ├── bin ├── init ├── linuxrc -> bin/busybox ├── sbin └── usr
(a)init 文件
#!/bin/busybox sh /bin/busybox echo "Hello Linux" /bin/mount -t proc none /proc /bin/busybox sh
或者参考 超级详细讲解根文件系统rootfs的制作 进行制作Rootfs
(2) QEMU调试参数
cmdline:nokaslr (禁用内核地址空间布局随机)
-S 在开始时阻塞 CPU 执行
-s 开启 GDB 服务器,端口 1234
-gdb tcp::1234 开启 GDB 服务器,端口可以自己指定
qemu-system-x86_64 \ -kernel bzImage \ -initrd initramfs.img \ -m 1G \ -nographic \ -append "earlyprintk=serial,ttyS0 console=ttyS0 nokaslr" \ -S \ -gdb tcp::1234
(a)运行脚本
Makefile 中 ramfs 目标用来创建 initramfs.img,run 目标用来引导新建的内核和根文件系统。
ramfs: cd ./rootfs && find . -print0 | cpio -ov --null --format=newc | gzip -9 > ../initramfs.img run: qemu-system-x86_64 \ -kernel bzImage \ -initrd initramfs.img \ -m 1G \ -nographic \ -append "earlyprintk=serial,ttyS0 console=ttyS0"
(3) GDB 命令调试
target remote:1234
break start_kernel
continue
step
# 启动内核 make run #调试内核 gdb vmlinux # 根下的vmlinux # 连接远端gdb端口 target remote :1234 # 设置断点 break start_kernel # 可通过System.map查看断点地址和信息 continue gdb init
(4)vscode 界面调试
(a)launch.json
.vscode 下 launch.json ,配置调试信息。
// launch.json { // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "gdb debug", "type": "cppdbg", "request": "launch", // "miDebuggerServerAddress": "172.18.25.30:1234", "miDebuggerServerAddress": "127.0.0.1:1234", "program": "${workspaceRoot}/vmlinux", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "logging": { "engineLogging": false }, "MIMode": "gdb" } ] }
(b)c_cpp_properties.json
- 生成 compile_commands.json
# 生成 compile_commands.json ./scripts/clang-tools/gen_compile_commands.py
- 配置 c_cpp_properties.json
.vscode 下 c_cpp_properties.json 可以使用 CTRL + SHIFT + P 选择 C/C++: Edit Configurations,创建 c_cpp_properties.json 文件。
// c_cpp_properties.json { "configurations": [ { "name": "Linux", "includePath": [ "${workspaceFolder}/**" ], "defines": [], "compilerPath": "/usr/bin/gcc", "cStandard": "c17", "cppStandard": "c++14", "intelliSenseMode": "linux-clang-x64", "compileCommands": "${workspaceFolder}/compile_commands.json" } ], "version": 4 }
(5)QEMU 命令
CTAL + A,然后按 x 键
8、前置知识
(1)多个版本GCC编译器的安装
9、Linux 0.11
10、Linux 内核设计与实现
11、深入理解 Linux 内核
四、内核驱动
1、Camera 与 V4L2
【Camera基础(一)】Camera摄像头工作原理及整机架构
【Camera基础(二)】摄像头驱动原理和开发&&V4L2子系统驱动架构
基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集
基于ZedBoard的Webcam设计(二):USB摄像头图片采集+QT显示
基于ZedBoard的Webcam设计(三):视频的采集和动态显示
基于ZedBoard的Webcam设计(四):MJPG编码和AVI封装
基于ZedBoard的Webcam设计(五):x264编码在zedboard上的实现(软编码)
Linux摄像头驱动学习之:(二)通过虚拟驱动vivi分析摄像头驱动
五、busybox
bootloader与linux中位置无关代码(PIC)的分析理解