前置:这里使用的linux版本是4.8,x86体系。

其实linux的内核启动的入口文件还是非常好找的,init/main.c。

static 和 extern

首先理解的是static和extern的区别:

static int kernel_init(void *);

extern void init_IRQ(void);
extern void fork_init(void);
extern void radix_tree_init(void);

这个代码说的是kernel_init函数的定义在这个文件中,extern说明init_IRQ函数的定义在其他文件中。

这三个extern分别是对中断的初始化,对fork功能的初始化,对基数树的初始化。不过具体不知道为什么有的函数以init_xxx为风格,有的又以xxx_init的风格来做。

main的第一行看到了这么个语句

#define DEBUG

感觉有点奇怪,原来还有#define <宏名> 而没有定义具体的值。其实这个可以当作已经有定义,且定义了空串来理解。

http://bbs.csdn.net/topics/390960776?page=1

继续往下面看,还会看到

bool early_boot_irqs_disabled __read_mostly;

这里最后的__read_mostly 是一个宏,它标记了前面这个变量是很经常被读取的。那么做了标记有什么用呢?

如果在有缓存的平台上,它就能把这个变量存放到cache中,以保证后续读取的速度。这个宏定义在 arch/arm/include/asm/cache.h

#define __read_mostly __attribute__((__section__(".data..read_mostly")))

这里的意思是将这个数据结构链接进data.read_mostly段。

EXPORT_SYMBOL

EXPORT_SYMBOL(system_state);

这个是和extern一起使用的,表示system_state这个方法在这个模块中定义了,提供给其他模块使用。

在其他模块中,只需要使用extern 就可以使用这个方法。

这里就涉及到模块的概念。

模块是linux内核对外提供的一个插件机制,由于linux是单内核,这个单内核是相对微内核来说的。所以linux很大可能会非常庞大,这个模块机制就是对单内核的一种补充,把一些功能放给内核模块开发。比如像上面的那个代码,就是对内核提供了system_state的函数接口。

__initdata

下面代码:

char __initdata boot_command_line[COMMAND_LINE_SIZE];

这里的__initdata也是一个宏,定义在include/linux/init.h

#define __init        __section(.init.text) __cold notrace
#define __initdata __section(.init.data)
#define __initconst __constsection(.init.rodata)
#define __exitdata __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)

同上面__read_mostly一样,是用来把这个变量绑定在某个区里面。

http://blog.csdn.net/beatbean/article/details/8448623

这个图就说明了什么是__section。它的功能有点像是全局变量,只是这个全局变量是对汇编这个层次的表达,某个变量,我固定在某个内存段里面。这么做其实还有一个好处,段也是一种分类,比如这个段存储的是init函数的变量,那么等初始化结束之后,我把这个段的内存直接释放。里面的变量也一次性消除了。

EXPORT_SYMBOL_GPL

下面看到一个很奇怪的方法

EXPORT_SYMBOL_GPL(static_key_initialized);

这个和之前的EXPORT_SYMBOL不一样,多了一个GPL后缀。

由于模块很有可能是第三方(非linux内核组成员)开发的。那么有人希望自己开发的模块是闭源的。它就会在自己开发的模块里面使用

MODULE_LICENSE("Proprietary")

来标记这个模块是闭源的。相对的,如果你的模块遵循GPL这个开源许可证规则,那么则增加下面的:

MODULE_LICENSE("GPL");

好了,linux对这两种许可证行为的模块开放的接口并不相同,本节的这个函数就是说明这个方法只对GPL的模块开放。

http://www.ruanyifeng.com/blog/2010/02/why_gpl_is_a_better_choice.html

__setup 和 early_param

unsigned int reset_devices;

EXPORT_SYMBOL(reset_devices);

static int __init set_reset_devices(char *str)

{

reset_devices = 1;

return 1;

}

__setup("reset_devices", set_reset_devices);

这段代码,首先需要理解__setup,这个函数就理解为:启动时候如果有接收reset_devices参数,那么就调用set_reset_devices方法。而详细看了下set_reset_devices方法,里面只是把reset_devices变量设置为1,但是呢,这个reset_devices变量又是一个给所有模块使用的变量。

所以这段代码能达到的功能是只要启动参数有包含reset_device,通过设置reset_devices通知给所有模块。

与__setup相对应的还有一个叫做early_param。这两个宏函数的功能一样,区别就在于early_param定义的参数比__setup更早。

http://www.linuxde.net/2013/02/12446.html

