《Linux内核编程》第十五章:Linux设备模型

2024-03-15 14:38

本文主要是介绍《Linux内核编程》第十五章:Linux设备模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文基于mstar801平台Linux2.6.35.11。

一、底层数据结构kset及kobject

kernel2.6.35.11/include/linux/kobject.h

struct kobject {const char		*name;  struct list_head	entry;struct kobject		*parent;struct kset		*kset;struct kobj_type	*ktype;struct sysfs_dirent	*sd;struct kref		kref;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;
};
struct kset {struct list_head list;spinlock_t list_lock;struct kobject kobj;const struct kset_uevent_ops *uevent_ops;
};

kernel2.6.35.11/lib/kobject.c

EXPORT_SYMBOL_GPL(kobject_get_path);
EXPORT_SYMBOL_GPL(kobject_init_and_add);
EXPORT_SYMBOL_GPL(kobject_rename);
EXPORT_SYMBOL_GPL(kobject_create_and_add);
EXPORT_SYMBOL_GPL(kset_create_and_add);

kobject:

kobject是Linux2.6引入的新的设备管理机制,通过这个数据结构使所有设备在底层都具有统一接口。

总线、设备和驱动就是通过kobject连接起来的;一般用于设备和驱动模型。

结合面向对象的思想,任何一个设备模型:总线、设备和驱动都属于一个kobject,这种派生关系就是在结构体中包含一个kobject的变量。

该结构体提供了所有模型需要的最基本的功能:引用计数,sysfs表示,热插拔事件处理。

内核用kobject结构将各个对象组成一个分层的结构体系,与模块化的子系统相匹配;有两个独立的机制用于连接:parent指针和kset域。

kset:

kset是管理kobject的集合;一般用于总线模型。

kobject通常通过kset组成成层次化的结构,kset是具有相同类型的kobject的集合;kset数据结构内嵌了一个kobject对象,所有属于kset的kobject对象的parent域都指向这个内嵌的对象。

二、基于底层数据结构kobject的设备模型:总线,设备,驱动

1.总线——bus_type:

kernel2.6.35.11/include/linux/device.h

struct bus_type {const char		*name;  //总线名称struct bus_attribute	*bus_attrs;  //总线属性struct device_attribute	*dev_attrs;  //设备属性struct driver_attribute	*drv_attrs;  //驱动属性int (*match)(struct device *dev, struct device_driver *drv);int (*uevent)(struct device *dev, struct kobj_uevent_env *env);int (*probe)(struct device *dev);int (*remove)(struct device *dev);void (*shutdown)(struct device *dev);int (*suspend)(struct device *dev, pm_message_t state);int (*resume)(struct device *dev);const struct dev_pm_ops *pm;struct subsys_private *p;  //总线类型私有数据
};

kernel2.6.35.11/drivers/base/base.h

struct subsys_private {struct kset subsys;  //与该总线相关的子系统struct kset *devices_kset;  //挂载在总线上的设备ksetstruct kset *drivers_kset;  //总线驱动程序的kset   struct klist klist_devices;  //挂载在总线上的设备链表struct klist klist_drivers;  //驱动程序链表struct blocking_notifier_head bus_notifier;unsigned int drivers_autoprobe:1;struct bus_type *bus;struct list_head class_interfaces;struct kset glue_dirs;struct mutex class_mutex;struct class *class;
};

说明:从上边结构体可以看出:一条总线拥有两条链表;一条是设备链表、一条是驱动链表。有了总线对应的数据结构,就可以获得总线关联了多少设备、以及有哪些驱动来支持这类设备。

后来注册的设备\驱动就是添加到kset中的。

kernel2.6.35.11/drivers/base/bus.c

