EtherCAT主站IGH-- 1 -- IGH之cdev.h/c文件解析

EtherCAT主站IGH-- 1 -- IGH之cdev.h/c文件解析

  • 0 预览
  • 一 该文件功能
    • `cdev.c` 文件功能函数预览
  • 二 函数功能介绍
    • `cdev.c` 中主要函数的作用
        • 1. `ec_cdev_init`
        • 2. `ec_cdev_clear`
        • 3. `eccdev_open`
        • 4. `eccdev_release`
        • 5. `eccdev_ioctl`
        • 6. `eccdev_mmap`
        • 7. `eccdev_vma_fault`
        • 8. `eccdev_vma_nopage`
  • 三 h文件翻译
  • 四 c文件翻译
  • 该文档修改记录:
  • 总结

0 预览

一 该文件功能

该文件定义了 EtherCAT 主站的字符设备驱动程序。EtherCAT 是一种实时以太网通信标准,广泛用于工业自动化控制系统。字符设备驱动程序允许用户空间程序与内核空间的 EtherCAT 主站进行交互,通过字符设备文件对 EtherCAT 主站进行操作。

该文件实现了 EtherCAT 主控设备的字符设备驱动程序。此驱动程序允许用户空间程序与 EtherCAT 主设备进行交互,主要功能包括打开设备、释放设备、处理 IO 控制命令、内存映射以及处理虚拟内存区域的缺页错误。

cdev.c 文件功能函数预览

函数功能和用途使用场景
ec_cdev_init初始化 EtherCAT 主控设备的字符设备。在应用程序启动时进行 EtherCAT 主控设备的初始化。
ec_cdev_clear清理 EtherCAT 主控设备的字符设备。在应用程序关闭或设备不再使用时进行清理操作。
eccdev_open打开字符设备文件,初始化私有数据结构。在用户空间程序需要访问设备时调用。
eccdev_release释放字符设备文件,清理私有数据结构。在用户空间程序关闭设备文件时调用。
eccdev_ioctl处理来自用户空间的 IO 控制命令。当用户空间程序发出 ioctl() 命令时调用。
eccdev_mmap处理设备文件的内存映射请求。当用户空间程序请求内存映射时调用。
eccdev_vma_fault处理虚拟内存区域的缺页错误。当内核处理缺页错误时调用(内核版本 >= 2.6.23)。
eccdev_vma_nopage处理虚拟内存区域的首次访问缺页错误。当内核处理首次访问缺页错误时调用(内核版本 < 2.6.23)。

二 函数功能介绍

cdev.c 中主要函数的作用

1. ec_cdev_init
int ec_cdev_init(ec_cdev_t *cdev, ec_master_t *master, dev_t dev_num)
{int ret;cdev->master = master;cdev_init(&cdev->cdev, &eccdev_fops);cdev->cdev.owner = THIS_MODULE;ret = cdev_add(&cdev->cdev, MKDEV(MAJOR(dev_num), master->index), 1);if (ret) {EC_MASTER_ERR(master, "Failed to add character device!\n");}return ret;
}
  • 功能和用途:初始化 EtherCAT 主控设备的字符设备。
  • 使用场景:在应用程序启动时进行 EtherCAT 主控设备的初始化。
2. ec_cdev_clear
void ec_cdev_clear(ec_cdev_t *cdev)
{cdev_del(&cdev->cdev);
}
  • 功能和用途:清理 EtherCAT 主控设备的字符设备。
  • 使用场景:在应用程序关闭或设备不再使用时进行清理操作。
3. eccdev_open
int eccdev_open(struct inode *inode, struct file *filp)
{ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);ec_cdev_priv_t *priv;priv = kmalloc(sizeof(ec_cdev_priv_t), GFP_KERNEL);if (!priv) {EC_MASTER_ERR(cdev->master, "Failed to allocate memory for private data structure.\n");return -ENOMEM;}priv->cdev = cdev;priv->ctx.writable = (filp->f_mode & FMODE_WRITE) != 0;priv->ctx.requested = 0;priv->ctx.process_data = NULL;priv->ctx.process_data_size = 0;filp->private_data = priv;#if DEBUGEC_MASTER_DBG(cdev->master, 0, "File opened.\n");
#endifreturn 0;
}
  • 功能和用途:打开字符设备文件,初始化私有数据结构。
  • 使用场景:在用户空间程序需要访问设备时调用。
4. eccdev_release
int eccdev_release(struct inode *inode, struct file *filp)
{ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;ec_master_t *master = priv->cdev->master;if (priv->ctx.requested) {ecrt_release_master(master);}if (priv->ctx.process_data) {vfree(priv->ctx.process_data);}#if DEBUGEC_MASTER_DBG(master, 0, "File closed.\n");
#endifkfree(priv);return 0;
}
  • 功能和用途:释放字符设备文件,清理私有数据结构。
  • 使用场景:在用户空间程序关闭设备文件时调用。
5. eccdev_ioctl
long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;#if DEBUGEC_MASTER_DBG(priv->cdev->master, 0,"ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x), arg = 0x%lx)\n",filp, cmd, _IOC_NR(cmd), arg);
#endifreturn ec_ioctl(priv->cdev->master, &priv->ctx, cmd, (void __user *) arg);
}
  • 功能和用途:处理来自用户空间的 IO 控制命令。
  • 使用场景:当用户空间程序发出 ioctl() 命令时调用。
6. eccdev_mmap
int eccdev_mmap(struct file *filp, struct vm_area_struct *vma)
{ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;EC_MASTER_DBG(priv->cdev->master, 1, "mmap()\n");vma->vm_ops = &eccdev_vm_ops;vma->vm_flags |= VM_DONTDUMP; /* Pages will not be swapped out */vma->vm_private_data = priv;return 0;
}
  • 功能和用途:处理设备文件的内存映射请求。
  • 使用场景:当用户空间程序请求内存映射时调用。
7. eccdev_vma_fault
#if LINUX_VERSION_CODE >= PAGE_FAULT_VERSIONstatic
#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 0, 0)
vm_fault_t
#else
int
#endif
eccdev_vma_fault(
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)struct vm_area_struct *vma,
#endifstruct vm_fault *vmf)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)struct vm_area_struct *vma = vmf->vma;
#endifunsigned long offset = vmf->pgoff << PAGE_SHIFT;ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;struct page *page;if (offset >= priv->ctx.process_data_size) {return VM_FAULT_SIGBUS;}page = vmalloc_to_page(priv->ctx.process_data + offset);if (!page) {return VM_FAULT_SIGBUS;}get_page(page);vmf->page = page;EC_MASTER_DBG(priv->cdev->master, 1, "Vma fault, virtual_address = %p,"
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))" offset = %lu, page = %p\n", (void*)vmf->address, offset, page);
#else" offset = %lu, page = %p\n", vmf->virtual_address, offset, page);
#endifreturn 0;
}
#else
  • 功能和用途:处理虚拟内存区域的缺页错误。
  • 使用场景:当内核处理缺页错误时调用(内核版本 >= 2.6.23)。
8. eccdev_vma_nopage
struct page *eccdev_vma_nopage(struct vm_area_struct *vma,unsigned long address,int *type)
{unsigned long offset;struct page *page = NOPAGE_SIGBUS;ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;ec_master_t *master = priv->cdev->master;offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);if (offset >= priv->ctx.process_data_size)return NOPAGE_SIGBUS;page = vmalloc_to_page(priv->ctx.process_data + offset);EC_MASTER_DBG(master, 1, "Nopage fault vma, address = %#lx,"" offset = %#lx, page = %p\n", address, offset, page);get_page(page);if (type)*type = VM_FAULT_MINOR;return page;
}#endif
  • 功能和用途:处理虚拟内存区域的首次访问缺页错误。
  • **使用场景

**:当内核处理首次访问缺页错误时调用(内核版本 < 2.6.23)。

三 h文件翻译

/******************************************************************************\**  $Id$**  版权所有 (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH**  本文件是 IgH EtherCAT 主站的一部分。**  IgH EtherCAT 主站是免费软件;您可以根据自由软件基金会发布的 GNU 通用公共许可证第2版的条款重新分发和/或修改它。**  IgH EtherCAT 主站的分发目的是希望它有用,但没有任何保证;甚至没有适销性或特定用途适用性的隐含保证。详情请参阅 GNU 通用公共许可证。**  您应该已经收到了与 IgH EtherCAT 主站一起提供的 GNU 通用公共许可证的副本;如果没有,请写信给自由软件基金会,地址是:51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA。**  ---**  上述许可证仅适用于源代码。使用 EtherCAT 技术和品牌仅允许在遵守 Beckhoff Automation GmbH 的工业产权和类似权利的情况下使用。*****************************************************************************//**\fileEtherCAT 主站字符设备。
*//*****************************************************************************/#ifndef __EC_CDEV_H__
#define __EC_CDEV_H__#include <linux/fs.h>
#include <linux/cdev.h>#include "globals.h"/*****************************************************************************//** EtherCAT 主站字符设备。
*/
typedef struct {ec_master_t *master; /**< 拥有该设备的主站。 */struct cdev cdev; /**< 字符设备。 */
} ec_cdev_t;/*****************************************************************************/int ec_cdev_init(ec_cdev_t *, ec_master_t *, dev_t);
void ec_cdev_clear(ec_cdev_t *);/*****************************************************************************/#endif

四 c文件翻译

/******************************************************************************\**  $Id$**  版权所有 (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH**  本文件是 IgH EtherCAT 主站的一部分。**  IgH EtherCAT 主站是免费软件;您可以根据自由软件基金会发布的 GNU 通用公共许可证第2版的条款重新分发和/或修改它。**  IgH EtherCAT 主站的分发目的是希望它有用,但没有任何保证;甚至没有适销性或特定用途适用性的隐含保证。详情请参阅 GNU 通用公共许可证。**  您应该已经收到了与 IgH EtherCAT 主站一起提供的 GNU 通用公共许可证的副本;如果没有,请写信给自由软件基金会,地址是:51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA。**  ---**  上述许可证仅适用于源代码。使用 EtherCAT 技术和品牌仅允许在遵守 Beckhoff Automation GmbH 的工业产权和类似权利的情况下使用。*****************************************************************************//**\fileEtherCAT 主站字符设备。
*//*****************************************************************************/#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>#include "cdev.h"
#include "master.h"
#include "slave_config.h"
#include "voe_handler.h"
#include "ethernet.h"
#include "ioctl.h"/** 设置为 1 以启用设备操作调试。*/
#define DEBUG 0/*****************************************************************************/static int eccdev_open(struct inode *, struct file *);
static int eccdev_release(struct inode *, struct file *);
static long eccdev_ioctl(struct file *, unsigned int, unsigned long);
static int eccdev_mmap(struct file *, struct vm_area_struct *);/** 这是 .fault 成员在 vm_operations_struct 中可用的内核版本。*/
#define PAGE_FAULT_VERSION KERNEL_VERSION(2, 6, 23)#if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION
static
#if LINUX_VERSION_CODE > KERNEL版本 (5, 0, 0)
vm_fault_t
#else
int
#endif
eccdev_vma_fault(
#if LINUX_VERSION_CODE < KERNEL版本 (4, 11, 0)struct vm_area_struct *, /**< 虚拟内存区域。 */
#endifstruct vm_fault *); /**< 错误数据。 */
#else
static struct page *eccdev_vma_nopage(struct vm_area_struct *, unsigned long, int *);
#endif/*****************************************************************************//** EtherCAT 字符设备的文件操作回调。*/
static struct file_operations eccdev_fops = {.owner          = THIS_MODULE,.open           = eccdev_open,.release        = eccdev_release,.unlocked_ioctl = eccdev_ioctl,.mmap           = eccdev_mmap
};/** 用 ecdevc_mmap() 检索到的虚拟内存区域的回调。*/
struct vm_operations_struct eccdev_vm_ops = {
#if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION.fault = eccdev_vma_fault
#else.nopage = eccdev_vma_nopage
#endif
};/*****************************************************************************//** 文件句柄的私有数据结构。*/
typedef struct {ec_cdev_t *cdev; /**< 字符设备。 */ec_ioctl_context_t ctx; /**< 上下文。 */
} ec_cdev_priv_t;/*****************************************************************************//** 构造函数。** \return 成功时返回0,否则返回<0*/
int ec_cdev_init(ec_cdev_t *cdev, /**< EtherCAT 主站字符设备。 */ec_master_t *master, /**< 父主站。 */dev_t dev_num /**< 设备号。 */)
{int ret;cdev->master = master;cdev_init(&cdev->cdev, &eccdev_fops);cdev->cdev.owner = THIS_MODULE;ret = cdev_add(&cdev->cdev,MKDEV(MAJOR(dev_num), master->index), 1);if (ret) {EC_MASTER_ERR(master, "添加字符设备失败!\n");}return ret;
}/*****************************************************************************//** 析构函数。*/
void ec_cdev_clear(ec_cdev_t *cdev /**< EtherCAT XML 设备 */)
{cdev_del(&cdev->cdev);
}/******************************************************************************* 文件操作*****************************************************************************//** 打开字符设备时调用。*/
int eccdev_open(struct inode *inode, struct file *filp)
{ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);ec_cdev_priv_t *priv;priv = kmalloc(sizeof(ec_cdev_priv_t), GFP_KERNEL);if (!priv) {EC_MASTER_ERR(cdev->master,"分配私有数据结构内存失败。\n");return -ENOMEM;}priv->cdev = cdev;priv->ctx.writable = (filp->f_mode & FMODE_WRITE) != 0;priv->ctx.requested = 0;priv->ctx.process_data = NULL;priv->ctx.process_data_size = 0;filp->private_data = priv;#if DEBUGEC_MASTER_DBG(cdev->master, 0, "文件已打开。\n");
#endifreturn 0;
}/*****************************************************************************//** 关闭字符设备时调用。*/
int eccdev_release(struct inode *inode, struct file *filp)
{ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;ec_master_t *master = priv->cdev->master;if (priv->ctx.requested) {ecrt_release_master(master);}if (priv->ctx.process_data) {vfree(priv->ctx.process_data);}#if DEBUGEC_MASTER_DBG(master, 0, "文件已关闭。\n");
#endifkfree(priv);return 0;
}/*****************************************************************************//** 发出 ioctl() 命令时调用。*/
long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;#if DEBUGEC_MASTER_DBG(priv->cdev->master, 0,"ioctl(filp = 0x%p, cmd = 0x%08x (0x%02x), arg = 0x%lx)\n",filp, cmd, _IOC_NR(cmd), arg);
#endifreturn ec_ioctl(priv->cdev->master, &priv->ctx, cmd, (void __user *) arg);
}/*****************************************************************************/#ifndef VM_DONTDUMP
/** VM_RESERVED 在 3.7 中消失。*/
#define VM_DONTDUMP VM_RESERVED
#endif/** EtherCAT 字符设备的内存映射回调。** 实际映射将在虚拟内存区域的 eccdev_vma_nopage() 回调中完成。** \return 总是返回零(成功)。*/
int eccdev_mmap(struct file *filp,struct vm_area_struct *vma)
{ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data;EC_MASTER_DBG(priv->cdev->master, 1, "mmap()\n");vma->vm_ops = &eccdev_vm_ops;vma->vm_flags |= VM_DONTDUMP; /* 页面不会被换出 */vma->vm_private_data = priv;return 0;
}/*****************************************************************************/#if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION/** 虚拟内存区域的页面错误回调。** 在首次访问使用 ecdev_mmap() 检索到的虚拟内存区域时调用。** \return 成功时返回零,否则返回负错误代码。*/
static
#if LINUX_VERSION_CODE > KERNEL版本 (5, 0, 0)
vm_fault_t
#else
int
#endif
eccdev_vma_fault(
#if LINUX_VERSION_CODE < KERNEL版本 (4, 11, 0)struct vm_area_struct *vma, /**< 虚拟内存区域。 */
#endifstruct vm_fault *vmf /**< 错误数据。 */)
{
#if LINUX版本_CODE >= KERNEL版本 (4, 11, 0)struct vm_area_struct *vma = vmf->vma;
#endifunsigned long offset = vmf->pgoff << PAGE_SHIFT;ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;struct page *page;if (offset >= priv->ctx.process_data_size) {return VM_FAULT_SIGBUS;}page = vmalloc_to_page(priv->ctx.process_data + offset);if (!page) {return VM_FAULT_SIGBUS;}get_page(page);vmf->page = page;EC_MASTER_DBG(priv->cdev->master, 1, "虚拟内存区域错误,虚拟地址 = %p,"
#if (LINUX_VERSION_CODE >= KERNEL版本 (4,10,0))" 偏移量 = %lu, 页面 = %p\n", (void*)vmf->address, offset, page);
#else" 偏移量 = %lu, 页面 = %p\n", vmf->virtual_address, offset, page);
#endifreturn 0;
}#else/** 虚拟内存区域的无页回调。** 在首次访问使用 ecdev_mmap() 检索到的虚拟内存区域时调用。*/
struct page *eccdev_vma_nopage(struct vm_area_struct *vma, /**< 内核初始化的虚拟内存区域。 */unsigned long address, /**< 请求的虚拟地址。 */int *type /**< 类型输出参数。 */)
{unsigned long offset;struct page *page = NOPAGE_SIGBUS;ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;ec_master_t *master = priv->cdev->master;offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);if (offset >= priv->ctx.process_data_size)return NOPAGE_SIGBUS;page = vmalloc_to_page(priv->ctx.process_data + offset);EC_MASTER_DBG(master, 1, "无页错误 vma,地址 = %#lx,"" 偏移量 = %#lx, 页面 = %p\n", address, offset, page);get_page(page);if (type)*type = VM_FAULT_MINOR;return page;
}#endif/*****************************************************************************/

该文档修改记录:

修改时间修改说明
2024年6月29日EtherCAT主站IGH 该 文件解析

总结

以上就是EtherCAT主站IGH文件解析的内容。
有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。
创作不容,如果文档对您有帮助,记得给个赞。

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

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

相关文章

批处理脚本参数传递:掌握命令行的艺术

批处理脚本参数传递&#xff1a;掌握命令行的艺术 批处理脚本&#xff08;Batch Script&#xff09;是Windows操作系统中一种自动化执行任务的脚本文件&#xff0c;通常以.bat或.cmd为文件扩展名。在编写批处理脚本时&#xff0c;我们经常需要从命令行接收参数以提供更大的灵活…

【Android面试八股文】说一说ListView卡顿的原因以及相对应的优化策略

文章目录 一、ListView卡顿的原因1.1 Item没有复用1.2 布局的层级过深1.3 数据绑定逻辑过多1.4 滑动时不必要的图片刷新1.5 频繁的notifyDataSetChanged二、优化策略2.1 使用 ViewHolder 进行视图复用2.2 优化布局结构2.3 优化数据绑定逻辑过多2.4 图片加载优化2.5 避免频繁调用…

电机故障检测系统的通用性限制分析

电机故障检测系统因应用环境、功能需求、经济性等多方面差异而难以实现通用。工厂与实验室在环境条件、使用频率、功能需求、成本、维护及数据处理方面有显著不同&#xff0c;此外&#xff0c;LabVIEW软件在两者中的应用和数据处理也存在差异&#xff0c;这进一步限制了系统的通…

一个实例配置多个服务名

更改参数实现配置多个服务名 需求背景 在做案例模拟的时候发现博主的环境配置的是3个服务名&#xff0c;通常都是一个服务名&#xff0c;服务名就是数据库名&#xff0c;出于好奇进行了以下实验。 环境&#xff1a;Oracle 11.2.0.4 单点 配置多个服务名的意义 可以通过服务…

数组方法总结

创建数组的方法 Array.of(): 创建包含所有传入参数的数组。Array.from(): 从类数组或可迭代对象创建数组。 let arr1 Array.of(1, 2, 3); // [1, 2, 3] let arr2 Array.from(hello); // [h, e, l, l, o]添加/删除元素 push(): 在数组末尾添加一个或多个元素&#xff0c;返…

YOLOv8/v10项目使用教程

根据改好的YOLOv8.yaml改yolov10.yaml教程 打开ultralytics/cfg/models/v8路径&#xff0c;找到需要移植的yaml文件&#xff0c;从其中复制相关的模块。打开一个YOLOv10的yaml文件。 注释掉之前相应位置的模块&#xff0c;并粘贴上面复制的模块&#xff0c;完成。 其余使用步骤…

云原生面试

云原生面试 Kubernetes原理Kubernetes 如何保证集群的安全性。简述 Kubernetes 准入机制简述Kubernetes Secret 有哪些使用方式简述Kubernetes PodSecurityPolicy机制简述Kubernetes PodSecurityPolicy机制能实现哪些安全策略简述Kubernetes 网络策略原理简述Kubernetes 数据持…

基于SpringBoot+Vue的美容美发在线预约系统的设计与实现【附源码】

毕业设计(论文) 题目&#xff1a;基于SpringBootVue的美容美发在线预约系统的设计与实现 二级学院&#xff1a; 专业(方向)&#xff1a; 班 级&#xff1a; 学 生&#xff1a; 指导教师&#xff…

072、对象的创建与调用方法

071、Python 类的定义 当我们定义好一个类后&#xff0c;肯定是为了使用其中的功能来解决某些问题的&#xff0c;那么如何使用呢&#xff1f; 首先就是需要通过类创建对象&#xff0c;也就是类的实例化&#xff08;只有实例化后的对象才能够调用里面的属性和方法&#xff09;…

