【linux kernel】linux 内核设备模型的初始化(01)

linux 内核设备模型的初始化(01)

一、驱动框架模型初始化流程
(1-1)driver_init()

驱动框架模型的初始化操作由driver_init()函数完成(/drivers/base/init.c)

void __init driver_init(void)
{
	/* 核心初始化部分 */
    //(/drivers/base/devtmpfs.c)
	devtmpfs_init();
    //(/drivers/base/core.c)
	devices_init();
    //(/drivers/base/buses.c)
	buses_init();
    //(drivers/base/class.c)
	classes_init();
    //(drivers/base/firmware.c)
	firmware_init();
    //(drivers/base/hypervisor.c)
	hypervisor_init();
    
    
/* 以下函数也是驱动模型初始化的核心,但是要放在以上函数的后面调用 */
   //(drivers/base/platform.c)
	platform_bus_init();
    //(drivers/base/auxiliary.c)
	auxiliary_bus_init();
    //(drivers/base/cpu.c)
	cpu_dev_init();
    //(drivers/base/memory.c)
	memory_dev_init();
    //(drivers/base/container.c)
	container_dev_init();
    //(drivers/of/base.c)
	of_core_init();
}
(1-2)do_basic_setup()

driver_init()在(init/main.c)中do_basic_setup()函数中被调用:

static void __init do_basic_setup(void)
{
	cpuset_init_smp();
	usermodehelper_init();
	shmem_init();
	driver_init();
	init_irq_proc();
	do_ctors();
	usermodehelper_enable();
	do_initcalls();
	random_int_secret_init();
}
二、devtmpfs初始化

devtmpfsdevtmpfs_init()函数完成,如下代码所示:

int __init devtmpfs_init(void)
{
	int err = register_filesystem(&dev_fs_type);
	if (err) {
		printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
		       "type %i\n", err);
		return err;
	}

	thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
	if (!IS_ERR(thread)) {
		wait_for_completion(&setup_done);
	} else {
		err = PTR_ERR(thread);
		thread = NULL;
	}

	if (err) {
		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
		unregister_filesystem(&dev_fs_type);
		return err;
	}

	printk(KERN_INFO "devtmpfs: initialized\n");
	return 0;
}

上述第3行代码,调用register_filesystem()注册devtmpfs文件系统,devtmpfs文件系统类型定义如下:

static struct file_system_type dev_fs_type = {
	.name = "devtmpfs",
	.mount = dev_mount,
	.kill_sb = kill_litter_super,
};

在整个linux内核启动过程中,在注册驱动程序核心设备之前,将创建基于tmpfs的文件系统devtmpfs。每个请求设备节点的驱动核心设备都将在这个文件系统中添加一个节点。默认情况下,所有设备都以设备名命名,属于根用户,默认模式为0600(小生疑问:这个是什么含义呢?),子系统可以在需要时覆盖默认设置。

三、kset、kobject概述
(3-1)kobject概述

kobject内核对象定义:

struct kobject {
	const char		*name;
	struct list_head	entry;
	struct kobject		*parent;
	struct kset		*kset;
	struct kobj_type	*ktype;
	struct kernfs_node	*sd;
	struct kref		kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
	struct delayed_work	release;
#endif
	unsigned int state_initialized:1;
	unsigned int state_in_sysfs:1;
	unsigned int state_add_uevent_sent:1;
	unsigned int state_remove_uevent_sent:1;
	unsigned int uevent_suppress:1;
};
(3-2)kset概述

kset有如下定义(/include/linux/kobject.h):

struct kset {
    //这个kset的所有kobject的列表
	struct list_head list; 
    //用于遍历kobject的锁
	spinlock_t list_lock;
     //放在kset中的kobject
	struct kobject kobj;
    //kset的uevent操作集
	const struct kset_uevent_ops *uevent_ops; 
};

kset用于描述:一个特定子系统的一组特定类型的kobjects,即使用kset来描述一个子系统的多个kobjects。它们可以是单独的、不同的类型,但总的来说,这些kobjects都希望被组合在一起,并以相同的方式操作它们。kset用于定义属性回调和发生在kobject上的其他的常见事件。

四、devices初始化

linux 内核使用devices_init()函数来初始化devices、dev内核设备模型的支持对象,定义如下:

int __init devices_init(void)
{
	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
	if (!devices_kset)
		return -ENOMEM;
	dev_kobj = kobject_create_and_add("dev", NULL);
	if (!dev_kobj)
		goto dev_kobj_err;
	sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
	if (!sysfs_dev_block_kobj)
		goto block_kobj_err;
	sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
	if (!sysfs_dev_char_kobj)
		goto char_kobj_err;

	return 0;

 char_kobj_err:
	kobject_put(sysfs_dev_block_kobj);
 block_kobj_err:
	kobject_put(dev_kobj);
 dev_kobj_err:
	kset_unregister(devices_kset);
	return -ENOMEM;
}

上述代码中kobject_create_and_add使用动态方法创建struct kset,并将其添加到sysfs中,当该函数执行完成后,linux内核下将会有devices(/sys/devices/)对象集合、还创建了dev对象,其中dev对象包含blockchar两个子对象。

五、buses初始化

linux内核中使用buses_init()函数来初始化buses总线。定义如下(/drivers/base/bus.c):

int __init buses_init(void)
{
	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
	if (!bus_kset)
		return -ENOMEM;

	system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
	if (!system_kset)
		return -ENOMEM;

	return 0;
}

上述代码第3行,使用kset_create_and_add()创建bus对象集合。

第7行代码,使用kset_create_and_add()创建了system集合,同时指定system的父对象是在devices_init()中创建的devices对象集。

函数buses_init()的本质就是在系统中创建bussystem两个与buses相关的对象集合。

如下图所示,在根文件系统中有以下的目录信息:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-83B2RWlu-1644243333731)(/home/iriczhao/.config/Typora/typora-user-images/image-20220127212836151.png)]

六、classes初始化

linux内核中使用classes_init()函数来初始化classes类。定义如下(/drivers/base/class.c):

int __init classes_init(void)
{
	class_kset = kset_create_and_add("class", NULL, NULL);
	if (!class_kset)
		return -ENOMEM;
	return 0;
}

buses_init()相同,使用kset_create_and_add()创建class对象集。

在这里插入图片描述

七、firmware初始化

linux内核中使用firmware_init()函数来进行firmware初始化。定义如下(/driver/base/firmware.c):

int __init firmware_init(void)
{
	firmware_kobj = kobject_create_and_add("firmware", NULL);
	if (!firmware_kobj)
		return -ENOMEM;
	return 0;
}

同样的,firmware_init使用kobject_create_and_add()firmware被添加到/sys/中。

八、hypervisor初始化

linux内核中使用hypervisor_init()函数进行hypervisor的初始化,如下定义(/driver/base/hypervisor.c):

int __init hypervisor_init(void)
{
	hypervisor_kobj = kobject_create_and_add("hypervisor", NULL);
	if (!hypervisor_kobj)
		return -ENOMEM;
	return 0;
}

同样的,hypervisor_init()将创建hypervisor对象,并将其添加到/sys/中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iriczhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值