嵌入式系统移植万字学习笔记分享

目录

第一部分

嵌入式系统移植导学

一. 嵌入式系统分层

二. 课程内容

三. 系统移植的目的

四. 系统移植过程

Windows装机

Linux系统移植

第二部分

开发板启动流程 

一. 开发板启动过程

二. 系统移植步骤

第三部分

交叉开发环境的搭建

一. ubuntu网络配置

1、桥接模式

2、NAT模式和仅主机模

二. tftp

三. nfs

第四部分

uboot概述及SD卡制作

一. bootloader

开发板启动过程

2. BOOT LOADER

3, 常见的boot loader

二. SD卡知识

SD卡的存储结构

第五部分

uboot的使用

1. uboot模式

2. uboot帮助命令

3. uboot环境变量命令

4. 常用环境变量

5. Uboot网络传输命令

6. uboot存储器访问命令

7. uboot自启动环境变量

第六部分

linux内核安装及交叉编译

1. uboot内核启动命令

2. uboot自启动参数环境变量

3. 开发板启动过程

4. 给开发板装操作系统的几种办法

第七部分

交叉编译工具链

1. 交叉编译

一. 编译原理

二. GCC编译过程

三. 交叉编译

四. 交叉编译工具链

1.  交叉编译工具链的获取:

2. ELF格式

一. ELF文件格式

二. ELF文件相关命令

三. BIN文件格式

3. 交叉编译工具链常用工具

第八部分

uboot源码配置编译

一. uboot源码结构

二. uboot配置与编译

第九部分

uboot移植深化

 

第十部分

linux内核移植

1. linux内核概述

一. 内核与操作系统

二. 层次结构

三. linux内核特点

2. linux内核源码结构

一. Linux内核源码获取

 Linux内核源码下载

 Linux内核版本命名

 Linux内核版本选择

二. Linux内核源码结构

平台相关代码

平台无关代码

帮助文档、示例程序、工具等

3. linux内核源码的配置与编译

一. Linux内核源码配置

二. make menuconfig

三. Linux内核源码编译

第十一部分

linux驱动移植及内核深化

1. 设备树

一. 设备树

二. 设备树语法概述

三. linux内核驱动移植

第十二部分

linux内核调试及rootfs移植

1. 根文件系统

一. 根文件系统

二. 根文件系统内容

三. BusyBox


第一部分


嵌入式系统移植导学



一. 嵌入式系统分层

二. 课程内容

安装系统

   

    在基于ARM处理器的开发板上安装Linux系统

三. 系统移植的目的

移植

    不同架构的处理器指令集不兼容,即便是相同的处理器架构,板卡不同驱动代码也不兼容

    Linux是一个通用的内核并不是为某一个特定的处理器架构或板卡设计的,所以从官方获取Linux源码后我们要先经过相应的配置使其与我们当前的硬件平台相匹配后才能进行编译和安装, 对不需要的功能进行裁剪留下需要的功能就行。

四. 系统移植过程

Windows装机

  1.准备Windows系统镜像(系统的安装包)、U盘启动盘(大白菜, 黄桃)

  2.进入BIOS选择启动方式(U盘启动, 电脑在启动的时候按下功能键, 不同电脑品牌进入BIOS模式不同)

  3.通过U盘中的引导程序安装系统

  4.安装Windows驱动程序(驱动外设工作)

  5.安装Windows应用程序

Linux系统移植

  1.准备Linux内核镜像、SD卡启动盘(SD卡里面存储UBOOT安装引导程序)

  2.通过拨码开关选择启动方式(SD启动)

  3.通过SD卡中的引导程序安装系统

  4.安装Linux驱动程序

  5.安装Linux应用程序

第二部分


开发板启动流程 



一. 开发板启动过程

开发板上电后首先运行SOC内部iROM中固化的代码(BL0),这段代码先对基本的软硬件环境(时钟等...)进行初始化,然后再检测拨码开关位置获取启动方式,然后再将对应存储器中的uboot搬移到内存,然后跳转到uboot运行

 uboot开始运行后首先对开发板上的软硬件环境做进一步初始化,然后将linux内核、设备树(dtb)、根文件系统(rootfs)从外部存储器(或网络)搬移到内存,然后跳转到linux运行

 linux开始运行后先对系统环境做初始化,当系统启动完成后,Linux再从内存中(或网络)挂载根文件系统

二. 系统移植步骤

uboot移植

 linux内核移植(包含设备树)

 根文件系统移植


知识补充: 操作系统的作用


操作系统是一种软件,它是计算机系统中的核心组成部分,具有以下主要作用:

