imx6ull-驱动开发篇33——platform 平台驱动模型

目录

Linux 驱动的分离与分层

驱动的分隔与分离

驱动的分层

platform 平台驱动模型

platform 总线

bus_type 结构体

platform 总线

platform_match函数

platform 驱动

platform_driver 结构体

device_driver 结构体

platform_driver_register 函数

platform_driver_unregister 函数

platform 驱动框架

platform 设备

platform_device结构体

resource结构体

platform_device_register 函数

platform_device_unregister 函数

platform 设备信息框架


Linux 驱动的分离与分层

驱动的分隔与分离

驱动的分隔,就是将主机驱动和设备驱动分隔开来,比如 I2C、 SPI 等等都会采用驱动分隔的方式来简化驱动的开发。

Linux 中的总线(bus)、驱动(driver)和设备(device)模型,也就是常说的驱动分离。

驱动的分离,是指将驱动程序中与硬件相关的部分和与硬件无关的部分分开实现。

主要分离方式

​设备与驱动分离​

  • 设备(device):描述硬件资源(如寄存器地址、中断号等)
  • 驱动(driver):包含操作硬件的具体实现
  • 通过总线(bus)将两者匹配起来

​输入子系统分离​

  • 输入核心(input core)处理通用输入逻辑
  • 输入驱动(input driver)处理具体硬件操作
  • 输入事件(input event)处理事件上报

​平台设备驱动分离​

  • 平台设备(platform_device)描述平台相关资源

  • 平台驱动(platform_driver)实现硬件操作

驱动的分层

驱动的分层,是指将驱动程序按照功能或抽象层次进行分层实现。

Linux 驱动通常可以分为以下几个主要层次:

以input(输入子系统)为例,

  • input 子系统,负责管理所有跟输入有关的驱动,包括键盘、鼠标、触摸等,
  • 最底层的就是设备原始驱动,负责获取输入设备的原始值,获取到的输入事件上报给 input 核心层。
  • input 核心层会处理各种 IO 模型,并且提供 file_operations 操作集合。
  • 在编写输入设备驱动的时候,只需要处理好输入事件的上报即可。

platform 平台驱动模型

Linux 提出了 platform 这个虚拟总线,相应的就有 platform_driver platform_device

platform 总线

Linux系统内核使用bus_type 结构体表示总线,bus_type 结构体定义在文件 include/linux/device.h。

bus_type 结构体

bus_type 结构体内容如下:

/*** struct bus_type - 总线类型结构体* * 表示Linux内核中的一条总线类型,用于管理设备与驱动的匹配和交互*/
struct bus_type {/* 总线基本信息 */const char *name;        /* 总线名称(如"pci", "usb", "platform"等) */const char *dev_name;    /* 用于设备枚举的默认名称 */struct device *dev_root; /* 总线设备的根设备 *//* 属性相关 */struct device_attribute *dev_attrs;      /* 总线设备的默认属性 */const struct attribute_group **bus_groups; /* 总线自身的属性组(在sysfs中显示) */const struct attribute_group **dev_groups; /* 总线上设备的默认属性组 */const struct attribute_group **drv_groups; /* 总线上驱动的默认属性组 *//* 核心操作函数 */int (*match)(struct device *dev, struct device_driver *drv); /* 匹配设备与驱动的关键函数,返回1表示匹配成功 */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 (*online)(struct device *dev);       /* 使设备上线 */int (*offline)(struct device *dev);      /* 使设备下线 *//* 电源管理相关 */int (*suspend)(struct device *dev, pm_message_t state); /* 挂起设备 */int (*resume)(struct device *dev);       /* 恢复设备 */const struct dev_pm_ops *pm;             /* 电源管理操作集 *//* IOMMU相关 */const struct iommu_ops *iommu_ops;       /* IOMMU操作函数集 *//* 私有数据 */struct subsys_private *p;                /* 总线私有数据,由内核内部使用 */struct lock_class_key lock_key;          /* 锁类键,用于锁调试 */
};

其中,match 函数就是完成设备和驱动之间匹配的:

  • 总线最重要的函数之一

  • 负责检查设备(device)是否可以被驱动(device_driver)支持

  • 通常通过比较设备ID和驱动支持的ID表来实现

match 函数有两个参数: dev 和 drv,这两个参数分别为 device 和 device_driver 类型,也就是设备和驱动。