Go 语言学习笔记之通道 Channel

Go 语言学习笔记之通道 Channel 大家好&#xff0c;我是码农先森。 概念 Go 语言中的通道&#xff08;channel&#xff09;是用来在 Go 协程之间传递数据的一种通信机制。 通道可以避免多个协程直接共享内存&#xff0c;避免数据竞争和锁的使用&#xff0c;从而简化了并发程…

【解决方案】Mysql 数据库千万数据插入脚本

一.背景 要做数据模拟&#xff0c;需要在测试环境创建7千万的流水数据&#xff0c;进行迁移的模拟动作。 二.具体代码 private static final String DB_URL "jdbc:mysql://IP:3306/twallet_dev?zeroDateTimeBehaviorconvertToNull&allowMultiQueriestrue&useAf…

《Mybatis-Plus》系列文章目录

什么是 MyBatis-Plus&#xff1f; Mybatis-Plus是一个在MyBatis基础上进行增强和扩展的开源Java持久层框架。 Mybatis-Plus&#xff08;简称MP&#xff09;旨在简化开发、提高效率&#xff0c;通过提供一系列便捷的功能和工具&#xff0c;大幅度减少开发人员编写重复代码的时…

element-ui 下拉菜单el-dropdown-item添加点击事件

使用element-ui下拉菜单组件Dropdown时绑定点击事件&#xff0c;事件不生效。 click 常见于其用在Vue中的事件绑定&#xff0c;而实际上是 v-on 的简写&#xff0c;而 v-on 则是对 vue 的事件体系封装之后的 API接口。 native修饰符用于处理DOM原生事件&#xff0c;由于组件 …

如何在web页面下做自动化测试?

自动化测试是在软件开发中非常重要的一环&#xff0c;它可以提高测试效率并减少错误率。在web页面下进行自动化测试&#xff0c;可以帮助我们验证网页的功能和交互&#xff0c;并确保它们在不同浏览器和平台上的一致性。本文将从零开始&#xff0c;详细介绍如何在web页面下进行…

10--7层负载均衡集群

前言&#xff1a;动静分离&#xff0c;资源分离都是在7层负载均衡完成的&#xff0c;此处常被与四层负载均衡比较&#xff0c;本章这里使用haproxy与nginx进行负载均衡总结演示。 1、基础概念详解 1.1、负载均衡 4层负载均衡和7层负载均衡是两种常见的负载均衡技术&#xff…

PHP 语言特定指南

PHP 语言特定指南 本指南将教您如何使用 Docker 创建容器化的 PHP 应用程序。通过本指南&#xff0c;您将学习如何&#xff1a; 容器化并运行一个 PHP 应用程序设置用于开发 PHP 应用程序的本地环境在容器内运行 PHP 应用程序的测试使用 GitHub Actions 配置容器化 PHP 应用程…

vite+vue3+ts项目搭建流程 (pnpm, eslint, prettier, stylint, husky,commitlint )

vitevue3ts项目搭建 项目搭建项目目录结构 项目配置自动打开项目eslint①vue3环境代码校验插件②修改.eslintrc.cjs配置文件③.eslintignore忽略文件④运行脚本 prettier①安装依赖包②.prettierrc添加规则③.prettierignore忽略文件④运行脚本 stylint①.stylelintrc.cjs配置文…

前端自动化

前端自动化的内容 自动化代码检查自动化测试自动化构建自动化部署自动化文档 前端自动化的最佳实践

基于改进YOLOv5的安全帽检测算法 | 引入Ghost卷积 + 添加CA注意力机制 + 更换Neck网络之BiFPN + 更换损失函数之WIoU

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。为了解决建筑工地、隧道、煤矿等施工场景中现有安全帽检测算法对于小目标、密集目标以及复杂环境下的检测精度低的问题&#xff0c;设计实现了一种基于YOLOv5的改进目标检测算法&#xff0c;记为YOLOv5-GBCW。首先使用Ghos…

心理健康测试系统设计

心理健康测试系统设计需要综合考虑多个方面&#xff0c;以确保系统的准确性、易用性和有效性。以下是一个心理健康测试系统设计方案&#xff1a; 一、设计目标 准确性&#xff1a;确保测试结果能够准确反映被测者的心理健康状况。 易用性&#xff1a;设计简洁明了的界面和操作…