资源管理:操作系统管理计算机的各种资源,包括处理器、内存、存储设备、输入输出设备等。它负责分配和调度这些资源,以便多个程序可以同时运行,并且有效地利用计算机资源。

进程管理:操作系统负责管理进程(程序的执行实例)。它为不同的进程分配处理器时间,并根据优先级和调度算法进行调度。操作系统还提供了进程间的通信和同步机制,以确保进程的协调和共享资源的安全访问。

内存管理:操作系统负责管理计算机系统的内存资源。它管理和分配内存空间,将进程加载到内存中,并根据需要进行内存的回收和释放。操作系统还处理内存碎片问题,提供虚拟内存等机制来扩展物理内存的使用。

文件系统管理:操作系统提供文件系统来管理和组织存储设备中的数据。它处理文件的创建、修改、删除等操作,提供了文件的访问和保护机制,以及文件的组织和备份策略。

用户界面:操作系统提供用户与计算机系统之间的交互界面。这可以是命令行界面(如终端),也可以是图形用户界面(如操作系统的桌面环境)。用户通过界面来执行操作和访问系统功能。

设备管理:操作系统管理计算机的各种硬件设备,包括打印机、键盘、鼠标、网络设备等。它提供设备驱动程序和接口,使应用程序可以方便地与硬件设备进行通信和控制。

总之,操作系统的作用是为用户和应用程序提供一个统一的、可靠的、高效的计算机环境,实现资源管理、进程管理、内存管理、文件系统管理、用户界面和设备管理等功能,以便有效地管理和控制计算机系统的运行。

第三部分


交叉开发环境的搭建



一. ubuntu网络配置

1、桥接模式

桥接模式:利用本机真实的网卡进行通信。虚拟机设置跟本机在一个网段的ip后,不仅可以与本机通信,还可以与本机在同一局域网内的其他设备通信,如果本机连接互联网,模拟机也可以上网。其实就相当于一台单独的电脑。缺点是需要占用该网段一个IP。

2、NAT模式和仅主机模

"NAT模式"和"仅主机模式"都是利用虚拟网卡进行通信。

(2.1)、Nat模式:使用虚拟网卡VMNET8进行通信。可以与主机通信,如果主机连网,虚拟机也可以连网。但是无法与主机所在的局域网内的其他设备通信。优点是不需要占用本机网段的IP。


知识补充:什么是网关


网关(Gateway)又称网间连接器、协议转换器。网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关的结构也和路由器类似,不同的是互连层。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。在使用不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的信息要重新打包,以适应目的系统的需求。同时,网关也可以提供过滤和安全功能。大多数网关运行在OSI 7层协议的顶层--应用层。

顾名思义,网关(Gateway)就是一个网络连接到另一个网络的“关口”。在OSI中,网关有两种:一种是面向连接的网关,一种是无连接的网关。当两个子网之间有一定距离时,往往将一个网关分成两半,中间用一条链路连接起来,我们称之为半网关。

二. tftp

tftp(Trivial File Transfer Protocol)即简单文件传输协议

是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件

传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69

三. nfs

nfs(Network File System)即网络文件系统,其基于UDP/IP

使用nfs能够在不同计算机之间通过网络进行文件共享,能使使用

者访问网络上其它计算机中的文件就像在访问自己的计算机一样。

第四部分


uboot概述及SD卡制作



一. bootloader

  1. 开发板启动过程

开饭板启动流程之前上面有说

2. BOOT LOADER

Bootloader

    在操作系统运行之前运行的一小段代码,用于将软硬件环境初始化到

一个合适的状态,为操作系统的加载和运行做准备(其本身不是操作系统)

 Bootloader基本功能

    -> 初始化软硬件环境

    -> 引导加载linux内核

    -> 给linux内核传参

    -> 执行用户命令, 在sercur crt中可以执行uboot命令。

注:bootloader是启动引导程序的统称,嵌入式linux常用的bootloader是uboot        

3, 常见的boot loader

二. SD卡知识

SD卡的存储结构

SD卡的存储以扇区为单位,每个扇区的大小为512Byte, 其中零扇区存储分区表(即分区信息, 即是sd每一个扇区的使用情况),后续的扇区可自行分区和格式化;

   若选择SD卡启动,处理器上电后从第一个扇区(块)开始将其中的内容搬移到内存,所以我们把uboot放到从第一个扇区开始之后的空间, 之后的空间根据个人需求可进行分区和格式化


知识补充


1. 从windows拖拽文件到Linux下

2. 做这一步的目的

为了空出SD卡前的512个字节, 空出一个扇区

3. boot   引导       loader  加载

第五部分


uboot的使用



1. uboot模式