platform 总线

platform 总线是 bus_type 的一个具体实例,定义在文件 drivers/base/platform.c。

platform 总线 定义如下:

/*** platform_bus_type - 平台总线类型实例* * Linux内核中用于管理平台设备(platform device)和平台驱动(platform driver)的总线类型* 平台总线用于那些不连接在传统物理总线上的SoC外设和集成设备*/
struct bus_type platform_bus_type = {.name = "platform",  /* 总线名称,在sysfs中显示为/sys/bus/platform *//* 平台设备的默认属性组 */.dev_groups = platform_dev_groups,  /* 关键操作函数:平台设备与驱动的匹配函数 */.match = platform_match,  .uevent = platform_uevent,  /* 处理平台设备的热插拔事件,生成用户空间uevent *//* 电源管理操作集 */.pm = &platform_dev_pm_ops,  };

platform_bus_type 就是 platform 平台总线,其中 platform_match 就是匹配函数。

platform_match函数

platform_match 函数 定义在文件 drivers/base/platform.c 中,函数内容如下所示:

/*** platform_match - 平台设备与驱动的匹配函数* @dev: 待匹配的设备* @drv: 待匹配的驱动** 这个函数实现了平台设备与平台驱动的匹配逻辑,按照以下优先级顺序进行匹配:* 1. 首先检查driver_override强制绑定* 2. 然后尝试设备树(OF)风格匹配* 3. 接着尝试ACPI风格匹配* 4. 再尝试ID表匹配* 5. 最后回退到名称匹配** 返回1表示匹配成功,0表示匹配失败*/
static int platform_match(struct device *dev, struct device_driver *drv)
{/* 转换为平台设备/驱动类型 */struct platform_device *pdev = to_platform_device(dev);struct platform_driver *pdrv = to_platform_driver(drv);/* * 1. 检查driver_override - 当设置了driver_override时,*    只绑定到名称完全匹配的驱动(用于强制指定驱动)*/if (pdev->driver_override)return !strcmp(pdev->driver_override, drv->name);/** 2. 首先尝试设备树(OF)风格匹配*    检查设备树节点是否与驱动中of_match_table匹配*/if (of_driver_match_device(dev, drv))return 1;/** 3. 尝试ACPI风格匹配*    检查ACPI设备ID是否与驱动中acpi_match_table匹配*/if (acpi_driver_match_device(dev, drv))return 1;/** 4. 尝试使用驱动的id_table进行匹配*    比较驱动的id_table和设备的name/id*/if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;/** 5. 最后回退到简单的名称匹配*    直接比较设备名称和驱动名称*/return (strcmp(pdev->name, drv->name) == 0);
}

驱动和设备的匹配有四种方法:

  • 设备树(OF)风格匹配:设备树中的每个设备节点的 compatible 属性会和 of_match_table 表中的所有成员比较,查看是否有相同的条目,如果有的话就表示设备和此驱动匹配,设备和驱动匹配成功以后 probe 函数就会执行。
  • ACPI风格匹配
  • ID表匹配:每个 platform_driver 结构体有一个 id_table成员变量,保存了很多 id 信息。这些 id 信息存放着这个 platformd 驱动所支持的驱动类型。
  • 名称匹配:如果第三种匹配方式的 id_table 不存在的话就直接比较驱动和设备的 name 字段,看看是不是相等,如果相等的话就匹配成功。

platform 驱动

platform_driver 结构体表示platform 驱 动 , 此结构体定义在文件include/linux/platform_device.h
中。

platform_driver 结构体

platform_driver 结构体内容如下:

/*** struct platform_driver - 平台设备驱动结构体*/
struct platform_driver {int (*probe)(struct platform_device *);      // 设备匹配成功后的初始化函数int (*remove)(struct platform_device *);     // 设备移除时的清理函数void (*shutdown)(struct platform_device *);  // 系统关机时的设备关闭函数int (*suspend)(struct platform_device *, pm_message_t state); // 设备挂起函数(传统PM)int (*resume)(struct platform_device *);     // 设备恢复函数(传统PM)struct device_driver driver;                // 内嵌的标准驱动结构(含name/owner/pm等)const struct platform_device_id *id_table;  // 驱动支持的设备ID表(传统匹配方式)bool prevent_deferred_probe;                // 是否禁止延迟探测
};
  • probe 函数,当驱动与设备匹配成功以后 probe 函数就会执行。
  • driver 成员,为 device_driver 结构体变量,相当于基类,提供了最基础的驱动框架。
  • id_table 是个表( 也就是数组) ,每个元素的类型为 platform_device_id

