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

相关文章

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

Linux ls命令操作详解

《Linuxls命令操作详解》通过ls命令,我们可以查看指定目录下的文件和子目录,并结合不同的选项获取详细的文件信息,如权限、大小、修改时间等,:本文主要介绍Linuxls命令详解,需要的朋友可... 目录1. 命令简介2. 命令的基本语法和用法2.1 语法格式2.2 使用示例2.2.1 列出当前目录下的文

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

鸿蒙中@State的原理使用详解(HarmonyOS 5)

《鸿蒙中@State的原理使用详解(HarmonyOS5)》@State是HarmonyOSArkTS框架中用于管理组件状态的核心装饰器,其核心作用是实现数据驱动UI的响应式编程模式,本文给大家介绍... 目录一、@State在鸿蒙中是做什么的?二、@Spythontate的基本原理1. 依赖关系的收集2.

Linux中的计划任务(crontab)使用方式

《Linux中的计划任务(crontab)使用方式》:本文主要介绍Linux中的计划任务(crontab)使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、前言1、linux的起源与发展2、什么是计划任务(crontab)二、crontab基础1、cro