《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使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

Linux Mint Xia 22.1重磅发布: 重要更新一览

《LinuxMintXia22.1重磅发布:重要更新一览》Beta版LinuxMint“Xia”22.1发布,新版本基于Ubuntu24.04,内核版本为Linux6.8,这... linux Mint 22.1「Xia」正式发布啦!这次更新带来了诸多优化和改进,进一步巩固了 Mint 在 Linux 桌面

LinuxMint怎么安装? Linux Mint22下载安装图文教程

《LinuxMint怎么安装?LinuxMint22下载安装图文教程》LinuxMint22发布以后,有很多新功能,很多朋友想要下载并安装,该怎么操作呢?下面我们就来看看详细安装指南... linux Mint 是一款基于 Ubuntu 的流行发行版,凭借其现代、精致、易于使用的特性,深受小伙伴们所喜爱。对

什么是 Linux Mint? 适合初学者体验的桌面操作系统

《什么是LinuxMint?适合初学者体验的桌面操作系统》今天带你全面了解LinuxMint,包括它的历史、功能、版本以及独特亮点,话不多说,马上开始吧... linux Mint 是一款基于 Ubuntu 和 Debian 的知名发行版,它的用户体验非常友好,深受广大 Linux 爱好者和日常用户的青睐,

Linux(Centos7)安装Mysql/Redis/MinIO方式

《Linux(Centos7)安装Mysql/Redis/MinIO方式》文章总结:介绍了如何安装MySQL和Redis,以及如何配置它们为开机自启,还详细讲解了如何安装MinIO,包括配置Syste... 目录安装mysql安装Redis安装MinIO总结安装Mysql安装Redis搜索Red

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

Linux磁盘分区、格式化和挂载方式

《Linux磁盘分区、格式化和挂载方式》本文详细介绍了Linux系统中磁盘分区、格式化和挂载的基本操作步骤和命令,包括MBR和GPT分区表的区别、fdisk和gdisk命令的使用、常见的文件系统格式以... 目录一、磁盘分区表分类二、fdisk命令创建分区1、交互式的命令2、分区主分区3、创建扩展分区,然后