platform_device_id 结构体内容如下:

struct platform_device_id {char name[PLATFORM_NAME_SIZE];      /* 设备名称,最大长度为PLATFORM_NAME_SIZE(通常为20) */kernel_ulong_t driver_data;         /* 驱动私有数据,可通过platform_get_device_id()获取 */
};

device_driver 结构体

device_driver 结构体定义在 include/linux/device.h, device_driver 结构体内容如下:

/*** struct device_driver - 核心设备驱动结构体* * 表示Linux设备模型中的一个设备驱动程序*/
struct device_driver {const char *name;                /* 驱动名称,用于匹配设备 */struct bus_type *bus;            /* 所属总线类型 */struct module *owner;            /* 所属模块(THIS_MODULE) */const char *mod_name;            /* 内置模块名称 */bool suppress_bind_attrs;        /* 禁用sysfs中的bind/unbind属性 *//* 设备匹配表 */const struct of_device_id *of_match_table;  /* 设备树匹配表 */const struct acpi_device_id *acpi_match_table; /* ACPI匹配表 *//* 驱动操作函数 */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;                  /* 驱动私有数据 */
};

其中, of_match_table 就是采用设备树的时候驱动使用的匹配表,同样是数组,每个匹配项都为 of_device_id 结构体类型。

of_device_id 结构体定义在文件 include/linux/mod_devicetable.h 中,内容如下:

struct of_device_id {char name[32];          /* 传统设备名称(逐步淘汰) */char type[32];         /* 传统设备类型(逐步淘汰) */char compatible[128];  /* 设备树节点必须包含的兼容性字符串 */const void *data;      /* 传递给驱动的私有数据 */
};

对于设备树而言,就是通过设备节点的 compatible 属性值和 of_match_table 中每个项目的 compatible 成员变量进行比较,如果有相等的就表示设备和此驱动匹配成功。

在编写 platform 驱动的时候,首先定义一个 platform_driver 结构体变量,然后实现结构体中的各个成员变量,重点是实现匹配方法以及 probe 函数。当驱动和设备匹配成功以后 probe函数就会执行,具体的驱动程序在 probe 函数里面编写,比如字符设备驱动等等。

platform_driver_register 函数

当我们定义并初始化好 platform_driver 结构体变量以后,需要在驱动入口函数里面调用platform_driver_register 函数向 Linux 内核注册一个 platform 驱动。

platform_driver_register 函数原型如下所示:

int platform_driver_register (struct platform_driver *driver)
  • driver:要注册的 platform 驱动。
  • 返回值: 负数,失败; 0,成功。

platform_driver_unregister 函数

还需要在驱动卸载函数中,通过 platform_driver_unregister 函数卸载 platform 驱动, platform_driver_unregister 函数原型如下:

void platform_driver_unregister(struct platform_driver *drv)
  • drv:要卸载的 platform 驱动。
  • 返回值: 无。

platform 驱动框架

platform 驱动框架如下所示:

/* 设备结构体 */
struct xxx_dev {struct cdev cdev;/* 设备结构体其他具体内容 */
};struct xxx_dev xxxdev; /* 定义个设备结构体变量 */static int xxx_open(struct inode *inode, struct file *filp)
{/* 函数具体内容 */return 0;
}static ssize_t xxx_write(struct file *filp, const char __user *buf,size_t cnt, loff_t *offt)
{/* 函数具体内容 */return 0;
}/** 字符设备驱动操作集*/
static struct file_operations xxx_fops = {.owner = THIS_MODULE,.open = xxx_open,.write = xxx_write,
};/** platform 驱动的 probe 函数* 驱动与设备匹配成功以后此函数就会执行*/
static int xxx_probe(struct platform_device *dev)
{......cdev_init(&xxxdev.cdev, &xxx_fops); /* 注册字符设备驱动 *//* 函数具体内容 */return 0;
}static int xxx_remove(struct platform_device *dev)
{......cdev_del(&xxxdev.cdev);/* 删除 cdev *//* 函数具体内容 */return 0;
}/* 匹配列表 */
static const struct of_device_id xxx_of_match[] = {{ .compatible = "xxx-gpio" },{ /* Sentinel */ }
};/** platform 平台驱动结构体*/
static struct platform_driver xxx_driver = {.driver = {.name = "xxx",.of_match_table = xxx_of_match,},.probe = xxx_probe,.remove = xxx_remove,
};/* 驱动模块加载 */
static int __init xxxdriver_init(void)
{return platform_driver_register(&xxx_driver);
}/* 驱动模块卸载 */
static void __exit xxxdriver_exit(void)
{platform_driver_unregister(&xxx_driver);
}module_init(xxxdriver_init);
module_exit(xxxdriver_exit);
MODULE_LICENSE("GPL");

platform 驱动还是传统的字符设备驱动、块设备驱动或网络设备驱动,只是套上了一张“platform” 的皮,目的是为了使用总线、驱动和设备这个驱动模型来实现驱动的分离与分层。

platform 设备

platform_device结构体

platform_device 这个结构体表示 platform 设备,如果内核支持设备树,就是用设备树来描述设备。

platform_device 结构体定义在文件include/linux/platform_device.h 中,结构体内容如下:

/*** struct platform_device - 平台设备结构体* * 表示一个不连接在传统硬件总线上的设备(如SoC内置外设)*/
struct platform_device {const char      *name;        /* 设备名称,用于与驱动匹配 */int             id;          /* 设备实例ID(-1表示单个实例) */bool            id_auto;     /* 是否自动分配ID */struct device   dev;         /* 内嵌的标准设备结构 */u32             num_resources; /* 资源数量 */struct resource *resource;    /* 设备资源数组(内存/I/O/中断等) */const struct platform_device_id *id_entry; /* 设备ID条目(传统匹配方式) */char            *driver_override; /* 强制指定驱动名称 */struct mfd_cell *mfd_cell;    /* 如果是MFD子设备,指向父单元 */struct pdev_archdata archdata; /* 架构特定数据 */
};

其中:

  • name 表示设备名字,要和所使用的 platform 驱动的 name 字段相同,否则的话设备就无法匹配到对应的驱动。
  • num_resources 表示资源数量。
  • resource 表示资源,也就是设备信息,比如外设寄存器等。

resource结构体

Linux 内核使用 resource结构体表示资源, resource 结构体内容如下:

/*** struct resource - 硬件资源描述结构体* * 描述设备使用的硬件资源,包括内存区域、I/O端口、中断号等*/
struct resource {resource_size_t start;  /* 资源起始地址/中断号 */resource_size_t end;    /* 资源结束地址/中断号 */const char *name;       /* 资源名称(可选) */unsigned long flags;    /* 资源类型和属性标志 *//* 资源树管理指针(内核内部使用) */struct resource *parent; /* 父资源 */struct resource *sibling; /* 兄弟资源 */struct resource *child;  /* 子资源 */
};
  • start 和 end 分别表示资源的起始和终止信息,对于内存类的资源,就表示内存起始和终止地址。
  •  name 表示资源名字。
  • flags 表示资源类型。

可选的资源类型,都定义在了文件include/linux/ioport.h 里面,如下所示:

#define IORESOURCE_IO        0x00000100  /* IO端口资源 */
#define IORESOURCE_MEM       0x00000200  /* 内存区域资源 */
#define IORESOURCE_IRQ       0x00000400  /* 中断资源 */
#define IORESOURCE_DMA       0x00000800  /* DMA通道 */
#define IORESOURCE_BUSY      0x80000000  /* 资源已分配 */#define IORESOURCE_CACHEABLE 0x00000001  /* 可缓存内存 */
#define IORESOURCE_READONLY  0x00000002  /* 只读内存 */

在以前不支持设备树的Linux版本中,用户需要编写platform_device变量来描述设备信息,然后使用 platform_device_register 函数将设备信息注册到 Linux 内核中。

platform_device_register 函数

platform_device_register 函数原型如下所示:

int platform_device_register(struct platform_device *pdev)
  • pdev:要注册的 platform 设备。
  • 返回值: 负数,失败; 0,成功。

platform_device_unregister 函数

如果不再使用 platform 的话,可以通过 platform_device_unregister 函数注销掉相应的 platform设备。

 platform_device_unregister 函数原型如下