EXPORT_SYMBOL_GPL(bus_register);
EXPORT_SYMBOL_GPL(bus_unregister);
EXPORT_SYMBOL_GPL(bus_register_notifier);
EXPORT_SYMBOL_GPL(bus_unregister_notifier);
EXPORT_SYMBOL_GPL(bus_get_kset);
EXPORT_SYMBOL_GPL(bus_get_device_klist);
EXPORT_SYMBOL_GPL(bus_create_file);
EXPORT_SYMBOL_GPL(bus_remove_file);
EXPORT_SYMBOL_GPL(bus_for_each_dev);
EXPORT_SYMBOL_GPL(bus_find_device);
EXPORT_SYMBOL_GPL(bus_find_device_by_name);
EXPORT_SYMBOL_GPL(bus_for_each_drv);
EXPORT_SYMBOL_GPL(bus_rescan_devices);
EXPORT_SYMBOL_GPL(device_reprobe);
EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);

2.设备——device:

kernel2.6.35.11/include/linux/device.h

struct device {struct device		*parent;    //父设备struct device_private	*p;    //设备结构的私有数据struct kobject kobj;    //kobject对象const char		*init_name; //设备初始化名字const struct device_type *type;    //设备方法struct mutex		mutex;	  //信号量struct bus_type	*bus;	//设备所在总线struct device_driver *driver;	//该设备的驱动void		*platform_data;	//平台总线私有数据struct dev_pm_info	power;struct dev_power_domain	*pwr_domain;
#ifdef CONFIG_NUMAint		numa_node;	/* NUMA node this device is close to */
#endifu64		*dma_mask;	/* dma mask (if dma'able device) */u64		coherent_dma_mask;/* Like dma_mask, but foralloc_coherent mappings asnot all hardware supports64 bit addresses for consistentallocations such descriptors. */struct device_dma_parameters *dma_parms;struct list_head	dma_pools;	/* dma pools (if dma'ble) */struct dma_coherent_mem	*dma_mem; /* internal for coherent memoverride *//* arch specific additions */struct dev_archdata	archdata;struct device_node	*of_node; /* associated device tree node */dev_t			devt;	/* dev_t, creates the sysfs "dev" */spinlock_t		devres_lock;struct list_head	devres_head;struct klist_node	knode_class;struct class		*class;const struct attribute_group **groups;	/* optional groups */void	(*release)(struct device *dev);
};

kernel2.6.35.11/drivers/base/base.h

struct device_private {struct klist klist_children;struct klist_node knode_parent;struct klist_node knode_driver;struct klist_node knode_bus;void *driver_data;    //我们关心的数据struct device *device;
};

说明:利用结构中的kobject跟kset进行关联;在进行设备注册时,将设备添加到总线中去。

kernel2.6.35.11/drivers/base/core.c

EXPORT_SYMBOL_GPL(device_add);
EXPORT_SYMBOL_GPL(device_del);
EXPORT_SYMBOL_GPL(device_register);
EXPORT_SYMBOL_GPL(device_unregister);
EXPORT_SYMBOL_GPL(device_for_each_child);
EXPORT_SYMBOL_GPL(device_find_child);
EXPORT_SYMBOL_GPL(device_initialize);
EXPORT_SYMBOL_GPL(get_device);
EXPORT_SYMBOL_GPL(put_device);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);
EXPORT_SYMBOL_GPL(__root_device_register);
EXPORT_SYMBOL_GPL(root_device_unregister);
EXPORT_SYMBOL_GPL(device_create_vargs);
EXPORT_SYMBOL_GPL(device_create);
EXPORT_SYMBOL_GPL(device_destroy);
EXPORT_SYMBOL_GPL(device_rename);
EXPORT_SYMBOL_GPL(device_move);
EXPORT_SYMBOL_GPL(device_create_bin_file);
EXPORT_SYMBOL_GPL(device_remove_bin_file);
EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
EXPORT_SYMBOL_GPL(dev_set_name);

3.驱动device_driver:

kernel2.6.35.11/include/linux/device.h

struct device_driver {const char		*name;struct bus_type		*bus;struct module		*owner;const char		*mod_name;	/* used for built-in modules */bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */const struct of_device_id	*of_match_table;int (*probe) (struct device *dev);int (*remove) (struct device *dev);void (*shutdown) (struct device *dev);int (*suspend) (struct device *dev, pm_message_t state);int (*resume) (struct device *dev);const struct attribute_group **groups;const struct dev_pm_ops *pm;struct driver_private *p;
};