自启动模式

    uboot启动后若没有用户介入,倒计时结束后会自动执行自启动

    环境变量(bootcmd)中设置的命令(一般作加载和启动内核)

 交互模式

    倒计时结束之前按下任意按键uboot会进入交互模式,交互模式下

    用户可输入uboot命令, 这也是uboot的作用之一, 执行用户命令。

2. uboot帮助命令

 help

    查看uboot支持的所有命令

 help 命令

    查看当前命令的使用方法        

3. uboot环境变量命令

printenv

    打印uboot中所有的环境变量

 setenv

    设置指定的环境变量(保存在RAM中)

        setenv 环境变量 环境变量的值        

 saveenv

    保存所有环境变量到EMMC中,执行完setenv命令之后再设置一下saveenv命令, 将修改的内容保存到emmc中。

4. 常用环境变量

ipaddr

    uboot的IP地址

 serverip

    服务器的IP地址(即ubuntu的IP)        

 bootdelay

    进入自启动模式之前倒计时的秒数, 否则按下任意键就就是进入到uboot交互模式。

5. Uboot网络传输命令

loadb

    通过Kermit协议下载文件到指定的内存地址

        loadb  地址

 tftp

    通过tftp协议下载文件到指定的内存地址

        tftp  地址  文件名(将文件下载到内存的哪一个位置)        

注:使用tftp之前要配置好网络及tftp服务器, 在服务器的tftp服务器要运行起来, uboot本身已经安装了tftp的客户端了。

6. uboot存储器访问命令

mmc read

    将EMMC中指定扇区中的内容读取到内存中指定的地址

mmc read  <addr> <blk#> <cnt>

addr:        内存地址

blk#:        EMMC中的扇区编号

cnt:        读取的扇区的个数

 mmc write

    将内存中指定地址中的内容写入到EMMC中指定的扇区

        mmc write <addr> <blk#> <cnt>        

7. uboot自启动环境变量

bootcmd

    自启动的环境变量

    该环境变量可以设置成一到多个uboot命令的集合(若有多个使用\;分割)

    自启动模式下uboot就会按照bootcmd中命令的顺序逐条执行

eg:

    setenv bootcmd tftp 40008000 interface.bin\; go 40008000

    saveenv

一条命令的结束, 以\;结束。


知识补充


通过tftp协议从服务端下载文件到内存的0x41000000这个位置

0 代表emmc, 1代表内存

对应上图:

  • 使用bootcmd这个命令让uboot在自启动模式下帮我们做一些事情
  • mmc命令
  • ubbot内部包含tftp协议, 不需要我们在开发板上装tftp的客户端
  • 这句命令的意思

第六部分


linux内核安装及交叉编译



1. uboot内核启动命令

bootm

    启动指定内存地址上的Linux内核并为内核传递参数

bootm kernel-addr ramdisk-addr dtb-addr

注:

    kernel-addr:        内核的下载地址 

    ramdisk-addr:        根文件系统的下载地址          

    dtb-addr:                设备树的下载地址

    若不使用相应的地址,对应的位置写“-”

eg:

    bootm 0x41000000 - 0x42000000        

2. uboot自启动参数环境变量

bootargs

    eg:

    setenv bootargs root=/dev/nfs nfsroot=xxx.xxx.xxx.xxx:/opt/4412/rootfs    

    rw console=ttySAC2,115200 init=/linuxrc ip=***.***.***.***

    注:

root                根文件系统类型(nfs)

nfsroot         网络文件系统路径(xxx.xxx.xxx.xxx:/opt/4412/rootfs)

rw                        操作网络文件系统的权限(rw)

console        控制台(使用串口2,波特率115200)

init                init进程的位置(/linuxrc)

ip                  linux启动后自身的IP(***.***.***.***)(开发板自身的IP)

该环境变量是用来给linux内核启动时给内核传参的,

3. 开发板启动过程

4. 给开发板装操作系统的几种办法

(1)通过 tftp 加载内核和根文件系统

(2)通过 EMMC 加载内核和根文件系统

(3)通过 tftp 加载内核通过 nfs 挂载根文件系统

(4)将uboot 安装到 EMMC


知识补充 


1. 文件的大小

2. #表示文件正在下载

3. 在这句话之前是uboot在运行, 这句话之后是linux内核在运行

uboot停止运行之后, linux内核开始运行

4. 通过nfs挂载根文件系统文件本身还是存储在linux服务端

nfs可以远程修改这些文件

5. 交叉编译

写程序和编译还是在ubuntu下, 执行程序的时候使用不同的编译器编译出不同cpu架构的汇编代码给不同的处理器执行。