void platform_device_unregister(struct platform_device *pdev)
  • pdev:要注销的 platform 设备。
  • 返回值: 无。

platform 设备信息框架

当 Linux 内核支持了设备树以后,就不需要用户手动去注册 platform 设备了。

因为设备信息都放到了设备树中去描述, Linux 内核启动的时候会从设备树中读取设备信息,然后将其组织成 platform_device 形式,

platform 设备信息框架如下所示:

/* 寄存器地址定义*/
#define PERIPH1_REGISTER_BASE (0X20000000) /* 外设1寄存器首地址 */
#define PERIPH2_REGISTER_BASE (0X020E0068) /* 外设2寄存器首地址 */
#define REGISTER_LENGTH 4/* 资源 */
static struct resource xxx_resources[] = {[0] = {.start = PERIPH1_REGISTER_BASE,.end = (PERIPH1_REGISTER_BASE + REGISTER_LENGTH - 1),.flags = IORESOURCE_MEM,},[1] = {.start = PERIPH2_REGISTER_BASE,.end = (PERIPH2_REGISTER_BASE + REGISTER_LENGTH - 1),.flags = IORESOURCE_MEM,},
};/* platform 设备结构体 */
static struct platform_device xxxdevice = {.name = "xxx-gpio",.id = -1,.num_resources = ARRAY_SIZE(xxx_resources),.resource = xxx_resources,
};/* 设备模块加载 */
static int __init xxxdevice_init(void)
{return platform_device_register(&xxxdevice);
}/* 设备模块注销 */
static void __exit xxxdevice_exit(void)
{platform_device_unregister(&xxxdevice);
}module_init(xxxdevice_init);
module_exit(xxxdevice_exit);
MODULE_LICENSE("GPL");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93961.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93961.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Win/Linux笔记本合盖不睡眠设置指南

在 笔记本电脑上,当你合上屏幕时,默认系统可能会进入“睡眠”或“休眠”状态。如果你希望合上屏幕时系统继续正常运行(例如后台下载、运行程序、远程访问等),需要修改系统的电源设置。 一、以下是 Windows 10 / Windo…

(栈)Leetcode155最小栈+739每日温度

739. 每日温度 - 力扣(LeetCode) while要把stack的判断放在前面,否则stack[-1]可能报错 class Solution(object):def dailyTemperatures(self, temperatures):""":type temperatures: List[int]:rtype: List[int]""…

【NLP(01)】NLP(自然语言处理)基础

目录NLP基础一、基本概念1. 自然语言处理的基本介绍1.1 与语言相关的概念1.2 为什么使用NLP2. NLP的应用方向2.1 **自然语言理解**2.2 自然语言转换2.3 自然语言生成3. NLP基础概念4. NLP的发展历史5. NLP的基本流程二、NLP中的特征工程0. 引入1. 词向量2. 传统NLP中的特征工程…

Python工程师进阶学习道路分析

本文将分为以下几个核心部分: 心态与基础重塑:从“会用”到“精通”核心语言深度:窥探Python的奥秘编程范式与设计模式:写出优雅的代码并发与异步编程:释放多核时代的威力性能分析与优化:让代码飞起来深入…

IntelliJ IDEA中Maven的“Sync“与“Reload“详解:小白的避坑指南

在IntelliJ IDEA中使用Maven时,Sync All Maven Projects(同步)和 Reload All Maven Projects(重新加载)是两个最常用的操作按钮。它们看似相似,实则承担着完全不同的职责。本文将通过通俗易懂的对比和场景分…

网络地址的详细计算说明

IP地址分类与计算 IP地址分5类A类 :0开头,适用于大型网络 B类 :10开头,适用于中型网络 C类 :110开头,适用于小型网络 D类 :1110开头,用于组播 E类 : 1110开头&#xff0c…

人工智能驱动的现代电商前端开发:从基础到智能体验

引言:AI如何重塑电商体验电子商务行业正在经历一场人工智能革命。从个性化推荐到视觉搜索,从智能客服到预测分析,AI技术正在彻底改变用户与电商平台的交互方式。作为前端开发者,了解如何集成AI功能已成为必备技能。本文将带您深入…

mimic数据统计

是否能联通 psql -h 127.0.0.1 -U Shinelon-d mimic --password pgadmin建库 psql -d mimiciv -f mimic-iv/buildmimic/postgres/create.sql 也可以pgadmin直接运行create.sql 导入csv.gz数据 psql -d mimic -v ON_ERROR_STOP1 -v mimic_data_dirH:/mimic-iv-2.2 -f C:\Users\S…

孟德尔随机化小试 从软件安装数据下载到多种检验

孟德尔随机化(Mendelian Randomization, MR)作为一种利用基因数据推断因果关系的强大工具,在流行病学研究中应用广泛。本文将详细讲解MR的核心原理、完整分析流程,并附上关键代码实现,帮助你从零开始完成一次MR分析。1…

记一次:postman请求下载文件的使用方法

前言:笔者的后端接口是swagger,遇到像文件导出下载的功能就实现不了。然后使用postman工具就可以了。注:postman工具使用send下拉选项中有请求下载,如图完美解决。后续有其它方法在补充。

快速搭建项目(若依)

RuoYi-Vue 是一个 Java EE 企业级快速开发平台,低代码的框架。 1.环境要求: 其中MySQL和Redis放在服务器上或者本机上。 2.代码搭建: 代码下载地址:https://gitee.com/y_project/RuoYi-Vue,在官方文档里面可下载若依…

iOS开发之UICollectionView为什么需要配合UICollectionViewFlowLayout使用

1. UICollectionView 的职责分离UICollectionView 本质上只是一个容器,用来展示一系列的 cell(单元格)。 它本身 不关心 cell 的摆放方式,只负责:Cell 的复用(避免性能浪费)Cell 的增删改查滚动…

一、部署LNMP

一、准备环境操作系统:CentOS 7.x(最少 2 核 CPU 2GB 内存 20GB 磁盘)网络:能访问公网(用于下载包)软件版本:Nginx 1.20MySQL 5.7/8.0PHP 7.4WordPress 6.x(商城插件 WooCommerce&…

【时时三省】vectorCAST 便捷使用技巧

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 目录 1,工程的共享 2,工程的关键文件保存 2,工作环境目录下,各个文件夹的作用 1,build 和 environment 的区别 2,vcm的作用 3,tst 文件的妙用 4,配置文件的妙用 5,复制测试环境 6,vectorCAST…

TOPSIS 优劣解距离法总结

TOPSIS 优劣解距离法总结 1. 基本思想 TOPSIS(Technique for Order Preference by Similarity to Ideal Solution)方法通过计算方案与正理想解(最优值)和负理想解(最劣值)的距离,来评价方案的优…

机器学习笔试题

人工智能与机器学习单选题(50道)1. 机器学习的核心目标是:A. 通过硬编码规则解决问题 B. 从数据中自动学习模式 C. 提高计算机硬件性能 D. 优化数据库查询速度2. 以下属于监督学习任务的是:A. 聚类分析 B. 图像分类 C. 异常检测 D…

CISP-PTE之路--10文

1.TCP/UDP 工作在 OSI 哪个层? 应用层 传输层 数据链路层 表示层 答案:传输层 解析:TCP(传输控制协议)和 UDP(用户数据报协议)是 OSI 模型中传输层的核心协议,负责端到端的数据传输管理,如可靠性(TCP)、实时性(UDP)等。 2.下列哪种设备可以隔离 ARP 广播帧? …

接口性能测试工具 - JMeter

1. 下载和运行JMeter 是由 Java 语言编写的, 因此 JMeter 的使用依赖于 Java 环境 - JRE.前往 oracle 官网下载 JMeter 压缩包.Mac 用户解压完成后, 在包内的 bin 目录下运行 sh jmeter:Windows 用户直接运行 bin 目录下的 jmeter.bat:即可进入 JMeter 主页面:1.1 添加环境变量…

Go语言实战案例-数据库事务处理

在实际业务中,很多操作需要保证 要么全部成功,要么全部失败,否则可能造成数据不一致。比如:• 用户转账(A 账户扣款,B 账户加款)• 下单支付(生成订单、扣减库存、记录支付&#xff…

为何vivo做了头显,小米却选择AI眼镜

在押注下一代智能终端这件事上,手机厂商为何步调不一致?文|游勇编|周路平在手机销量和创新都陷入停滞的背景下,主流手机厂商正在探索下一代交互终端,试图寻找新的增长点。今年6月,小米发布了AI眼…