Linux_kernel原理08

2024-09-06 11:52
文章标签 linux 原理 08 kernel

本文主要是介绍Linux_kernel原理08,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、温故知新

        系统移植

        1、uboot

                uboot主要做两件事:1、负责初始化硬件;2、负责引导操作系统的启动

        2、Linux内核

                Linux内核的五大功能

                【1】进程间通信

                【2】进程管理

                【3】网络子系统

                【4】虚拟文件子系统

                【5】内存管理

        3、根文件系统

                当Linux内核启动之后需要执行1号进程(init进程)

                1号进程对应的程序:cd ls cat touch cp。。。

                使用busybox工具制作自己的根文件系统

        4、开发板的烧写实验

                1)对emmc分区(按扇区进行访问)

                        EMMC的大小(8G)

                        根据uboot的大小来分区

                        根据uImage的大小来分区

                        根据rootfs的大小来分区

                mmc erase 0 0x100000

                tdisk 2 3 0x100000:0x4000000 0x4100000:0x2f200000 0x33300000:0

0M1M65M819M剩余空间
字节00x1000000x41000000x33300000剩余空间
ubootuboot-uImageuImage-rootfsrootfs-appapp
未分区未分区-mmcblk0p1mmcblk0p1-mmcblk0p2mmcblk0p2-mmcblk0p3mmcblk0p3
                2)烧写uboot

                cp ubootpak.bin /tftp_share/

                tftp 0x48000000 ubootpak.bin

                update_mmc 2 2ndboot 0x48000000 0x200 0x53ba8

注释:

        0x200 = 512byte = 1个扇区

                3)烧写uImage

                cp uImage /tftp_share/

                tftp 0x48000000 uImage

                mmc write 0x48000000 0x800 0x3000

                setenv bootcmd mmc read 48000000 800 3000 \; bootm 48000000

                4)烧写rootfs

                cp rootfs /tftp_share/

                tftp 0x48000000 rootfs

                mmc write 48000000 0x20800 0x32000

                setenv bootargs root=/dev/mmcblk0p2 rootfstype=ext4 console=ttySAC0,115200 maxcpus=1 lcd=wy070ml tp=gslx680

        5、通过nfs方式挂载根文件系统

        [1]上位机安装nfs服务

                sudo apt-get install nfs-kernel-server

        [2]创建nfs共享目录

                sudo mkdir /nfs_share

        [3]修改nfs共享目录的权限

                sudo chmod 777 /nfs_share

        [4]把根文件系统解压缩到nfs共享目录

                tar -xvf /nfs_share

        [5]修改配置文件

                sudo vim /etc/exports

                /nfs_share/rootfs *(rw,sync,no_root_squash)

        [6]修改服务文件

                sudo vim /etc/default/nfs-kernel-server

        [7]重启nfs服务

                sudo service nfs-kernel-server restart

                或

                sudo /etc/init.d/nfs-kernel-server restart

        [8]关闭防火墙

                sudo service ufw stop

                或

                sudo /etc/init.d/ufw stop

        [9]修改下位机的环境变量

                setenv bootargs root=/dev/nfs nfsroot=192.168.1.8:/nfs_share/rootfs  ip=192.168.1.6:192.168.1.8:192.168.1.1:255.255.255.0 init=/linuxrc