kernel2.6.35.11/drivers/base/base.h

struct driver_private {struct kobject kobj;struct klist klist_devices;struct klist_node knode_bus;struct module_kobject *mkobj;struct device_driver *driver;
};

kernel2.6.35.11/drivers/base/driver.c

EXPORT_SYMBOL_GPL(driver_register);
EXPORT_SYMBOL_GPL(driver_unregister);
EXPORT_SYMBOL_GPL(driver_for_each_device);
EXPORT_SYMBOL_GPL(driver_find_device);
EXPORT_SYMBOL_GPL(driver_create_file);
EXPORT_SYMBOL_GPL(driver_remove_file);
EXPORT_SYMBOL_GPL(driver_add_kobj);
EXPORT_SYMBOL_GPL(get_driver);
EXPORT_SYMBOL_GPL(put_driver);

三、USB输入设备的总线、设备与驱动

1.USB总线,包含bus_type、间接包含kset

kernel2.6.35.11/include/linux/usb.h

extern struct bus_type usb_bus_type;
kernel2.6.35.11/drivers/usb/core/driver.c
struct bus_type usb_bus_type = {.name =		"usb",.match =	usb_device_match,.uevent =	usb_uevent,
};

2.设备,包含device、间接包含kobject

kernel2.6.35.11/include/linux/input.h

struct input_dev{......struct device dev;......
}

3.驱动,包含device_driver、间接包含kobject

kernel2.6.35.11/include/linux/usb.h

struct usb_driver {......struct usbdrv_wrap drvwrap;......
}
struct usbdrv_wrap {struct device_driver driver;int for_devices;
};

这篇关于《Linux内核编程》第十五章:Linux设备模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/812302

相关文章

linux生产者,消费者问题

pthread_cond_wait() :用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它。 pthread_cond_wait() 必须与pthread_mutex 配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程通过pthread

Linux 安装、配置Tomcat 的HTTPS

Linux 安装 、配置Tomcat的HTTPS 安装Tomcat 这里选择的是 tomcat 10.X ,需要Java 11及更高版本 Binary Distributions ->Core->选择 tar.gz包 下载、上传到内网服务器 /opt 目录tar -xzf 解压将解压的根目录改名为 tomat-10 并移动到 /opt 下, 形成个人习惯的路径 /opt/tomcat-10

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

16.Spring前世今生与Spring编程思想

1.1.课程目标 1、通过对本章内容的学习,可以掌握Spring的基本架构及各子模块之间的依赖关系。 2、 了解Spring的发展历史,启发思维。 3、 对 Spring形成一个整体的认识,为之后的深入学习做铺垫。 4、 通过对本章内容的学习,可以了解Spring版本升级的规律,从而应用到自己的系统升级版本命名。 5、Spring编程思想总结。 1.2.内容定位 Spring使用经验

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

Windows/macOS/Linux 安装 Redis 和 Redis Desktop Manager 可视化工具

本文所有安装都在macOS High Sierra 10.13.4进行,Windows安装相对容易些,Linux安装与macOS类似,文中会做区分讲解 1. Redis安装 1.下载Redis https://redis.io/download 把下载的源码更名为redis-4.0.9-source,我喜欢跟maven、Tomcat放在一起,就放到/Users/zhan/Documents

Linux系统稳定性的奥秘:探究其背后的机制与哲学

在计算机操作系统的世界里,Linux以其卓越的稳定性和可靠性著称,成为服务器、嵌入式系统乃至个人电脑用户的首选。那么,是什么造就了Linux如此之高的稳定性呢?本文将深入解析Linux系统稳定性的几个关键因素,揭示其背后的技术哲学与实践。 1. 开源协作的力量Linux是一个开源项目,意味着任何人都可以查看、修改和贡献其源代码。这种开放性吸引了全球成千上万的开发者参与到内核的维护与优化中,形成了