6. 桥接到不同的网卡, 电脑实际上是用什么上的网就桥接到哪一个网卡linux才可以上外网, 如果想开发板想和linux互相通信的话必须桥接到有线网卡, 保证二者在同一个网段开发板就可以和linux主机之间互相通信了。

7. 在开发板上执行的程序需要使用arm的交叉编译器编译生成bin格式的可执行文件在arm架构的cpu上运行。

8. 从windows拖文件到linux下, 将所在目录权限修改为最高。

9. 想要开发板和Ubuntu能够通信, 需要将开发板的IP地址修改成和主机IP地址在同一个网段, 开发板的服务端的之际IP写Ubuntu下的的IP地址。

10. SD卡和emmc属于块设备, 一个块(扇区)512个字节。

11. EMMC嵌入式系统中的一种闪存解决方案。

12. 代表的都是数组首元素的地址

第七部分


交叉编译工具链



1. 交叉编译

一. 编译原理

机器码(二进制)是处理器能直接识别的语言,不同的机器码代表不同的运算指令,处理器能够识别哪些机器码是由处理器的硬件设计所决定的,不同的处理器机器码不同,所以机器码不可移植

 汇编语言是机器码的符号化,即汇编就是用一个符号来代替一条机器码,所以不同的处理器汇编也不一样,即汇编语言也不可移植

 C语言在编译时我们可以使用不同的编译器将C源码编译成不同架构处理器的汇编,所以C语言可以移植

二. GCC编译过程

三. 交叉编译

交叉编译

    程序的编译和运行不在同一台机器上

四. 交叉编译工具链

1.  交叉编译工具链的获取:

1) 官网获取(不推荐,需要自己进行复杂配置与编译)

Index of /gnu/gcc

2) BSP板级开发支持包(推荐), 芯片供应商会提供

samsung、全志…

需要移植, 去掉不需要的部分只留下自己需要的部分。

 交叉编译工具链的内容

1) 交叉编译工具

gcc / readelf / size / nm / strip / objcopy / objdump /addr2line

2) 库

ARM架构的库

2. ELF格式

一. ELF文件格式

ELF

    ELF格式是Linux平台上应用最广泛的二进制工业标准之一

    ELF格式的文件内包含了很多个段不同的段存储了不同的信息;因为ELF格式的文件要通过Linux内核的系统的加载和管理才能运行,所以除了最基本的代码段和数据段之外,其中还存储了很多其它的信息,如符号表、调试信息等

操作系统要为可执行文件分配进程号, 调度信息, 内存空间的分配, 所以就多了很多段, 文件大小也就大了很多。

二. ELF文件相关命令

file

    file + 文件名                查看文件的详细信息

   

 readelf

    readelf -h + 文件名         列出elf文件的头部信息

    readelf -a + 文件名         列出elf文件的所有信息

三. BIN文件格式

BIN

    BIN文件一般是直接运行在CPU之上

的可执行文件,文件内只包含了CPU能够直接识别和运行的指令和数据,不包含其它系统相关的信息

所以bin格式的文件就会小很多

3. 交叉编译工具链常用工具

 size                        列出目标文件每一段的大小以及总体的大小

    size + 文件名                

  nm                        列出目标文件中的符号表(标示符)

    nm + 文件名                

 strip                丢弃目标文件中的符号, 保留数据段和代码段, 不影响使用

    strip + 文件名                

    注:对于嵌入式开发,这个命令很重要

objdump                        从目标文件中显示信息        

    eg:                

            objdump -d + 文件名        将目标文件反汇编(机器码->汇编)

    objcopy                        对目标文件进行复制和转换

    eg:

            objcopy --gap-fill=0xff -O binary a.out a.bin                

将目标文件转换为bin格式

转换的本质是除了数据段和代码段丢去用0xff这个数填充


知识补充


1. 预处理, 将不能编译成汇编的预处理指令处理掉

2. size命令的用法

text段:存放一些语句

data段:存放一些数据, 全局变量, 和一些静态数据, 局部变量程序运行起来之后才分配空间, 所以局部变量不在这些段里

bss段:存放一些未初始化的全局变量, 程序运行起来之后操作系统将bss段里面的内容清0., 本质是操作系统的一段代码干的

3. size命令查看elf格式的文件的验证

4. size和ll所列出的elf格式文件的不同段, 所以导致大小不一样, ll命令是显示是整个elf格式文件的大小, 除了数据段和代码段其它段的内容也都显示出来。

5. 同一个代码使用不同的编译器编译出来的代码的大小完全不一样, 使用交叉编译器里面的size工具查看ARM架构的可执行文件的大小

size命令罗列出来的大小时加载到内存里面执行段的大小, 其它操作系统用到的段不加载到内存。

