1 前言
前面我们已经总结了从硬件上电到内核启动初始化的过程,但由于篇幅原因,对于一些比较重要的函数只是进行了简单介绍。本节我们来研究关于driver_init
函数的研究,从单词上的意思来讲,这个函数用于初始化驱动设备模型,也就是/sys
目录下的一些初始化工作,对于驱动开发工程师比较重要。
2 源码解析
注:本节代码取自Kernel 4.9,位置:driver/base/init.c
/**
*driver_init函数用来初始化驱动模型
* 驱动模型初始化函数用来初始化他们的子系统。最早在init/main.c中调用。
*/
void __init driver_init(void)
{
/* 这些是核心部分 */
/*devtmpfs文件系统初始化,该代码在drivers/base/devtmpfs.c中定义
devtmpfs-基于tmpfs的 /dev
在引导过程中,在注册任何驱动程序核心设备之前,
会创建一个基于tmpfs的文件系统devtmpfs。
每个请求设备节点的驱动核心设备都将在此文件系统中添加一个节点。
默认情况下,所有设备都以设备名称命名,该名称由root所有,
默认模式为0600。如果需要,子系统可以覆盖默认设置。
*/
devtmpfs_init();
/*初始化驱动模型中的部分子系统和kobject,
在 drivers/base/core.c中定义
其实就是做了以下操作
1.创建/sys/devices目录
2.创建一个/sys/dev的目录
3.在dev下创建block目录
4.在dev下创建char目录
*/
devices_init();
/*初始化总线驱动,在drivers/base/bus.c中定义
其实就是做了以下操作
1.创建/sys/bus目录
2.在/sys/devices下创建system目录
*/
buses_init();
/*
创建/sys/class目录,该目录下包含所有注册在kernel里面的设备类型,这是按照设备功能分类的设备模型,每个设备类型表达具有一种功能的设备。
定义在drivers/base/class.c
*/
classes_init();
/*
固件子系统初始化
firmware目录下包含对固件对象(firmware object)和属性进行操作和观察的接口,即这里是系统加载固件机制的对用户空间的接口.(关于固件有专用于固件加载的一套API)
在drivers/base/firmware.c中定义
其实就是创建了/sys/firmware目录
*/
firmware_init();
/*
hypervisor目录是与虚拟化Xen相关的装置。
/sys/hypervisor子系统初始化*/
hypervisor_init();
/* 这些也是核心部分,但必须在上面核心部分之后调用 */
/*
用于旧设备的平台'pseudo(虚拟、伪)'总线初始化
调用device_register创建了/sys/devices/platform目录以及对应设备对象
调用bus_register创建了/sys/bus/platform目录以及uneven等文件
*/
platform_bus_init();
/*cpu子系统初始化
用于启动未启动的其他CPU
会在/sys/devices/system/节点下建立一个名为”cpu”的子节点/sys/devices/system/cpu/,该节点包含CPU相关的属性
*/
cpu_dev_init();
/*内存设备初始化
建立memory设备在sysfs中的接口
会在/sys/devices/system/节点下建立一个名为”memory”的子节点/sys/devices/system/memory/;该节点包含了内存相关的属性,如块大小等
*/
memory_dev_init();
/*会在/sys/devices/system下创建container目录*/
container_dev_init();
/*会在/sys/firmware下创建devicetree目录以及相应的一些东西*/
of_core_init();
}
注:
Platform总线:
Platform总线是Linux设备驱动模型为了保持设备驱动的统一性而虚拟出来的总线。因为对于usb设备、i2c设备、pci设备、spi设备等等,他们与cpu的通信都是直接挂在相应的总线下面与cpu进行数据交互的,但是在嵌入式系统当中,并不是所有的设备都能够归属于这些常见的总线,在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设却不依附与此类总线。所以Linux驱动模型为了保持完整性,将这些设备挂在一条虚拟的总线上(platform总线),而不至于使得有些设备挂在总线上,另一些设备没有挂在总线上。
对于platform总线的解释转自此博客
3 总结
本篇文章主要列出了device_init的源码,并对它所调用的所有函数进行了介绍,对于这些函数没有进行展开讲解,里面的一些函数的实现不在本系列的范围内,如果有兴趣可以把源码打开详细了解。
本系列链接传送: