Linux驱动2_总线设备(一)

简介:

//	参考	Linux设备驱动程序(lld3)

//	实现一个简单的虚拟总线 simple bus
//		simple_bus_type为总线类型
//		simple_bus为总线设备
//	

//	simple.c 实现
#include "simple.h"

//	增加设备引用计数
static struct simple_device *simple_dev_get(struct simple_device *dev)
{
	if (dev)
		get_device(&dev->device);
	return dev;
}
//	递减设备引用计数
static void simple_dev_put(struct simple_device *dev)
{
	if (dev)
		put_device(&dev->device);

}

//	匹配设备/驱动
//		当有新设备或新驱动添加到总线时,判断是否匹配
//	调用路径:核心设备子系统->	
static int simple_device_match(struct device *dev, struct device_driver *drv)
{
	struct simple_device *sim_dev = to_simple_device(dev);
	struct simple_driver *sim_drv = to_simple_driver(drv);
	struct simple_class_id *ids = sim_drv->classes;

	if (ids)
		while (ids->class_id != SIMPLE_CLASS_END)
		{
			if (ids->class_id == sim_dev->class_id.class_id)
				return 1;
			ids++;
		}
	return 0;
}


//	添加设备/驱动
//		当simple_device_match返回true,说明device和driver匹配,通过
//		调用probe调用驱动的probe函数,初始化设备
//	调用路径:核心设备子系统->	
static int simple_device_probe(struct device *dev)
{
	int ret = 0;
	struct simple_device *sim_dev;
	struct simple_driver *sim_drv;
	sim_dev = to_simple_device(dev);
	sim_drv = to_simple_driver(dev->driver);
	simple_dev_get(sim_dev);
	if (sim_drv->probe)
		ret = sim_drv->probe(sim_dev);
	if (ret)
		simple_dev_put(sim_dev);
	return ret;
}

//	热插拔设备
//		总线上设备被热插拔
//	调用路径:核心设备子系统->	
static int simple_device_remove(struct device *dev)
{
	struct simple_device *sim_dev = to_simple_device(dev);
	struct simple_driver *sim_drv = to_simple_driver(dev->driver);
	if (sim_drv)
	{
		if (sim_drv->remove)
		{
			sim_drv->remove(sim_dev);
		}
	}

	simple_dev_put(sim_dev);
	return 0;
}

//	获取设备class id
static ssize_t simple_device_show_class_id(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct simple_device *sim_dev = to_simple_device(dev);
	sprintf(buf, "0x%x\n", sim_dev->class_id.class_id);
	return strlen(buf) + 1;
}
//	simple bus 设备属性

struct device_attribute simple_device_attrs[] = 
{
	__ATTR(class_id, S_IRUGO, simple_device_show_class_id, NULL),
	__ATTR_NULL
};

//	simple bus 总线类型
struct bus_type simple_bus_type = 
{
	.name 		= "simple",
	.match 		= simple_device_match,
	.probe 		= simple_device_probe,
	.remove 	= simple_device_remove,
	.dev_attrs 	= simple_device_attrs 
};

static void simple_bus_release(struct device *dev)
{
	return;
}

//	simple bus 总线设备
struct simple_bus simple_bus;

//	simple bus 模块初始化
static int __init simple_init(void)
{
    int ret;
    /* create /sys/bus/simple.*/
    if ((ret = bus_register(&simple_bus_type)) < 0)
    {
    	printk(KERN_ALERT "[SIMPLE] bus_register failed.\n");
    	goto err_bus_register;
    }

    simple_bus.dev.release = simple_bus_release;
    //simple_bus.dev.parent为null,表示为该总线的顶层设备
    dev_set_name(&simple_bus.dev, "simple");
    /* create /sys/devices/simple.*/
    if ((ret = device_register(&simple_bus.dev)))
    {
    	printk(KERN_ALERT "[SIMPLE] device_register failed.\n");
    	goto err_dev_register;
    }
    return ret;
err_dev_register:
	bus_unregister(&simple_bus_type);
err_bus_register:
	return ret;
}

//	simple bus 模块卸载
static void __exit simple_exit(void)
{
	device_unregister(&simple_bus.dev);
	bus_unregister(&simple_bus_type);
}

static void simple_device_release(struct device *dev)
{
	return;
}



//	注册设备
//		向simple bus注册设备
int simple_register_device(struct simple_device *dev)
{
	dev_set_name(&dev->device, dev->name);
	//设备类型为实现的simple_bus_type
	dev->device.bus 	= &simple_bus_type;
	//挂载的总线为simple_bus
	dev->device.parent 	= &simple_bus.dev; 
	dev->device.release = simple_device_release;
	return device_register(&dev->device);
}
EXPORT_SYMBOL(simple_register_device);


//	注销设备
//		从simple bus注销设备
void simple_unregister_device(struct simple_device *dev)
{
	/* 
	 *	device_unregister will do in two parts, first, remove it from all the subsystems with device_del(), 
	 *	then decrement the reference count via put_device(). If that is the final reference count,
	 *	the device will be cleaned up via device_release() above. Otherwise, the structure will stick 
	 *	around until the final reference to the device is dropped.
	 */
	device_unregister(&dev->device);
} 
EXPORT_SYMBOL(simple_unregister_device);


//	注册驱动
//		向simple bus注册驱动
int simple_register_driver(struct simple_driver *drv)
{
	int ret = 0;
	drv->driver.name= drv->name;
	drv->driver.bus = &simple_bus_type;
	ret = driver_register(&drv->driver);
	return ret;
}
EXPORT_SYMBOL(simple_register_driver);