6. 函数名在C语言里面代表函数在程序里面的入口地址。函数名在elf格式的文件中的符号表里面, 符号表里面还有一些汇编的符号, 用于BL指令跳转的标号。

7. 别人给你的代码你怎么知道该代码有没有瘦过身

使用file命令查看

8. 给别人的代码不给原码, 给.o文件, 但是别人想知道.o文件有那些函数, 就可以nm + 文件名查看文件中的符号。

第八部分


uboot源码配置编译



一. uboot源码结构

1. uboot源码获取

uboot源码下载

    The U-Boot Documentation — Das U-Boot unknown version documentation

 uboot版本命名

    前期:uboot-1.2.3

    现在:uboot-2008.01

 uboot版本选择

    支持对应的硬件平台

    相对成熟的版本(资料多)

2. uboot特点

代码结构清晰

 支持丰富的处理器与开发板,易于移植

 支持丰富的用户命令

 支持丰富的网络协议

 支持丰富的文件系统

 支持丰富的设备驱动

 更新活跃、用户较多、资料丰富

 开放源代码

 较高的稳定性

 不具有通用性(不同的处理器、开发板uboot不可通用)

3. uboot源码结构

平台相关代码

    即与CPU架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改

    arch:与CPU架构相关的源代码

    board:与开发板相关的源代码,包含各种官方评估板对应的源码

平台无关代码

    api:        应用接口

    common:        uboot命令源码

    disk:        对磁盘设备的支持

    drivers:        设备驱动源码

    fs:                对文件系统的支持        

    include:        头文件

    lib:        库

    net:        对网络协议的支持

    post:        上电自检程序

配置文件、帮助文档、示例程序、工具等:

    README:        说明文档

    doc:        帮助文档

    Makefile:        编译管理

    CREDITS:        开发者

    COPYING:        版权

    examples:        示例程序

    tools:        工具

    ... ...

二. uboot配置与编译

1. uboot配置

 1.1. 指定当前使用的硬件平台

make <board_name>_config

注1:<board_name>为当前使用的开发板的名字

注2:执行该命令的前提是uboot源码支持该开发板

注3:该命令必须在uboot源码的顶层目录下执行

2. 指定编译uboot源码使用的编译器

在uboot源码顶层目录下的Makefile中指定(CROSS_COMPILE变量)

2. uboot编译

2.1 编译uboot

make

注1:该命令必须在uboot源码的顶层目录下执行

注2:该命令执行后在uboot源码顶层目录下生成u-boot.bin

 2.2 清除编译过程中生成的中间文件

make clean

make distclean

注1:该命令必须在uboot源码的顶层目录下执行


知识补充


uboot源代码它把很多cpu架构的代码都写了一份, 当你想使用某中架构的cpu的uboot的时候只需要编译对应架构的源代码即可。官方评估板

  • ELF格式的文件是运行在linux操作系统之上, 但是uboot在运行的时候系统还没有运行起来,所以elf格式的文件不能直接放到开发板上去运行,使用objcopy工具将elf格式转换为bin格式的文件放到开发板上去执行。
  • 指定编译器(编译器里面又包含很多工具)
  • uboot支持很多硬件平台的原理

第九部分


uboot移植深化



1. 在Linux系统中,根目录(/)下的usr目录是用于存放用户相关的程序、库文件和其他用户资源的目录。"usr"是“用户”的缩写,这个目录包含了系统中的大部分用户

可访问的文件和目录。

2. /usr目录的主要内容包括:

/usr/bin:存放用户可执行的二进制文件(可执行程序)。这里通常存放着大量的用户应用程序,如常见的命令和工具。

/usr/include:存放C/C++等语言的头文件,用于编译和链接程序时使用。

/usr/lib:存放共享库文件(类似于Windows下的.dll文件),这些库文件被可执行程序调用。

/usr/local:类似于/usr目录,但是它通常用于存放地方相关的软件和文件。

/usr/sbin:存放一些系统管理员使用的系统命令和管理工具。这些命令和工具一般需要管理员权限才能执行。

/usr/share:用于存放共享文件,如系统的文档、帮助文件、图标等。

总之,/usr目录是Linux系统中重要的目录之一,它包含了各种用户相关的文件和资源,为用户提供了丰富的应用程序和工具。

3. 以下定义中,哪一项和其他三项是不同类型的?

A. Int square[12][23]; B. Int *square[23];

C. Int ** square; D. Int (*square)[23];

答案是C. Int ** square;。

在其他三个定义中,square都是一个数组或指向数组的指针。而在C选项中,square是一个指向指针的指针,类型不同。

真扯淡

  • 悬空指针
  • 题目分享
  • .sh文件的执行 第一种./ + 文件名   第二种bash + 文件名
  • 移植uboot, 本质就是将人家的代码和自己的开发板做一个匹配,修改一些平台相关代码, 修改外设硬件不同的配置文件, 修改一些makefile, 注册表等
  • linux根目录下的usr目录是干啥的

 

 

第十部分


linux内核移植



1. linux内核概述

一. 内核与操作系统

内核

    内核是一个操作系统的核心,提供了操作系统最基本的功能,是操作系统工作的基础,决定着整个系统的性能和稳定性

 操作系统

    操作系统是在内核的基础上添加了各种工具集、桌面管理器、库、shell、应用程序等

shell就是保护壳, 保护内核不直接被我们修改, 而是通过shell命令间接的操作内核, 对内核起到一定的保护作用。

操作系统和linux内核是一种包含关系, 操作系统基于内核之上加了很多东西, 比如shell, 图形化界面, 库、、、、

二. 层次结构

linux内核的层次结构

三. linux内核特点

代码结构清晰、模块化设计

 支持丰富的硬件平台

 较高的稳定性

 轻量化及较强的裁剪性

 开放源代码

 更新活跃、用户较多、资料丰富

 支持丰富的网络协议, 因此绝大多数的服务器都是使用linux内核

此外安卓的核心也是linux

 ... ...

2. linux内核源码结构

一. Linux内核源码获取

 Linux内核源码下载

    The Linux Kernel Archives

 Linux内核版本命名

    主版本号.次版本号.修订版本

 Linux内核版本选择

    支持对应的硬件平台

    相对成熟的版本(资料多)

    稳定版本(次版本号为偶数的版本一般都是稳定版)

二. Linux内核源码结构

平台相关代码

    arch:        与CPU架构相关的源代码

平台无关代码

    block:磁盘设备的支持                        crypto:加密相关

    drivers:设备驱动                                firmware:固件

    fs:文件系统                                include:头文件

    init:内核初始化                                ipc:进程间通信

    kernel:内核核心调度机制等                lib:库

    mm:内存管理                                net:网络协议

    scripts:工具、脚本等                        security:安全

    usr:打包与压缩                                virt:虚拟

帮助文档、示例程序、工具等

    COPYING:                版权

    CREDITS:                内核贡献者

    README:                说明文档

    Documentation:        帮助文档

    Makefile:                编译管理

    samples:                示例

    tools:                工具

3. linux内核源码的配置与编译

一. Linux内核源码配置

指定处理器架构及编译工具

    在Linux内核源码顶层目录下的Makefile中指定(ARCH、CROSS_COMPILE)

 导入当前处理器的默认配置

    make <soc_name>_defconfig

    注1:soc_name为当前使用的处理器的名字

    注2:内核源码的arch/arm/configs下对各个厂商的soc都有一个默认配置文件

    执行该命令后就会将对应的配置文件中的信息导入到源码顶层目录下的.config

    文件中CONFIG_xxx=y表示内核选中了该功能,内核编译时就会将该功能对应的

    代码编译,内核的体积也会增大。#CONFIG_xxx is not set表示内核没有选中

    该功能,内核编译时该功能对应的代码不会被编译,内核的体积也会减小。

defconfig   默认配置

修改配置

    默认配置只能保证内核拥有最基本的功能,我们需要根据自己的实际需求对内核做进一步的配置

    方法1:

直接修改.config文件(不推荐)

内容太多, 不知道每一项具体是什么含义,很多功能有很强的依赖关系, 对关系不清晰的话, 也配置不成功想要的功能。

    方法2:

make menuconfig

自动的检查各个依赖关系

二. make menuconfig

修改配置

    [ ] 有两种状态

            输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核

输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核

    < > 有三种状态

            输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核

  输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核

         输入M,显示“M”,内核中该功能被选为模块(被编译为独立的模块)

    注:使用make menuconfig配置的本质还是修改.config文件

三. Linux内核源码编译

内核编译(以下命令均在内核源码的顶层目录下执行)

    make uImage        

编译内核(编译选为“*”的选项到内核)

    make modules           

编译内核模块(编译选为“M”的选项为独立模块)

    make dtbs              

编译设备树(将设备树源文件dts编译为二进制文件dtb)

    make clean    

删除编译过程中产生的中间文件


知识补充


1. 含有箭头的是子菜单, 也就是本事自己是一个目录

2. 方框代表内核的默认功能, <>中有*代表我们后来自己加的

3. 按下空格, 在各种状态之间来回切换

4. uboot目录下的这个mkuImage是编译之后才有的

5. Ubuntu之下的命令都在这个目录下面

