log_init,

int log_init(void)
{
    struct log_driver *drv = ll_entry_start(struct log_driver, log_driver);

#define ll_entry_start(_type, _list)                    \
    ({                                    \
             static char start[0] __aligned(4) __attribute__((unused, section(".u_boot_list_2_"#_list"_1")));            \
              (_type *)&start;                        \
     })

//等价于:

//struct log_driver *drv = {static char start[0];(struct log_driver*)&start;},其中start[0]放置在.u_boot_list_2_log_driver_1段

/*.u_boot_list在u-boot.lds定义

.u_boot_list : {
                 KEEP(*(SORT(.u_boot_list*)));}

并按照u_boot_list后面的字符进行排序*/

const int count = ll_entry_count(struct log_driver, log_driver);

#define ll_entry_count(_type, _list)                    \
    ({                                \
        _type *start = ll_entry_start(_type, _list);        \
        _type *end = ll_entry_end(_type, _list);        \
        unsigned int _ll_result = end - start;            \
        _ll_result;                        \
    })

//等价于const int count=ll_entry_end(_type, _list)-ll_entry_start(_type, _list),即计算.u_boot_list_2_log_driver_3和.u_boot_list_2_log_driver_1之间有多少个struct log_driver结构体
    struct log_driver *end = drv + count;             //指向.u_boot_list_2_log_driver_3处
    INIT_LIST_HEAD((struct list_head *)&gd->log_head);

static inline void INIT_LIST_HEAD(struct list_head *list)
    {
          list->next = list;
          list->prev = list;
     }

//即将gd->log_head设置为循环链表的头
    while (drv < end) {
        struct log_device *ldev;

ldev = calloc(1, sizeof(*ldev));              //给ldev分配空间
        if (!ldev) {
            debug("%s: Cannot allocate memory\n", __func__);
            return -ENOMEM;
        }
        INIT_LIST_HEAD(&ldev->filter_head);     //将ldev->filter_head成员初始化为循环链表
        ldev->drv = drv;                                        //将ldev->drv成员指向当前的log_driver
        list_add_tail(&ldev->sibling_node,
                  (struct list_head *)&gd->log_head);    //把ldev->sibling_node成员加入到gd->log_head的循环链表中
        drv++;
    }

//通过该循环,将.u_boot_list_2_log_driver_3和.u_boot_list_2_log_driver_1之间的所有struct log_driver结构体都加入到了gd->log_head的循环链表中
    gd->flags |= GD_FLG_LOG_READY;

//之前gd->flags=0,此时设置gd->flags为GD_FLG_LOG_READY,即gd->flags=0x08000
    if (!gd->default_log_level)
        gd->default_log_level = LOGL_INFO;        //设置gd->default_log_level为LOGL_INFO
    gd->log_fmt = LOGF_DEFAULT;                    //设置gd->log_fmt为LOGF_DEFAULT

return 0;
}

log_init的主要功能是将.u_boot_list_2_log_driver_3和.u_boot_list_2_log_driver_1之间的所有struct log_driver结构体都加入到了gd->log_head的循环链表中,并初始化gd->default_log_level和gd->log_fmt
————————————————
版权声明:本文为CSDN博主「yanggx0929」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yanggx0929/article/details/88785318

u-boot log_init函数分析的更多相关文章

  1. 精尽Spring Boot源码分析 - SpringApplication 启动类的启动过程

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  2. 精尽Spring Boot源码分析 - 配置加载

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  3. split(),preg_split()与explode()函数分析与介

    split(),preg_split()与explode()函数分析与介 发布时间:2013-06-01 18:32:45   来源:尔玉毕业设计   评论:0 点击:965 split()函数可以实 ...

  4. string函数分析

    string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把 ...

  5. start_amboot()函数分析

    一.整体流程 start_amboot()函数是执行完start.S汇编文件后第一个C语言函数,完成的功能自然还是初始化的工作 . 1.全局变量指针r8设定,以及全局变量区清零 2.执行一些类初始化函 ...

  6. uboot的jumptable_init函数分析

    一.函数说明 函数功能:安装系统函数指针 函数位置:common/exports.c 二.函数分析 void jumptable_init (void) { int i; gd->jt = (v ...

  7. Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析

    Linux-0.11内存管理模块是源码中比較难以理解的部分,如今把笔者个人的理解发表 先发Linux-0.11内核内存管理get_free_page()函数分析 有时间再写其它函数或者文件的:) /* ...

  8. 31.QPainter-rotate()函数分析-文字旋转不倾斜,图片旋转实现等待

    在上章和上上上章: 28.QT-QPainter介绍 30.QT-渐变之QLinearGradient. QConicalGradient.QRadialGradient 学习了QPainter基础绘 ...

  9. Spring Boot 入门详细分析

    推荐阅读: 我们为什么要学习 Spring Boot 我们搭建 Spring Boot 项目,可以使用 Spring 为我们提供的初始化网站,那个可能不太方便,今天呢,我们就来说说如何使用 IDEA ...

随机推荐

  1. android studio中方法和类被调用多次,但是AS显示灰色,解决办法

    Android Studio里面的一些类及方法,明明有被其他的类或者方法调用,但是去看的时候显示灰色,鼠标放上面的时候显示:Class ‘XXX’ is never used或者Method ‘XXX ...

  2. Oracle 安装 RAC 11.2.0.4 centos7.4 -udev磁盘绑定/执行root脚本报错

    在centos 7.4上安装oracle rac 11.2.0.4 报错及相关解决 $ cat /etc/redhat-release CentOS Linux release 7.4.1708 (C ...

  3. .on()之selector——jQuery

    API:[https://www.jquery123.com/on/]

  4. ElasticSearch的中文分词器ik

    一.前言   为什么要在elasticsearch中要使用ik这样的中文分词呢,那是因为es提供的分词是英文分词,对于中文的分词就做的非常不好了,因此我们需要一个中文分词器来用于搜索和使用. 二.IK ...

  5. vsftp新建用户及目录时遇到的坑

    1.有关vsftp配置及用户权限设置,请参考: http://blog.sina.com.cn/s/blog_3edc5e2e0102vzv8.html 2.需求:公司另一部门要求单独建一目录,来存在 ...

  6. 关于glog使用中遇到的问题

    项目中需要打log,当初看到glog,觉得google出品应该差不了,而且简单易用,库不是很大,就选择他了. 但是在使用中还真的发现一些不顺手和库设计上的问题,反正和我的使用习惯有点不一样. 设置lo ...

  7. js 数组去重方法总结

    var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, ...

  8. USACO1.6 Superprime Rib

    题目传送门 每一个特殊质数都会被从右边切掉,所以除了首位外的其它位数一定都不会是偶数,只能是$1$,$3$,$5$,$7$,$9$ 而每一个特殊质数的首位一定是质数,也就是$2$,$3$,$5$,$7 ...

  9. pyhton自动化项目编码以及命名规范

    对于任何一个编程项目来说,都需要一个编码的规范以及标准,这里整理了一些Google python的命名规范以及python语言PEP8的编码规范. 一.命名规范 命名示例: module_name, ...

  10. selenium之京东商品爬虫

    #今日目标 **selenium之京东商品爬虫** 自动打开京东首页,并输入你要搜索的东西,进入界面进行爬取信息 ``` from selenium import webdriver import t ...