二、uboot的基本概念 

        1、通用的ubootloader

                类似于PC机上的BIOS

                【1】负责初始化硬件

                【2】负责引导操作系统的启动

                bootloader不属于操作系统内核的一部分,这部分的代码不具有可移植性,如我我们将来换了一块开发板,现在的uboot不一定可以直接使用。

        通用的含义:

                【1】:支持多种CPU架构:arm、mips、ppc、x86。。。

                【2】:支持多种类型的操作系统:Linux、windows、vxworks、RTOS。。。

        我们现在使用的就是支持ARM架构下Linux操作系统的bootloader

        2、ubootpak.bin从何而来?

                程序编译uboot源码得到ubootpak.bin

                1)uboot

                        uboot是非常著名的开源软件,但原始包里有很多我们今后开发不一定用到的资源

                        官网:DENX Software Engineering – the Embedded Linux Experts

                2)从上游厂商获取(从demo板中获取)

                        uboot.tar.gz

                        demo版本是芯片厂商提供的参考版本,可能方便使用,也可能不方便使用,所以我们需要做uboot开发的工程师进行修改或调试,让这个uboot可以在我们的开发板上完美的运行。

                3)获取并编译uboot源码

               /*将源码拷贝至实验目录*/

                cp /mnt/hgfs/easthome_porting/uboot.tar.gz ~/S5p6818/

                /*解压源码*/

                tar -xvf uboot.tar.gz

                cd uboot

                /*获取最干净的uboot源码*/

                make distclean

                /*获取uboot编译的配置文件*/

                make x6818_config

                /*对源码进行编译*/

                make

                4)修改uboot命令行的提示符

                vim  uboot/include/configs/x6818.h

                #define CONFIG_SYS_PROMPT        "zjd#"

                5)修改默认ip配置

                vim  uboot/include/configs/x6818.h

                #define CONFIG_NETMASK        255.255.255.0

                #define CONFIG_IPADDR            192.168.1.6

                #define CONFIG_SERVERIP       192.168.1.8

                #define CONFIG_GATEWAYIP     192.168.1.1

        3、uboot源码的目录结构

                uboot的目录大致分为3类

                【1】与处理器体系结构或者开发板硬件直接相关

                【2】一些通用的函数或驱动程序

                【3】是uboot的应用程序\工具\文档

1)api

(应用程序编程接口)

独立于体系架构之外的功能函数接口,一般是uboot本身使用的,uboot在移植的时候基本不用动。

2)arch(Architecture)

体系架构

包含了特定的处理器架构的代码,如:ARM、PPC、MIPS、X86等

        arch/arm 在arch目录下现在只剩下arm了,已经被上游厂商裁剪过了。

        arch/arm/cpu:存放了和cpu紧密相关的内容

        arch/arm/cpu/slsiap:存放了三星公司的工程内容

        arch/arm/cpu/slsiap/s5p6818:有关s5p6818芯片的内容

3)board开发板相关的配置文件存放与开发板相关的代码,如:初始化脚本、设备树等
4)common通用的

包含大多数uboot的代码使用的通用函数

       主要是两类:1、实现uboot的命令;2、实现环境变量

5)disk硬盘提供硬盘驱动的位置,用于文件系统的读写操作
6)doc文档包含uboot的文档
7)drivers驱动

包含各种设备的驱动程序,如:网络驱动程序\显示驱动程序。。。

存放的是从Linux内核源码中拷贝过来的Linux设备驱动

主要是uboot在启动时所支持的硬件的驱动

其实uboot在一定程度上移植了Linux驱动

8)dts设备树提供设备树工具
9)examples示例代码提供了一些示例代码,如:使用uboot的命令,使用uboot的API
a)fs文件系统里面存放了支持的文件系统类型
b)include头文件里面存放了各种常用函数的头文件
c)lib库里面存放了各种常用函数的实现
d)net有关网络包含网络相关的代码,如:nfs、tftp
e)post上电自检属于硬件自检的操作
f)scripts包含用于编译uboot的脚本
g)test测试提供测试代码,用于验证uboot的功能
h)tools工具包含用于处理uboot镜像的工具

我们可以将uboot认为是一个巨大无比的裸板程序,几乎在uboot的每一级目录下都有一个makefile文件,决定了当前目录下,哪些文件参与编译,哪些不参与编译,那些需要重新编译。