linux源码分析(一)的更多相关文章

  1. linux源码分析2

    linux源码分析 这里使用的linux版本是4.8,x86体系. 这篇是 http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html  ...

  2. Linux源码分析之:malloc、free

    之前写代码的时候一直有个疑问,malloc申请内存的时候指定了内存大小,但是free的时候却只指定要释放的内存地址,那么free是如何知道它要释放的内存空间大小呢? 源码之前,了无秘密,下面就从源码来 ...

  3. linux源码分析(五)-start_kernel

    前置:这里使用的linux版本是4.8,x86体系. local_irq_disable(); 这个函数是做了关闭中断操作.和后面的local_irq_enable相对应.说明启动的下面函数是不允许被 ...

  4. linux源码分析(四)-start_kernel-cgroup

    前置:这里使用的linux版本是4.8,x86体系. cgroup_init_early(); 聊这个函数就需要先了解cgroup. cgroup概念 这个函数就是初始化cgroup所需要的参数的.c ...

  5. linux源码分析(三)-start_kernel

    前置:这里使用的linux版本是4.8,x86体系. start_kernel是过了引导阶段,进入到了内核启动阶段的入口.函数在init/main.c中. set_task_stack_end_mag ...

  6. linux源码分析(二)-启动过程

    前置:这里使用的linux版本是4.8,x86体系. 这篇是 http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html 的学习笔记. ...

  7. linux源码分析 - 进程

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 最近在回想一些知识点的时候,觉得对进程这一块有些模糊,特别写一篇随笔对进程信息进行巩固和复习. 程序和进程 以我 ...

  8. 源码分析:动态分析 Linux 内核函数调用关系

    源码分析:动态分析 Linux 内核函数调用关系 时间 2015-04-22 23:56:07  泰晓科技 原文  http://www.tinylab.org/source-code-analysi ...

  9. Linux内核源码分析方法

    一.内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次.如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径.我们都 ...

随机推荐

  1. 不需要sql进行计算数据的平均值、最大值、最小值、和

    介绍下SqlServer.前端js.后台C#三个阶段对均值.最大值.最小值.和计算int[] jisuan = {0, 1, 3, 5, 7,8 }; List<int> jisuan2 ...

  2. win 8 换 win7 注意事项

    win8 换win7 硬盘格式修改一下gpt 格式转换为mbr模式 当进入到要选择安装到某一个盘时,由于磁盘的类型不同,会提示:“选中的磁盘采用GPT分区形式无法安装系统”.这时需要重新设置分区形式( ...

  3. 代码自定义双色title的按钮

    所图所示,通过代码自定义这样的按钮. .h文件 // // CustomButtom.h // testPlus // // Created by 鹰眼 on 14/10/20. // Copyrig ...

  4. Microsoft开源跨平台的序列化库——Bond

    上个月Microsoft开源了Bond,一个跨平台的模式化数据处理框架.Bond支持跨语言的序列化/反序列化,支持强大的泛型机制能够对数据进行有效地处理.该框架在Microsoft公司内部的高扩展服务 ...

  5. 使用 MimeKit 和 MailKit 发送邮件

    MimeKit 给.NET 社区带来了一流的 MIME 解析器,它能处理复杂的各种Mime, 性能好.而且开箱即用支持 S/MIME 和 PGP.MimeKit 和 MailKit 支持最新的国际化的 ...

  6. ABP理论学习之仓储

    返回总目录 本篇目录 IRepository接口 查询 插入 更新 删除 其他 关于异步方法 仓储实现 管理数据库连接 仓储的生命周期 仓储最佳实践 Martin Fowler对仓储的定义 位于领域层 ...

  7. 剑指Offer面试题:15.反转链表

    一.题目:反转链表 题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点. 链表结点定义如下,这里使用的是C#描述: public class Node { public in ...

  8. 我所理解的RESTful Web API [Web标准篇]

    REST不是一个标准,而是一种软件应用架构风格.基于SOAP的Web服务采用RPC架构,如果说RPC是一种面向操作的架构风格,而REST则是一种面向资源的架构风格.REST是目前业界更为推崇的构建新一 ...

  9. maven pom中的repository节点配置没有起作用

    问题描述 昨天晚上想用spring boot快速搭建一个web开发的项目,就打开spring boot的doc,按照说明开始尝试.没想到出师未捷身先死,第一步就挂了. 以下是spring boot的配 ...

  10. 解决OracleConnection ORA-1017 和 HRESULT:0x8007000B 错误

    试图加载格式不正确的程序. (异常来自HRESULT:0x8007000B) 解决方案: IIS下 winform下: ORA-1017 错误