一、树莓派等芯片带操作系统的启动过程
1.x86、Intel、windows等设备的启动过程
启动过程:电源- > BIOS -> windows内核 -> C,D盘的启动 -> 程序的启动(例如QQ的启动)
2.嵌入式产品(树莓派、mini2440、mini6410、nanopi、海思、RK(瑞芯微) )的启动过程
启动过程:电源 -> BootLoader (引导操作系统启动) -> linux内核 -> 文件系统(根据功能性来组织文件夹,带访问权限)-> 实实在在的嵌入式产品的启动(例如KTV点歌机)
3.安卓操作系统的启动过程
启动过程:电源 -> fastBoot/Bootloader/ -> linux内核 -> 文件系统 -> 虚拟机 -> HOME应用程序 -> 点击某图标打开某app
4.C51、STM32(裸机,不带操作系统)的开发流程
不带操作系统的裸机开发是C语言直接操控底层寄存器实现相关业务。
5.文件系统补充
上图都是文件,它是根据功能来放的。
dev放的是设备相关,
lib放的是各种动态库和静态库,
proc放的是内核的数据信息,
home是用户登录的工作界面,
opt是跟内核底层有关的,
sbin通常是可执行文件或指令,
bin也是指令和可执行文件,
boot是启动要加载的配置等等。
二、树莓派linux源码分析
linux内核认知:
linux内核大约由1.3w个C文件组成,1100w行代码左右
linux是开源的,免费的,linux开源社区由其工作者和爱好者共同进行维护
linux是一个开源的,支持多架构多平台代码
可移植性非常高
但是linux内核编译出来一般就是几M,一般是4M左右
因为是支持多平台多架构,所以在编译之前是需要进行配置的,配置成适合的目标平台来用
三、树莓派内核源码下载
打开树莓派运行指令 uname -a 查看系统版本、架构等信息,或者直接运行 uname -r 查看树莓派版本信息,然后再去https://github.com/raspberrypi/下载 linux 源码,还要筛选找到对应版本。
然后复制到工作目录下解压。
四、树莓派内核源码配置
为什么要进行源码配置呢?
这是因为驱动代码的编写需要驱动代码的编译,而驱动代码的编译需要一个提前编译好的内核,所以我们需要内核源码的配置。
一般我们购买了芯片,厂家都会配linux内核源码,比如说我们买了树莓派,厂家就会向我们提供树莓派linux内核源码。
而linux源码中有很多工程,比如:树莓派1的工程是bcmrpi_defconfig,树莓派2、3的工程是bcm2709_defconfig。
这一环节我们的主要目的就是获得 .config 文件,获得方式主要有两种:
方式一:使用源码中的工程文件
运行指令,来查看各个架构的工程文件。
find . -name *_defconfig
然后在终端运行以下指令。
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
代码解释
ARCH=arm(指定当前要编译的是arm架构)
CROSS_COMPILE=arm-linux-gnueabihf- (指定编译器是树莓派交叉编译工具链)
KERNEL=kernel7 (指明kernel类型,树莓派1设置为kernel,树莓派2,3设置为kernel7)
make bcm2709_defconfig(make为配置命令)
这个命令的作用就是获取bcm2709_defconfig的配置到config中来,并生成 .config 文件。
方式二:一项一项来配置
通过make menuconfig 一项项的来配置,通常都是基于厂家的config来进行配置。通过这样的"裁剪",来减小内核的体积。
在此之前,要先安装一些用得到的库。
sudo apt-get install bc
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install zlib1g:i386
sudo apt-get install libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5
然后运行以下指令,对内核菜单进行配置。
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make menuconfig
之后就会出现以下画面。
选项解释。
General setup —>(通用选项)
[ * ] Enable loadable module support —> 内核模块选项
[ * ]Enable the block layer —> 块设备逻辑层选项(大文件支持、分区、I/O调度)
System Type —>(平台选项)
Bus support —> 总线选项
Kernel Features —>内核特征
Boot options —> 引导选项
CPU Power Management —> CPU电源管理选项
Floating point emulation —> 浮点运算
Userspace binary formats —> 用户程序格式
Power management options —> 电源管理选项
[*] Networking support —> 网络协议选项
Device Drivers —> 设备驱动
Firmware Drivers ---- 驱动固件选项
File systems —> 文件系统选项
Kernel hacking —> 内核调试选项
Security options —> 安全模块选项
选择要配置的文件,使用空格可以切换[ ]里面的模式。
[*]:编译进内核(*代表Y,编译进内核,zImage包含了驱动)
[M]:编译成模块(以模块的方式生成驱动文件xxx.ko,系统启动后,
通过命令inmosd xxx.ko来加载驱动,也可以减小一些内核大小)
[ ]:表示不需要的部分
空格可切换修改。
修改完毕后,保存退出
五、树莓派 linux 内核源码编译
1.编译指令
运行以下指令进行编译。
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
make -j4:指定用多少电脑资源进行编译(j4是四核的意思,这个要每个人根据
自己的电脑的配置以及虚拟机的设置的核数来决定)
zImage:生成内核镜像
modules:要生成驱动模块
dtbs:生成配置文件
编译的时间会比较久(看电脑配置,我花了45分钟),编译过程中如果跑了几分钟没有报错,那基本就是正确的。
2.将zImage文件打包成树莓派可用的xxx.img文件
编译成功后会生成vmlinux文件,如下图。
vmlinux其实是未进行压缩的linux内核源码,而我们的目标是压缩过的,位于 /arch/arm/boot 目录下的 zImage 文件。
运行以下指令,对zImage文件进行打包。
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
可能会出现以下报错。这是因为这个版本的linux源码包将mkknlimg工具给淘汰了,可以从一些旧版本的源码包中复制过来,也可以使用,同样位于 /scripts 目录。
3.将树莓派SD卡的U盘映射到虚拟机
把树莓派SD卡插到读卡器,再与电脑连接,然后映射到虚拟机,过程中虚拟机可能会识别不到,问题不大,可自行百度解决。
虚拟机识别后,终端输入dmesg查看内核信息。
出现 sdb1 和 sdb2 说明成功映射到虚拟机上了。
4.挂载U盘
在用户目录下创建两个文件夹data1和data2,然后运行以下两个指令。
sudo mount /dev/sdb1 data1
//挂载U盘的sdb1文件分区到当前路径下的data1文件夹,
//该分区为fat分区,是boot相关的内容,kernel的img.
sudo mount /dev/sdb2 data2
//挂载U盘的sdb2文件分区到当前路径下的data2文件夹,
//该分区为ext4分区,也就是系统的根目录分区.
5.安装modules
运行指令安装,因为内核配置时,有一部分是编译成模块的形式配置进来的,安装后hdmi接口、usb、wifi、io口等等的设备才能使用,所以需要这么一步。
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=[ext4] modules_install
操作ext4分区需要root权限,sudo
[ext4]为第二分区(sdb2)虚拟机上挂载的地址(data2的位置),需要根据自己的地址更改
比如我的
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=/home/eva/data2 modules_install
这个指令一定要在我们解压的源码文件夹(/linux-rpi-5.4.y)里运行。
6.更新内核文件
运行以下指令,将生成的kernel_new.img文件拷贝到boot分区(也就是data1文件夹)。
cp ./kernel_new.img ~/data1
还要修改boot分区的config.text文件。
vi ~/data1/config.text
//在最后一行加入kernel=kernel_new.img
7. 拷贝配置相关文件
cp arch/arm/boot/dts/.*dtb* [fat]/
cp arch/arm/boot/dts/overlays/.*dtb* [fat]/overlays/
cp arch/arm/boot/dts/overlays/README [fat]/overlays/
[fat]为第一分区(sdb1)虚拟机上挂载的地址(data1的位置),需要根据自己的地址更改。
这样就完成了,然后断开与虚拟机的连接,把cmdline.txt更改成以下内容,用串口查看是否刷机成功。
dwc_otg.lpm_enable=0 console=tty1 console=serial0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
8.最后启动树莓派
用串口或者远程登录树莓派后,用指令uname -a查看内核版本,发现内核信息已经是发生改变了。
替换内核之前。
替换内核之后。
树莓派的版本已经发生了变化,说明内核替换成功了。
六、其他
1.查看文件拷贝是否损坏
在文件拷贝的过程中有一个md5的值,如果拷贝过程中文件没有损坏的话,md5的值是不变的,如果拷贝失败或者是文件损坏的话,这个值就会改变。
2.虚拟机挂载共享文件夹
sudo vmhgfs-fuse .host:/ /mnt/hgfs -o nonempty -o allow_other
3.根目录、家目录
cd / //返回根目录
cd ~ //返回用户目录