uboot/common/Makefile

        4、找到uboot的入口点文件

                C程序的启动与终止

                【1】内核通过exec——族函数调用C启动例程

                【2】C启动例程再调用main函数,进程开始运行

                【3】main函数return就返回到了C启动例程

                【4】C启动例程需要调用exit(3)函数

                        注意:C启动例程不能直接返回给内核

                【5】exit(3)再调用_exit(2)或者_Exit(2)函数返回给内核进程才会结束

                        注意:内核预留的终止进程的函数结构是_exit(2)或_Exit(2)

                【6】exit(3)函数在调用_exit(2)或_Exit(2)函数之前还会调用其他的函数接口,比如标准IO的清理程序(清缓冲区)

                1) 查找源码的入口点文件(法一)

                gcc -v        // 查看gcc版本

                make -v        // 查看make版本

                arm-cortex_a9-linux-gnueabi-gcc -v        // 查看交叉编译工具链版本

                make V=1        // V=1将编译链接的详细过程展示出来

        /*查看最后的链接*/

                arm-cortex_a9-linux-gnueabi-ld.bfd -pie --gc-sections -Bstatic -Ttext 0x43C00000 -o u-boot -T u-boot.lds arch/arm/cpu/slsiap/start.o

        /*这里的start.o是.c文件还是.s文件*/

        /*是.s文件,因为在初始化硬件初期时,内存没有被初始化,不能是.c文件,由此确定*/

        /*入口点文件是start.S文件*/

                2) 查找源码的入口点文件(法二)

        /*通过查看链接脚本文件,确定入口点*/

        vim uboot/u-boot.lds //连接脚本

/*文件内容*/

arch/arm/cpu/slsiap/s5p6818/start.o 入口点目标文件

arch/arm/cpu/slsiap/s5p6818/start.S 入口点文件

/*发现于法一的结果不同,以链接脚本文件为准,由此确定*/

 /*入口点文件是arch/arm/cpu/slsiap/s5p6818/start.S文件*/

        5、uboot的执行流程 

        【1】vim arch/arm/cpu/slsiap/s5p6818/start.S

        【2】设置cpu为SVC管理模式

        【3】关闭看门狗

        【4】禁止L1 L2缓存,关闭MMU内存管理单元

                关闭MMU内存管理单元的目的:要使用物理地址

        【5】回到被调用的位置

        【6】跳转到cpu_init_crit

        【7】跳转到lowlevel_init

        【8】vim arch/arm/cpu/slsiap/s5p6818/low_init.S

        【9】跳转到clear_bss

        【10】先打开MMU内存管理单元,再清除bss段

                打开MMU内存管理单元的目的:可以使用虚拟地址,MMU在不断的更新物理地址和虚拟地址的映射

        【11】跳转到board_init_f

        【12】vim arch/arm/lib/board.c

        【13】board_init_f(重要!!!)

                它完成了一系列硬件的初始化

                如:cpu、uart、display、env。。。

        init_fnc_ptr:指向各硬件初始化函数的指针

        init_sequence:一个函数指针数组,包含着各硬件初始化函数的入口地址

经过一边循环,就可以对所有保存在数组里的硬件进行初始化

        【14】跳转到board_init_r

        【15】vim arch/arm/lib/board.c

        【16】board_init_r(重要!!!)

                它指定堆栈的区域,对EMMC进行初始化

        【17】main_loop()可以返回自动引导,如果已经引导了,那就再引导一次

        【18】cli_loop()

        【19】cli_simple_loop()

        6、总结

                1)uboot的执行流程

                        【1】设置cpu为svc管理模式

                        【2】关闭看门狗,防止系统复位重启

                        【3】禁止L1 L2缓存,以及关闭MMU,使用物理地址

                        【4】检验CPU-ID是否合法,防止不法厂商

                        【5】清除BSS段

                        【6】打开MMU,使用虚拟地址

                        【7】跳转到board_init_f初始化硬件(关键!!!)

                        【8】跳转到board_init_r指定堆栈区域,初始化EMMC(关键!!!)

                        【9】main_loop

                        【a】cli_loop

                        【b】cli_simple_loop

                2)修改默认配置

                        include/config/x6818.h

                【a】波特率

                【b】命令行提示符

                【c】各种环境变量

三、uboot中添加启动logo

        我们可以在所有的显示类设备增加一个启动logo(商业行为)

