读U-Boot源码-C语言编程大法总结篇一

导读:如本人在《U-Boot架构浅析》所说,U-Boot具有十大黄金原则:小巧、快速、简单、可移植、可配置、可调试、易用、可维护、优雅、开源。面对如此精美的作品,如不深究,从提升编程技艺角度而言实为憾事。故本文试图观其形而悟其神,并把所见所思所得记录与诸君分享。文中观点或有错误疏漏,诚请交流指正,不甚感激!

说明:

  • 封面配图,纯为搞笑

  • 文中绘图采用UML语言,或有不对也请一并指正。

  • 代码分析基于u-boot-2016.09.y

    代码见下面

    https://gitlab.denx.de/u-boot/u-boot/-/tree/u-boot-2016.09.y

所得之一:封装思想

U-boot将几乎所有信息集总抽象至global_data,概括而言,大体有以下信息:

  • bd_info(bd_t*)包含CPU频率,内存大小,FLASH大小等信息

    为实现可移植原则,将不同体系结构利用宏进行选编译。

  • 通用属性数据:CPU频率、PCI频率、内存频率、环境变量地址、堆信息等杂散参数信息。

  • 驱动设备接口:

    • struct udevice     *dm_root;

      驱动程序模型的根指针

    • struct udevice     *dm_root_f;

      重定向前驱动程序模型的根指针

    • struct list_headuclass_root;

      uclass链表,所有被udevice匹配的uclass都会被挂载到这个双向链表上

    • struct udevice     *timer;

      定时器设备指针

    • struct udevice*cur_serial_dev;

      当前串口设备指针

  • structarch_global_data arch,

    各不同体系结构属性。

所得:

  • 可移植:实现接口统一,通用部分实现,多样性兼顾。

  • 可配置:差异属性利用宏进行使能与关闭。

所得之二:宏的妙用

jt_funcs 定义了函数跳转表:

在static int initr_jumptable(void)进行初始化。

#define EXPORT_FUNC(impl, res, func, ...)  res(*func)(__VA_ARGS__);

  • impl,函数名这个参数展开时没有用到,只是为了增加可读性。相当于函数实现名。

  • res 返回值

  • __VA_ARGS__ 可变参数列表

如:

EXPORT_FUNC(get_version, unsigned long,get_version, void)

展开为:

unsigned long (* get_version) (void)

利用该宏定义可变参数函数指针,将一系列不同函数原型用一种统一的格式进行定义,并收集在_exports.h中,jt_funcs结构体将该头文件包含,并封装而成跳转表结构体。编译预处理时自动将定义插入到结构体的定义中了。

<include /_exports.h>包含封装在EXPOR_FUNC宏中的一系列导出函数,其中一些导出取决于“ CONFIG_XXX”选项。将根据包含此标头的文件定义宏。例如,在common / exports.c>中,将设置EXPOR_FUNC宏以使用<include /_exports.h>中的函数初始化跳转表结构。 在<include /exports.h>中,EXPOR_FUNC宏将设置为包含在跳转表结构中的函数指针的类型。

这样做的好处:

  • 可维护性极高,如需添加或修改跳转表结构体函数,只需修改_exports.h,以及修改对应的实现源文件

  • 定义函数指针进跳转表另一个给我启发是,可以实现动态加载,以实现统一接口不同操作。类似C 的函数重载。

 所得之三:环形缓冲区

在分析控制台模块部分代码时发现,其内存缓冲区采用环形缓冲区。

所得之一:将环形缓冲区预留一个字节以判断满/空。这样做程序优雅实现简便。

  • 环形缓冲I/O:@start @size - 1

  • 空:如果@head ==@tail 则空

  • 满:如果在追加一个字节使@head== @tail,则满

未完待续。。。

点击留言

(0)

相关推荐

  • C语言学习篇(15)-----函数传参详解

    https://m.toutiao.com/is/JpuAcLb/ 前面我们已经介绍过什么是指针,指针变量的用法等等,今天我们就来讲讲什么是函数,函数有啥作用,函数的参数有哪些需要注意的地方以及指针与 ...

  • 读 Java Arrays 源码 笔记

    Arrays.java是Java中用来操作数组的类.使用这个工具类可以减少平常很多的工作量.了解其实现,可以避免一些错误的用法. 它提供的操作包括: 排序 sort 查找 binarySearch() ...

  • (2条消息) spring boot 源码解析2

    前言 我们生成一个spring boot 项目时,会自带一个启动类. 代码如下: @SpringBootApplication public class DemoApplication { publi ...

  • 线程池ThreadPoolExecutor源码分析,看这一篇就够了

    前言 多线程是我们日常工作中很少能接触到的技术,但是面试的时候100%会被问到,万一工作中用到了基本不会,本篇咱们就来深入分析线程池的实现类ThreadPoolExecutor. 1.构造方法 构造方 ...

  • 模块一 GO语言基础知识-库源码文件

    你已经使用过 Go 语言编写了小命令(或者说微型程序)吗? 当你在编写"Hello, world"的时候,一个源码文件就足够了,虽然这种小玩意儿没什么用,最多能给你一点点莫名的成就 ...

  • 模块一 Go语言基础知识-命令源码文件

    我们已经知道,环境变量 GOPATH 指向的是一个或多个工作区,每个工作区中都会有以代码包为基本组织形式的源码文件. 这里的源码文件又分为三种,即:命令源码文件.库源码文件和测试源码文件,它们都有着不 ...

  • 源码读起来,Go源码共读计划

    由来 随着云原生的越来越成熟,Go语言也顺其自然的被各大公司采用. 相信越来越多的人,或多或少的都了解或接触都一点点的GO. 同时,也有越多越多的应用,从其他的语言转到了Go语言的怀抱. Go语法及其 ...

  • 两万字长文带你深入Go语言GC源码(上)

    作者:luozhiyun,腾讯IEG后台开发工程师 博客: https://www.luozhiyun.com/archives/475 本文使用的 Go 的源码1.15.7 介绍 三色标记法 三色标 ...

  • 两万字长文带你深入Go语言GC源码(下)

    作者:luozhiyun,腾讯IEG后台开发工程师 博客: https://www.luozhiyun.com/archives/475 本文使用的 Go 的源码1.15.7 创建后台标记 Worke ...

  • 春运火车票如何安心购票?用C语言实现火车售票系统(源码分享)

    今年春运首日火车票12月30日正式开售.每年春运,不少乘客为购得一张回家车票,"八仙过海.各显神通",然而,总有部分乘客"神通失灵".今年春运火车票如何安心购票 ...