使mkuimage在Ubuntu下全局可用

6. 第二次编译为什么时间很短

因为make会自动检查各个文件的时间戳, 没有修改的文件就不会重新编译了, 只编译错的文件和修改过的文件。

7. .ko内核模块的意思

.ko文件是Linux内核模块的文件格式,它包含了编译好的可加载内核模块的二进制代码。内核模块是一种能够在运行中动态加载到Linux内核中并添加功能的机制。模块可以在运行时通过插入或移除来扩展或修改内核的功能。

.ko文件是一种经过编译的二进制形式,其中包含模块的代码和数据。这些文件通常位于Linux操作系统的模块目录(通常是/lib/modules/<kernel_version>/)下的不同子目录中,与正在运行的内核版本相对应。

加载模块时,内核会查找.ko文件并将其加载到内存中。加载后,模块的代码就可以被调用和执行,从而为内核添加新的功能或修改现有功能。

.ko文件对于开发者来说是非常重要的,因为它们允许在不重新编译整个内核的情况下添加、移除和更新内核功能模块。这提供了更大的灵活性和可维护性,使得内核定制和扩展变得更加容易。

8. linux加载的时候卡住了, 因为linux内核在配置的时候默认使没有选择安装nfs的客户端的, 所以无法从ubuntu的服务端共享根文件系统。

想用nfs, 需要配置以上层级关系的内核

第十一部分


linux驱动移植及内核深化



1. 设备树

一. 设备树

设备树

    设备树是一种描述硬件信息的数据结构,Linux内核运行时可以通过设备树将硬件信息直接传递给Linux内核,而不再需要在Linux内核中包含大量的冗余编码

二. 设备树语法概述

设备树文件

    dts  设备树源文件

    dtsi 类似于头文件,包含一些公共的信息,可被其它设备树文件引用

    dtb  编译后的设备树文件

 设备树语法

    设备树的语法为树状结构,由一系列的节点和属性组成,根节点下包含子节点

    子节点下还可以包含子节点,节点内部包含了对应设备的属性

三. linux内核驱动移植

Linux内核驱动移植

1.在make menuconfig界面中选中要安装的驱动

2.在设备树中添加/修改相应的设备信息

3.重新编译内核/设备树


知识补充


1. 为什么可以通过网卡下载uimage, 挂载根文件系统的时候却不行呢

因为在linux内核运行之前使uboot在运行, uboot支持网卡的驱动, 所以在uboot运行的时候可以使用tftp协议在Ubuntutftp目录下下载文件。

2. 作业

1.简述内核和操作系统的关系?

2.简述为什么嵌入式开发中一般都使用Linux内核?

3.简述.config文件的作用以及.config文件和make menuconfig的关系?

4.简述make menuconfig界面中[ ]选项和选项<>的区别?

1. 内核时操作系统最核心的部分,决定着操作系统的性能, 稳定性等, 内核提供了操作系统最基本的功能, 操作系统是基于linux内核添加了一些额外的功能2, 比如shell, 图形化界面等。

2. linux内核轻量化, 可裁剪性强, 可根据实际的项目需求裁剪出对应的功能模块然后编译,可定制性强, 开源, 用户多,资料多, linux内核稳定, 支持丰富的网络协议, 总之linux更适合嵌入式这种硬件配置不高的应用场景。

3. .config文件是linux内核的配置文件, 该文件中包含了linux内核的一些功能代码, , 用户可以选择或者取消对应的功能代码, 该文件决定了对应的功能代码会不会被编译, make menuconfig相当于是.config文件的图形化版, 不需要我们知道各个配置之间的层级关系和.config文件中各个语句什么意思, 本质上make menuconfig也是修改了.config文件。

4. []这种有两种选择, 可以选上也可以不选, <>这种多了一种选项, 按下M, 表示将对应的功能代码编译成一个单独的模块。

3. 安装ncurses库(图形化界面库)

4. 该命令查看文件的大小

5. 作业2

1.简述设备树的作用以及使用设备树的优势是什么?

2.简述在Linux内核上移植一个驱动程序(内核源码支持)需要做哪些事?

1. 设备树的作用是在Linux内核运行的时候给内核传递硬件信息。设备树的优势是不需要每一种硬件的驱动代码都写一份, 硬件平台发生变化的时候, 直接修改设备树中的硬件信息, 减少不必要的代码累赘。

2. 首先修改.config文件中的配置, 通过make menuconfig去修改, 选择需要安装的驱动, 接着对比自己的开发版找一款linux内核支持的开发板对比一下硬件信息, 假设硬件上有不同的地方通过修改设备树文件。最后重新编译设备树和linux内核。