LCD、OLED、段码屏、数码管、点阵屏、LED灯、水立方

        1、显示原理 

        2、图像的构成

                图像是由一个一个像素点构成

                三原色

                16位色:RGB565

                32位色:RGB888【0~255】(前8位保留)

                红色:0x00FF0000

                绿色:0x0000FF00

                蓝色:0x000000FF

                白色:0xFFFFFFFF

                黑色:0x00000000

        3、LCD的分辨率

                7寸的LCD液晶显示屏

                lcd的分辨率 1024 * 600

                lcd的显存地址是由三星公司规定的0x46000000

                vim uboot/include/configs/x6818.h

                计算lcd对应点的地址P0(x0, y0)

                /*将P0点设置为红色*/

                *(volatile unsigned int *)(0x46000000 + ((y0 * 1024) + x0) * 4) = 0x00FF000000

        4、将图片转换为RGB

                工具位置:easthome_poriting\u-boot-logo\tools\Image2Lcd\Img2Lcd.exe 

        5、实验步骤

                1】将生成的子模文件拷贝至uboot目录

                cp logo.c uboot/common

                2】编写画点及画logo的函数

                vim uboot/common/draw_logo.c

#define LCD_BASE 0x46000000
#define WIDTH    1024
#define HIGHT    600
#define X0       0
#define Y0       0
#define LOGO_W   1024
#define LOGO_H   600extern const unsigned char gImage_logo[];void draw_pixel(int row, int col, int color)
{*(int *)(LCD_BASE + ((row * WIDTH) + col) * 4) = color;
}void lcd_draw_logo(void)
{int i = 0, j = 0;unsigned int blue = 0;unsigned int green = 0;unsigned int red = 0;unsigned int color = 0;const unsigned char *p = gImage_logo;for(i = Y0; i < (Y0 + LOGO_H); i++) {for(j = X0; j < (X0 + LOGO_W); j++) {blue = *p++;green = *p++;red = *p++;color = red << 16 | green << 8 | blue;draw_pixel(i, j, color);}}}
                3】添加调用画logo的函数

                vim uboot/arch/arm/cpu/slsiap/common/cmd_draw_logo.c

                4】修改Makefile文件

                vim uboot/common/Makefile

                5】编译uboot

                1]make distclean

                2]make x6818_config

                3]make

                6】烧写uboot

                1]上位机把新生成的ubootpak.bin文件拷贝到tftp共享目录中

                        cp ubootpak.bin /tftpboot

                2]下位机下载uboot

                        tftp 48000000 ubootpak.bin

                3]更新emmc

                        update_mmc 2 2ndboot 48000000 200 [下载的字节数]

                4]重启uboot

                        re

这篇关于Linux_kernel原理08的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141931

相关文章

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

MySQL中的MVCC底层原理解读

《MySQL中的MVCC底层原理解读》本文详细介绍了MySQL中的多版本并发控制(MVCC)机制,包括版本链、ReadView以及在不同事务隔离级别下MVCC的工作原理,通过一个具体的示例演示了在可重... 目录简介ReadView版本链演示过程总结简介MVCC(Multi-Version Concurr

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的

Linux编译器--gcc/g++使用方式

《Linux编译器--gcc/g++使用方式》文章主要介绍了C/C++程序的编译过程,包括预编译、编译、汇编和链接四个阶段,并详细解释了每个阶段的作用和具体操作,同时,还介绍了调试和发布版本的概念... 目录一、预编译指令1.1预处理功能1.2指令1.3问题扩展二、编译(生成汇编)三、汇编(生成二进制机器语

Rsnapshot怎么用? 基于Rsync的强大Linux备份工具使用指南

《Rsnapshot怎么用?基于Rsync的强大Linux备份工具使用指南》Rsnapshot不仅可以备份本地文件,还能通过SSH备份远程文件,接下来详细介绍如何安装、配置和使用Rsnaps... Rsnapshot 是一款开源的文件系统快照工具。它结合了 Rsync 和 SSH 的能力,可以帮助你在 li

Linux部署jar包过程

《Linux部署jar包过程》文章介绍了在Linux系统上部署Java(jar)包时需要注意的几个关键点,包括统一JDK版本、添加打包插件、修改数据库密码以及正确执行jar包的方法... 目录linux部署jar包1.统一jdk版本2.打包插件依赖3.修改密码4.执行jar包总结Linux部署jar包部署