//	注销驱动
//		从simple bus注销驱动
void simple_unregister_driver(struct simple_driver *drv)
{
	driver_unregister(&drv->driver);
}
EXPORT_SYMBOL(simple_unregister_driver);



module_init(simple_init);
module_exit(simple_exit);
MODULE_LICENSE("GPL");

//	simple.h,类型声明
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>

#ifndef _SIMPLE_BUS_H_
#define _SIMPLE_BUS_H_

#define to_simple_device(dev) container_of(dev, struct simple_device, device)
#define to_simple_driver(drv) container_of(drv, struct simple_driver, driver)
#define SIMPLE_CLASS_END  	0xffff



struct simple_class_id
{
	u16 class_id;
};

struct simple_device
{
	char *name;
	struct device device;
	struct simple_class_id class_id;
};

struct simple_driver
{
	char *name;
	struct device_driver driver;
	struct simple_class_id *classes;
	int (*probe) (struct simple_device *dev);
	/*Device removed (NULL if not a hot-plug capable driver) */
	int (*remove) (struct simple_device *dev);
};


struct simple_bus
{
	struct device dev;
};

extern int simple_register_device(struct simple_device *dev);
extern void simple_unregister_device(struct simple_device *dev);
extern int simple_register_driver(struct simple_driver *drv);
extern void simple_unregister_driver(struct simple_driver *drv);

#endif





目录
相关文章
|
2月前
|
安全 Linux 网络安全
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
100 0
Nipper 3.9.0 for Windows & Linux - 网络设备漏洞评估
|
3月前
|
数据采集 编解码 运维
一文讲完说懂 WowKey -- WowKey 是一款 Linux 类设备的命令行(CLT)运维工具
WowKey 是一款面向 Linux 类设备的命令行运维工具,支持自动登录、批量执行及标准化维护,适用于企业、团队或个人管理多台设备,显著提升运维效率与质量。
|
4月前
|
监控 Linux 开发者
理解Linux操作系统内核中物理设备驱动(phy driver)的功能。
综合来看,物理设备驱动在Linux系统中的作用是至关重要的,它通过与硬件设备的紧密配合,为上层应用提供稳定可靠的通信基础设施。开发一款优秀的物理设备驱动需要开发者具备深厚的硬件知识、熟练的编程技能以及对Linux内核架构的深入理解,以确保驱动程序能在不同的硬件平台和网络条件下都能提供最优的性能。
276 0
|
6月前
|
安全 Ubuntu Linux
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
221 0
Nipper 3.8.0 for Windows & Linux - 网络设备漏洞评估
|
7月前
|
运维 安全 Linux
试试Linux设备命令行运维工具——Wowkey
WowKey 是一款专为 Linux 设备设计的命令行运维工具,提供自动化、批量化、标准化、简单化的运维解决方案。它简单易用、高效集成且无依赖,仅需 WIS 指令剧本文件、APT 账号密码文件和 wowkey 命令即可操作。通过分离鉴权内容与执行内容,WowKey 让运维人员专注于决策,摆脱繁琐的交互与执行细节工作,大幅提升运维效率与质量。无论是健康检查、数据采集还是配置更新,WowKey 都能助您轻松应对大规模设备运维挑战。立即从官方资源了解更多信息:https://atsight.top/training。
|
7月前
|
数据采集 运维 安全
Linux设备命令行运维工具WowKey问答
WowKey 是一款用于 Linux 设备运维的工具,可通过命令行手动或自动执行指令剧本,实现批量、标准化操作,如健康检查、数据采集、配置更新等。它简单易用,只需编写 WIS 指令剧本和 APT 帐号密码表文件,学习成本极低。支持不同流派的 Linux 系统,如 RHEL、Debian、SUSE 等,只要使用通用 Shell 命令即可通吃Linux设备。
|
2月前
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
421 1
二、Linux文本处理与文件操作核心命令
|
2月前
|
Linux
linux命令—stat
`stat` 是 Linux 系统中用于查看文件或文件系统详细状态信息的命令。相比 `ls -l`,它提供更全面的信息,包括文件大小、权限、所有者、时间戳(最后访问、修改、状态变更时间)、inode 号、设备信息等。其常用选项包括 `-f` 查看文件系统状态、`-t` 以简洁格式输出、`-L` 跟踪符号链接,以及 `-c` 或 `--format` 自定义输出格式。通过这些选项,用户可以灵活获取所需信息,适用于系统调试、权限检查、磁盘管理等场景。
291 137
|
2月前
|
安全 Ubuntu Unix
一、初识 Linux 与基本命令
玩转Linux命令行,就像探索一座新城市。首先要熟悉它的“地图”,也就是/根目录下/etc(放配置)、/home(住家)这些核心区域。然后掌握几个“生存口令”:用ls看周围,cd去别处,mkdir建新房,cp/mv搬东西,再用cat或tail看文件内容。最后,别忘了随时按Tab键,它能帮你自动补全命令和路径,是提高效率的第一神器。
679 57
|
1月前
|
存储 安全 Linux
Linux卡在emergency mode怎么办?xfs_repair 命令轻松解决
Linux虚拟机遇紧急模式?别慌!多因磁盘挂载失败。本文教你通过日志定位问题,用`xfs_repair`等工具修复文件系统,三步快速恢复。掌握查日志、修磁盘、验重启,轻松应对紧急模式,保障系统稳定运行。
405 2