七、Linux——内核扫盲
7.1 操作系统的启动过程
Linux内核启动过程概述
一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader),Linux 内核,文件系统,应用程序。其中 ==Bootloader是系统启动或复位以后执行的第一段代码,它主要用来初始化处理器及外设,然后调用 Linux 内核。Linux 内核在完成系统的初始化之后需要挂载某个文件系统做为根文件系统(Root Filesystem)。==根文件系统是 Linux 系统的核心组成部分,它可以做为Linux 系统中文件和数据的存储区域,通常它还包括系统配置文件和运行应用软件所需要的库。应用程序可以说是嵌入式系统的“灵魂”,它所实现的功能通常就是设计该嵌入式系统所要达到的目标。如果没有应用程序的支持,任何硬件上设计精良的嵌入式系统都没有实用意义。
Linux常见目录说明
7.2 Linux源码配置(树莓派3B+)
**树莓派Linux源码下载:**https://github.com/raspberrypi/linux
uname -r//查看当前树莓派的版本号
以后可能涉及驱动代码的编写,驱动代码的编译需要一个提前编译好的内核,编译内核就需要对内核进行配置。
配置的最终目标是生成.config
文件,该文件指导Makefile去把有用的东西组织成内核。
配置的方式有以下几种方式:
-
第一种方式:厂家提供的Linux源码中会有配置文件
- 将厂家的.config文件拷贝成自己的.config文件。
find . -name *_deconfig//查找以deconfig结尾的文件
- 例如树莓派就是使用的bcm2709_deconfig,然后将它拷贝到自己的文件中
-
第二种方式:使用**make menuconfig(menuconfig、defconfig都是用来配置内核的)**一项项配置,通常是基于厂家文件修改
-
第三种方式:自己从头到尾改配置
7.3 Linux内核编译(树莓派3B+)
-
安装好交叉编译工具链;
安装以下库:
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
-
内核的配置
使用源码中自带的config
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig 指定架构 指定编译器 树莓派 主要核心指令
下面这条命令是用来更改驱动的
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make menuconfig
出现以下画面:
一般就选择exit退出就可以了,证明.config文件没问题了,然后检查.config文件是否存在问题,一般能顺利进入界面然后退出就可以了。注:记得把Enable loadable module support选上,以后编译内核需要本地模块支持。
-
内核的编译
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
指令说明:
- j4 指定用多少电脑资源进行编译。
- zImage 生成内核镜像。
- modules 要生成驱动模块。
- dtbs 生成配置文件。
注意:只要跑起来一分钟内没有出错,就说明前面配置没有出错。
等待大约20分钟左右,就编译完成了。
编译成功后,看到源码树目录多了 vmlinux,失败则无此文件
-
镜像拷贝到树莓派
打包 zimage 成树莓派可用的 xxx.img
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
创建两个新文件夹,分别用作树莓派的fat分区和ext4分区,然后把内存卡挂在到文件夹内
sudo mount /dev/sdb1 data1 //一个fat分区,是boot相关的内容,kernel的img sudo mount /dev/sdb2 data2 //一个是ext4分区,也就是系统的根目录分区
安装modules:设备驱动文件(wifi,hdmi,usb,io…) 此处是ext4分区的绝对路径
cd /SYSTEM/linux-rpi-4.14.y sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=/home/cjh/data2 modules_install
将生成的zimage文件拷贝到fat分区的文件夹
cp kernel_new.img /home/cjh/data1/kernel7.img
拷贝配置文件到fat分区
cp arch/arm/boot/dts/.*dtb* /home/cjh/data1 cp arch/arm/boot/dts/overlays/.*dtb* /home/cjh/data1/overlays/ cp arch/arm/boot/dts/overlays/README /home/cjh/data1/overlays/ //没啥用可以不拷贝
最后,解除掉挂载的U盘
sudo umount /dev/sdb1 sudo umount /dev/sdb2
树莓派重新上电,查看内核版本
7.4 文件系统
1、什么是文件系统?
常规认知就是根目录下那些文件,也可以这样笼统的讲,但具体来讲其实并不是那样。
**官方定义:文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。**操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。也指用于存储文件的磁盘或分区,或文件系统种类。 因此,可以说"我有2个文件系统"意思是他有2个分区,一个存文件,或他用“扩展文件系统”,意思是文件系统的种类。
比如在linux源码下文件下的文件系统代码存放在fs
文件夹(由此可知文件系统是一个程序):
2、文件系统的种类
文件系统(文件管理系统)的种类有哪些?
既然文件系统是管理磁盘文件的方法,那么肯定不止一种,比如说:FAT、vfat 、NTFS、EXT(ext2、ext3、ext4)、HFS
Linux常用的是EXT系列的文件系统,windows使用的文件系统是NTFS
树莓派查看文件系统的命令是:df-T,如下如所示,
type就是文件系统类型。
tmpfs:是临时文件系统也叫作**(内存文件系统)是基于内存的。
vfat和ext4是基于磁盘**的,也就是我们的SD卡,就是之前挂载到虚拟机的两个分区,fat分区存放boot(BootLoader)相关文件,ext4分区存放的是根目录文件。
3、什么是分区?
什么是分区?
**对于windows来说,**像是驱动器盘符,C盘是装系统的分区,D盘存放其他文件,但是C盘也可以放其他文件,比较随意(面向普通用户),但是C盘、D盘的内存都是联连续的一大块。
对于Linux来说,叫做文件系统结构,按照 功能来分区,每个分区严格存放文件(面对开发者),内存不一定连续,也就是说我们在linux同一个路径下看到的文件不一定是来自同一分区。
嵌入式系统的分区
嵌入式系统可以分为4个区,分别是**bootloader(启动代码)、para(启动代码向内核传递参数的位置)、kernel(内核分区)、根分区(文件系统结构)**等,与Windows、Linux分区不同。
①在嵌入式系统中,没有swap分区,只有实际的物理空间。
②bootloader、para、kernel这三个分区的功能类似于Linux系统中的/boot分区,这三个分区分别存放嵌入式系统的启动代码和内核。
注:Linux系统中/boot分区内存放着linux启动代码和内核源码。
③根分区(/)可以构造,其功能类似于Linux系统中的根分区在这个分区中可以创建许多目录,比如/root、/home、/usr等,但不能创建/boot目录。
④分区bootloader、para、kernel只能由地址来区分,而根分区只能由目录来区分。
⑤嵌入式系统的驱动程序、上层软件都放在根分区.在嵌入式系统启动后,系统无法查看到bootloader、para、kernel这三个分区
4、什么是文件系统目录结构
根目录就是文件系统目录结构。
在Linux系统中,目录被组织成一个:单根倒置树结构,文件系统目录结构从根目录开始,用/
来表示。
在 Linux 系统中,有几个目录是比较重要的,平时需要注意不要误删除或者随意更改内部文件。
/etc :这个是系统中的配置文件,如果你更改了该目录下的某个文件可能会导致系统不能启动。
/bin, /sbin, /usr/bin, /usr/sbin: 这是系统预设的执行文件的放置目录,比如 ls 就是在/bin/ls 目录下的。
值得提出的是, **/bin,/usr/bin ==是给系统用户使用的指令(除root外的通用户)
而/sbin, /usr/sbin==** 则是给root使用的指令。
/var: 这是一个非常重要的目录,系统上跑了很多程序,那么每个程序都会有相应的日志产生,而这些日志就被记录到这个目录下,具体在/var/log 目录下,另外mail的预设放置也是在这里。
/etc
etc下面是配置文件,若想要开机启动某个程序可以在/etc/init
这个文件夹下去配置某些文件,使之开机自启。比如打开bootmisc.sh.conf:vi /etc/init/bootmisc.sh.conf
然后将指令添加到脚本的最后即可。
但是一般不那么做,一般是在init
文件夹下去模仿这个文件夹下面的文件自己去新建一个文件,然后再文件里面写入相关的指令,只需文件以.conf
结尾即可。
除此之外还可以修改etc
下面的rc .local
也是添加相关的指令即可。
sudo nano /etc/rc.local
在exit0之前添加想要执行的文件,su表示获取权限,-c表示执行结束后恢复权限,&表示后台启动
su pi -c "bash /home/pi/WorkSpace/FaceDetection/detection_auto.sh &"
7.5 虚拟文件系统
什么是虚拟文件系统
VFS(虚拟文件系统)就是对各种文件系统的一个抽象,它为各种文件系统提供了一个通用接口,由指令df -T可以看出不同的文件来源于不同分区,然而每个分区都有自己的文件系统,所以访问文件的方式因为文件系统的不同而不同,因为不同的文件系统文件、数据存储的方式不一样。这样访问不同分区的文件就比较麻烦,而linux通过叫做VFS的中间层对这些文件系统提供了完美的支持。在大部分情况下,用户通过libc和kernel的 VFS 交互,不需要关心底层文件系统的具体实现。这样就使我们使用open、read、write等函数对文件展开操作,不需要关心它底层的文件系统。
虚拟文件系统的目的: 将接口暴露给用户,屏蔽底层文件系统的差异性,它是对所有不同文件系统的抽象。
用户空间内调用write函数的具体过程如下
7.6 内核结构
Linux内核结构图
- Unix和Linux系统内核都采用的都是如下图所示的结构,
其中可以看到三个层次:硬件级、内核级和用户级。
用户程序通过陷入完成由用户态到内核态的转换。
为了方便调用内核,Linux将内核的功能接口制作成系统调用(system call)。用户不需要了解内核的复杂结构,就可以使用内核。==系统调用是操作系统的最小功能单位。==一个操作系统,以及基于操作系统的应用,都不可能实现超越系统调用的功能。 系统调用提供的功能非常基础,所以使用起来很麻烦。一个简单的给变量分配内存空间的操作,就需要动用多个系统调用。Linux定义一些库函数(library routine)来将系统调用组合成某些常用的功能。上面的分配内存的操作,可以定义成一个库函数,比如常用的malloc。