6. 高内聚低耦合

高内聚指的是模块内部的各个组件相互关联紧密,功能高度集中,每个组件都有明确的职责。高内聚能够提高模块的可维护性和可测试性,使代码更加清晰和易于理解。

低耦合指的是模块与模块之间的依赖关系尽量减少,模块之间相互独立。低耦合可以提高系统的灵活性和扩展性,减少系统的复杂性,方便单元测试和模块重用。

高内聚低耦合的设计原则是为了实现模块化、可复用、可维护的软件系统。通过将功能划分为独立的模块,每个模块只关注自己的职责,并通过接口进行通信,便于单独测试和修改,同时减少了模块之间的依赖,提高了系统的灵活性和可扩展性。这样的设计能够使软件系统更加健壮、可靠和可维护。

第十二部分


linux内核调试及rootfs移植



1. 根文件系统

一. 根文件系统

    根文件系统是内核启动后挂载的第一个文件系统系统引导程序会在根文件系统挂载后从中把一些基本的初始化脚本和服务等加载到内存中去运行

二. 根文件系统内容

 bin                shell命令(elf格式)(通过busybox编译生成)

 dev                设备文件(内核启动后会将设备信息写入该目录)

 etc                内核配置文件

 lib                共享库(elf格式)(从交叉编译工具链中获取), 运行在linux之上

 linuxrc        内核运行的第一个应用程序(通过busybox编译生成)

 mnt                挂载目录(非必要)

 proc                进程相关文件(内核启动后会将进程信息写入该目录)

 root                超级用户家目录(非必要)

 sbin           系统管理shell命令(elf格式)(通过busybox编译生成)

 sys                驱动相关文件(内核启动后会将驱动信息写入该目录)

 usr                shell命令(elf格式)(通过busybox编译生成)

三. BusyBox

    BusyBox将很多常用的工具集成到一个很小的可执行文件中,为普通用户提供大多数常用的命令,BusyBox实现的命令都是精简版的,很多扩展都不支持。BusyBox被称为Linux工具里的瑞士军刀

 BusyBox的获取

    Index of /downloads


知识补充


1. 根文件系统本质也是一些文件, linux内核运行起来之后需要用到这些文件。

2. ubuntu下存放的shell命令, 执行命令实际上是执行了对应的这些文件。

3. 二进制文件就会涉及到平台属性, X86, ARM, 考虑架构问题

4. linux下的蓝色文件称为软连接文件, 类似快捷方式

5. 静态库和动态库的优缺点?

  1. 开发板上只是安装了内核, 没有库,库和shell一样在内核在外, 在开发板执行一些应用程序的时候需要用到一些库函数。
  2. busybox可以理解成linux下shell命令的源代码, 在通过arm的编译器编译就可以得到能够在开发板上运行的shell命令
  3. 静态库的优点, 不管有没有安装动态库, 都可以执行。
  4. strip工具给可执行文件瘦身, 去掉elf格式里面的一些无关紧要得到符号表

busyboc是busybox_unstripped瘦身得到的

6. linxu下的可执行文件必须都是elf格式的

7. 开发板上只执行程序, 不编译程序, 所以不需要静态库, 只需要动态库。

8. 瘦身之前看一下需要瘦身文件的大小,

瘦身去掉的是elf格式文件中的符号表信息, 不影响使用。

9. -rf, 表示操作文件和目录

10. 软链接和硬链接

软链接(symbolic link,也称为符号链接)和硬链接(hard link)都是文件系统中用于创建链接的概念。

软链接是一个特殊的文件,它包含了指向目标文件或目录的路径。当通过软链接访问文件时,实际上是通过软链接的路径找到目标文件并进行操作。软链接可以跨越文件系统,即可以链接到不同的磁盘分区或文件系统。

硬链接是指在文件系统中创建的指向同一目标文件的不同文件名。具有相同的inode(索引节点)和相同的数据块,它们实际上是同一个文件的不同访问方式。相比于软链接,硬链接只能在同一文件系统内创建。对于硬链接,当原始文件被删除时,硬链接仍然可以访问该文件的内容,因为它们都指向同一个数据。

它们之间的一些主要区别包括:

软链接可以链接到文件或目录,而硬链接只能链接到文件。

软链接可以跨越文件系统,而硬链接只能在同一文件系统内创建。

软链接有自己的权限和时间戳,而硬链接与原始文件共享相同的权限和时间戳。

总的来说,软链接提供了更大的灵活性和可移植性,而硬链接提供了更高效的访问方式和更紧密的关联性。使用哪种链接方式取决于特定的需求和使用场景。



内容到这里就结束了, 后期会出具体的实验手册。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@daiwei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值