EtherCAT 开源主站 IGH 在 linux 开发板的移植和伺服通信测试

手边有一套正点原子linux开发板imax6ul,一直在吃灰,周末业余时间无聊,把EtherCAT的开源IGH主站移植到开发板上玩玩儿,搞点事情做。顺便学习研究下EtherCAT总线协议及其对伺服驱动器的运动控制过程。实验很有意思,这里总结下实验过程,分享给有需要的小伙伴。

前言

igh EtherCAT Master是一个用于控制EtherCAT网络的软件模块,它提供了主站功能。主站负责与从站进行通信和同步,控制从站的操作。igh EtherCAT Master具有丰富的功能和灵活的配置选项,可以满足不同应用场景的需求。它提供了一系列的API和工具,使得开发者可以方便地进行EtherCAT网络的开发和调试。

igh EtherCAT Master是用的最多且实时性最好的 EtherCAT 开源主站。很多公司项目软件主站都是用的它,有很多软件专利可以挖掘。一些公司的机器人主控四肢电机驱动器通信和运动板卡,采用的也是IgH 。基于IgH作产品开发,基本能满足大部分使用场景。

关于EtherCAT主站协议栈,目前有两大主流开源代码为SOEM(即支持Linux,又支持windows )和IgH EtherCAT Master只支持Linux )。

本文以IgH最新稳定版本1.6来移植,简单记录下IgH EtherCAT Master在嵌入式系统中的移植过程及主从站伺服驱动器通信测试。( [Linux 内核版本:Linux-4.1.15] )。

IgH官方介绍:

EtherCAT-Master | EtherLab

整个交叉编译过程很顺利,没遇到一点儿报错。本次移植仅是测试,简单起见使用通用的网卡驱动,性能上肯定不是最好。要想高性能一方面需要给内核打实时性补丁,一方面还需对特定的网卡驱动进行优化适配。源码里自带了一些网卡驱动,如8139和e1000网卡驱动,Igb(Intel Gigabit )以太网驱动程序。

8139和e1000是两种常见的网卡芯片,分别由Realtek和Intel生产。Realtek 8139(也称为RTL8139)是Realtek生产的一款常用的乙太网网卡芯片,广泛应用于早期的计算机和嵌入式系统中。Intel e1000系列是Intel生产的一组高性能千兆位乙太网控制器芯片,包括e1000、e1000e和82574等型号,适用于桌面计算机、服务器和嵌入式系统。这两种网卡芯片均具有集成的MAC(Media Access Control)功能,用于管理数据链路层的访问和控制,以及PHY(Physical Layer)功能,用于处理物理层的信号传输和解调。它们同时具备MAC和PHY功能。

移植准备

IGH最新稳定版1.6源码下载地址:

https://gitlab.com/etherlab.org/ethercat/-/archive/stable-1.6/ethercat-stable-1.6.tar.gz

准备Linux-4.1.15内核源码,(编译驱动模块需要) 我的路径:

/root/test/imax6ul/linux

开发板提供的gcc交叉编译工具链:

/opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

如果还想要给内核打上实时性补丁包,可以在这找到:Index of /pub/linux/kernel/projects/rt/4.14/

#为内核源码打上实时补丁
cd linux
patch -p 1 -i ../patch-4.10.199-rt97.patch

至此,准备工作完成。 

源码编译过程

先加载编译环境变量,直接执行以下指令即可。

source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

执行完成后, arm-poky-linux-gnueabi-gcc已经加入到环境变量中了。可以在命令行输出echo $CC试试看,输出了arm-poky-linux-gnueabi-gcc,说明环境已经生效了。

 编译主站程序和协议栈

# EtherCAT 源码存放目录为:/root/test/ethercat/ethercat-stable-1.6
# Linux-4.1.15 源码存放目录为:/root/test/imax6ul/linux/ linux-4.1.15tar -zxvf ethercat-stable-1.6.tar.gz	# 解压源码 /root/test/ethercat/ethercat-stable-1.6
cd ethercat-stable-1.6# --prefix是指定你下面make install时的安装目录,--with-linux-dir是指定你的linux内核目录
./configure --prefix=/root/test/ethercat/output --with-linux-dir=/root/test/imax6ul/linux --enable-8139too=no --enable-generic=yes --host=arm-poky-linux-gnueabimake	# 编译主站和协议栈源码make install #安装到指定目录

经过上面的交叉编译,只是编译出了主站协议栈库和自带主站工具及程序,但是这还不算完。

ethercat:可执行程序是用于配置和管理 EtherCAT 主站(IGH 主站)的命令行工具。

ethercatctl:是一个用于控制 EtherCAT Master 运行状态的命令行工具。它提供了启动、停止、重启 EtherCAT Master 等操作的命令,用于管理 EtherCAT Master 的运行。

经过上面的编译,编译出来的内容如下图所示:

库和头文件: 

linux内核驱动模块还没出来,所以直接是运行不起来的,还需要编译出内核网络驱动模块。

编译内核驱动模块

#编译网卡驱动模块
# 指定交叉编译工具,编译modules
make ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- modules 		# 编译通过会对应生成ethercat-stable-1.6/devices/ec_generic.ko和ethercat-stable-1.6/master/ec_master.ko
sudo make install		# 在该目录下生成output目录

成功编译出了ec_master.ko 和 ec_generic.ko的linux驱动模块。 

ec_master.ko:用于支持 EtherCAT 主站运行的 Linux 内核模块。它实现了 EtherCAT 主站协议栈,允许在 Linux 系统上与 EtherCAT 从站设备进行实时通信和数据交换。主要负责存储一些ethercat从站信息,管理domains域,管理从站配置等有关于ethercat系统的资源,在/etc/sysconfig/ethercat中配置的MASTER0_DEVICE会作为该模块参数传入主站模块,最终成为主站模块的mac使用网络地址,即master->macs;

ec_generic.ko,经由系统网络栈利用标准以太网 (Ethernet) 的网络驱动程序。

ec_generic,这个通用的驱动文件是在TCP/IP协议栈接口之上进行调用的,所以会走TCP/IP协议栈,会影响实时性。正式用应优化网卡驱动,在网卡驱动上直接支持IgH接口。

放到板子上运行

复制ec_generic.ko和ec_master.ko到/lib/modules/内核版本号,复制ethercat到usr/local/bin目录下。安装通用网卡驱动,配置rules,创建设备号。

操作步骤

# 在/root/test/ethercat目录下创建modules文件夹,并复制ec_generic.ko和ec_master.ko到modules下
mkdir -p output/modules
cp devices/ec_generic.ko output/modules/
cp master/ec_master.ko output/modules/# 将output文件夹打包,传输到开发板(nfs/tftp/scp)
tar -cjf output.tar.bz2 output/-------------------------------------------------------------------------------------------------------------------------------------
# 开发板上执行
tar -jxvf output.tar.bz2cp output/modules/ec_generic.ko /lib/modules/4.1.15
# 复制ec_master.ko到/lib/modules/内核版本号/ 
cp output/modules/ec_master.ko /lib/modules/4.1.15 # 内核版本可以通过uname -r 查看depmodln -fs output/etc/init.d/ethercat /etc/init.d/ # 创建链接,相比于复制节省内存空间
ln -fs output/bin/ethercat /usr/local/bin/mkdir /etc/sysconfig
ln -fs output/etc/sysconfig/ethercat /etc/sysconfig/# 配置rules,创建设备号
echo KERNEL==\"EtherCAT[0-9]*\", MODE=\"0664\" > /etc/udev/rules.d/99-EtherCAT.rules# 获取板子MAC地址
ifconfig
# eth2  Link encap:以太网  硬件地址 00:0c:29:01:69:aa-------------------------------------------------------------------------------------------------------------------------------------
# 启动EtherCAT
# 配置主站的MAC地址
modprobe ec_master main_devices=1E:ED:19:27:1A:B3 # 启动ethercat
/etc/init.d/ethercat start# 安装通用网卡驱动
insmod  output/modules/ec_generic.ko# 通过ethercat查看信息
Ethercat --help

运行测试

通过网线直连ethercat主从站,从站启动完成后,启动ethercat。

/etc/init.d/ethercat start

下面就可以使用 ethercat 工具来进行一些操作了。

sudo ethercat cstruct

ethercat 命令行

EtherCAT 命令行在 《EtherCAT IGH 1.52.pdf》中的 <7.1 Command-line Tool> 也有很详细的一个介绍。在编译和安装IGH的时候,如果不修改默认的编译参数,那么就是会提供 EtherCAT 命令行工具的。每个主站的实例都有生成一个字符设备,名字为:/dev/EtherCATx, 其中 x ∈ {0 . . . n}为主站实例的索引。

常用命令介绍

ethercat master

该命令行用来显示主站和以太网设备信息。

列出主站状态:

ethercat slaves

列出连接的从站:

ethercat cstruct
ethercat sdos

该命令行用来输出当前驱动器支持的所有的SDO信息。

举例:

@:~$ ethercat upload 0x2001 0x0000
0x03e8 1000

解析:读取从站0中索引号为 0x2001(16位),子索引号为00(8位)的SDO条目。返回的参数值为 1000。

注意:必须有从站连接才能使用此命令,不运行应用程序也可以使用。

 ethercat download

该命令行用以向指定的从站 SDO 中的子索引中写入相应的参数值。

例子:

向从站0的索引号为0x6060(16位),子索引号为00(8位)的地址写入参数值"0x08"。

@:~$ sudo ethercat download -t int16 -p 0 0x6060 00 08

有的SDO 可能是由于厂家的限制,不能写入参数。

@:~$ sudo ethercat download -t uint16 0x2008 0x0000 0x000f
SDO transfer aborted with code 0x08000021: Data cannot be transferred or stored to the application because of local control

注意:必须有从站连接才能使用此命令,不运行应用程序也可以使用。 

@:~$ ethercat sdos
SDO 0x1000, "Device type"0x1000:00, r-r-r-, uint32, 32 bit, "Device type"
SDO 0x1001, "Error register"0x1001:00, r-r-r-, uint8, 8 bit, "Error register"
SDO 0x1008, "Device name"0x1008:00, r-r-r-, string, 72 bit, "Device name"
SDO 0x1009, "Hardware version"0x1009:00, r-r-r-, string, 24 bit, "Hardware version"
SDO 0x100a, "Software version"0x100a:00, r-r-r-, string, 32 bit, "Software version"
SDO 0x1010, "store parameters"0x1010:00, r-r-r-, uint8, 8 bit, "SubIndex 000"0x1010:01, rwrwrw, uint32, 32 bit, "save all parameters"0x1010:02, rwrwrw, uint32, 32 bit, "save communication parameters"0x1010:03, rwrwrw, uint32, 32 bit, "save application parameters"0x1010:04, rwrwrw, uint32, 32 bit, "save manufacturer defined parameters"
..............
SDO 0x6007, "Abort_connection_option_code"0x6007:00, rwrwrw, int16, 16 bit, "Abort_connection_option_code"
SDO 0x603f, "errorcode"0x603f:00, r-r-r-, uint16, 16 bit, "errorcode"
SDO 0x6040, "controlword"0x6040:00, rwrwrw, uint16, 16 bit, "controlword"
SDO 0x6041, "statusword"0x6041:00, r-r-r-, uint16, 16 bit, "statusword"
..............
ethercat pdos

该命令行用来显示出同步管理器的参数和PDO分配和映射信息。

ethercat upload

该命令行用以读取指定从站相应PDO设定的参数值。

其他一些命令,参考:EtherCAT IGH 命令行介绍_igh ethercat-CSDN博客

@:~$ ethercat --helpalias      Write alias addresses.config     Show slave configurations.crc        CRC error register diagnosis.cstruct    Generate slave PDO information in C language.data       Output binary domain process data.debug      Set the master's debug level.domains    Show configured domains.download   Write an SDO entry to a slave.eoe        Display Ethernet over EtherCAT statictics.foe_read   Read a file from a slave via FoE.foe_write  Store a file on a slave via FoE.graph      Output the bus topology as a graph.ip         Set EoE IP parameters.master     Show master and Ethernet device information.pdos       List Sync managers, PDO assignment and mapping.reg_read   Output a slave's register contents.reg_write  Write data to a slave's registers.rescan     Rescan the bus.sdos       List SDO dictionaries.sii_read   Output a slave's SII contents.sii_write  Write SII contents to a slave.slaves     Display slaves on the bus.soe_read   Read an SoE IDN from a slave.soe_write  Write an SoE IDN to a slave.states     Request application-layer states.upload     Read an SDO entry from a slave.version    Show version information.xml        Generate slave information XML.Global options:--master  -m <master>  Comma separated list of mastersto select, ranges are allowed.Examples: '1,3', '5-7,9', '-3'.Default: '-' (all).--force   -f           Force a command.--quiet   -q           Output less information.--verbose -v           Output more information.--help    -h           Show this help.Numerical values can be specified either with decimal (no
prefix), octal (prefix '0') or hexadecimal (prefix '0x') base.Call 'ethercat <COMMAND> --help' for command-specific help.

测试效果

网上有一组测试效果,连接五个从站,主站单次收发数据的平均耗时以及实时性。测试主站单次收发数据的平均耗时的程序每隔 100 μs 发送并接收一次过程数据,如此每循环 10000 次记录一下当前时间,相邻两次记录的时间间隔减去其间空闲时间 100 μs × 10000 = 1 s 再除以收发次数 10000 便得到单次收发数据的平均耗时,使用三种不同的网卡驱动,三种情形下的大致结果如下表:

主站测试代码

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>/****************************************************************************/#include "ecrt.h"/****************************************************************************/// Application parameters
#define FREQUENCY 100
#define PRIORITY 1// Optional features
#define CONFIGURE_PDOS  1/****************************************************************************/// EtherCAT
static ec_master_t *master = NULL;
static ec_master_state_t master_state = {};static ec_domain_t *domain1 = NULL;
static ec_domain_state_t domain1_state = {};
static ec_domain_t *domain2 = NULL;
static ec_domain_state_t domain2_state = {};static ec_slave_config_t *sc;
static ec_slave_config_state_t sc_ana_in_state = {};// Timer
static unsigned int sig_alarms = 0;
static unsigned int user_alarms = 0;/****************************************************************************/// process data
static uint8_t *domain1_pd = NULL;
static uint8_t *domain2_pd = NULL;#define BusCouplerPos  0, 0#define TI_AM3359ICE    0xE000059D, 0x54490001// offsets for PDO entries
static unsigned int off_dig_out2;
static unsigned int off_dig_in2;static unsigned int counter = 0;
static unsigned int blink = 0x00;/*****************************************************************************/#if CONFIGURE_PDOS
ec_pdo_entry_info_t slave_0_pdo_entries[] = {{0x7010, 0x00, 32},{0x6000, 0x00, 4*8},
};
ec_pdo_info_t slave_0_pdos[] = {{0x1601, 1, slave_0_pdo_entries + 0},{0x1a00, 1, slave_0_pdo_entries + 1},
};
static ec_sync_info_t slave_0_pdo_syncs[] = {{2, EC_DIR_OUTPUT, 1, slave_0_pdos + 0},{3, EC_DIR_INPUT,  1, slave_0_pdos + 1},{0xff}
};#endif/*****************************************************************************/void check_domain1_state(void)
{ec_domain_state_t ds;ecrt_domain_state(domain1, &ds);if (ds.working_counter != domain1_state.working_counter)printf("Domain1: WC %u.\n", ds.working_counter);if (ds.wc_state != domain1_state.wc_state)printf("Domain1: State %u.\n", ds.wc_state);domain1_state = ds;
}/*****************************************************************************/
void check_domain2_state(void)
{ec_domain_state_t ds;ecrt_domain_state(domain2, &ds);if (ds.working_counter != domain2_state.working_counter)printf("Domain2: WC %u.\n", ds.working_counter);if (ds.wc_state != domain2_state.wc_state)printf("Domain2: State %u.\n", ds.wc_state);domain2_state = ds;
}/*****************************************************************************/void check_master_state(void)
{ec_master_state_t ms;ecrt_master_state(master, &ms);if (ms.slaves_responding != master_state.slaves_responding)printf("%u slave(s).\n", ms.slaves_responding);if (ms.al_states != master_state.al_states)printf("AL states: 0x%02X.\n", ms.al_states);if (ms.link_up != master_state.link_up)printf("Link is %s.\n", ms.link_up ? "up" : "down");master_state = ms;
}/*****************************************************************************/void check_slave_config_states(void)
{ec_slave_config_state_t s;ecrt_slave_config_state(sc, &s);if (s.al_state != sc_ana_in_state.al_state)printf("AnaIn: State 0x%02X.\n", s.al_state);if (s.online != sc_ana_in_state.online)printf("AnaIn: %s.\n", s.online ? "online" : "offline");if (s.operational != sc_ana_in_state.operational)printf("AnaIn: %soperational.\n",s.operational ? "" : "Not ");sc_ana_in_state = s;
}/*****************************************************************************/void cyclic_task()
{// receive process dataecrt_master_receive(master);ecrt_domain_process(domain1);ecrt_domain_process(domain2);// check process data state (optional)check_domain1_state();check_domain2_state();//    if (counter) {
//        counter--;
//    } else { // do this at 1 Hzcounter = FREQUENCY;// calculate new process datablink ++;// check for master state (optional)check_master_state();// check for islave configuration state(s) (optional)check_slave_config_states();//	printf("AnaIn: value=0x%x\n", EC_READ_U32(domain2_pd + off_dig_in2));printf("AnaIn: value=0x%x\n", EC_READ_U32(domain2_pd + off_dig_in2));
//printf("AnaIn: value=0x%x\n", EC_READ_U32(domain2_pd + off_dig_in2 + 4));EC_WRITE_U32(domain1_pd + off_dig_out2, blink);
//		printf("AnaIn: value=0x%x\n", EC_READ_U32(domain1_pd + off_dig_out2));
//    }// send process dataecrt_domain_queue(domain1);ecrt_domain_queue(domain2);ecrt_master_send(master);
}/****************************************************************************/void signal_handler(int signum) {switch (signum) {case SIGALRM:sig_alarms++;break;}
}/****************************************************************************/int main(int argc, char **argv)
{struct sigaction sa;struct itimerval tv;master = ecrt_request_master(0);if (!master)return -1;domain1 = ecrt_master_create_domain(master);if (!domain1)return -1;domain2 = ecrt_master_create_domain(master);if (!domain2)return -1;#if CONFIGURE_PDOSif (!(sc = ecrt_master_slave_config(master, BusCouplerPos, TI_AM3359ICE))) {fprintf(stderr, "Failed to get slave configuration.\n");return -1;}if (ecrt_slave_config_pdos(sc, EC_END, slave_0_pdo_syncs)) {fprintf(stderr, "Failed to configure PDOs.\n");return -1;}printf("Configuring PDOs...\n");// Create configuration for bus coupleroff_dig_out2 = ecrt_slave_config_reg_pdo_entry(sc,0x7010, 0, domain1, NULL);if (off_dig_out2 < 0)return -1;off_dig_in2 = ecrt_slave_config_reg_pdo_entry(sc,0x6000, 0, domain2, NULL);if (off_dig_in2 < 0)return -1; 
#endifprintf("Activating master...\n");if (ecrt_master_activate(master))return -1;if (!(domain1_pd = ecrt_domain_data(domain1))) {return -1;}if (!(domain2_pd = ecrt_domain_data(domain2))) {return -1;}sa.sa_handler = signal_handler;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;if (sigaction(SIGALRM, &sa, 0)) {fprintf(stderr, "Failed to install signal handler!\n");return -1;}printf("Starting timer...\n");tv.it_interval.tv_sec = 0;tv.it_interval.tv_usec = 1000000 / FREQUENCY;tv.it_value.tv_sec = 0;tv.it_value.tv_usec = 2000;if (setitimer(ITIMER_REAL, &tv, NULL)) {fprintf(stderr, "Failed to start timer: %s\n", strerror(errno));return 1;}printf("Started.\n");while (1) {pause();while (sig_alarms != user_alarms) {cyclic_task();user_alarms++;}}return 0;
}/****************************************************************************//***********IGH demo编译*****************/
arm-linux-gnueabi-gcc main.c -o ethercat_test -I../../ethercat/include/ -L../..ethercat/lib -lethercat

IGH在Linux应用空间的其他使用

参考EtherCAT源码下的example。

git clone https://gitee.com/wllw7176/MyEthercat-IGH-1.5.2.git

 参考EtherCAT二次开发的源代码

其他资源

EtherCAT使用与解析-ethercat系统内核模块加载与初始化操作_ec_generic.ko-CSDN博客

https://www.cnblogs.com/wujingcqu/p/16295570.html

https://blog.51cto.com/u_15858333/6406909

IgH详解 一、概述-CSDN博客

EtherCAT设备协议详解二、EtherCAT状态机及配置流程-CSDN博客

在x86-64和arm64 Linux上调试IgH EtherCAT主站软件以及实现星形走线连接多从站 - 知乎

ethercatpack/mytest/test_ethercat.c · wllw7176_gitee/MyEthercat-IGH 1.5.2 - Gitee.com

https://pwl999.blog.csdn.net/article/details/109397917

IgH EtherCAT主站开发案例分享——基于NXP i.MX 8M Mini - 知乎

开源工业以太网现场总线协议栈汇总_soes从站模拟器-CSDN博客

raspberry pi RT-Linux平台搭建IgH环境_一种用于igh的网络驱动系统及方法与流程-CSDN博客

EtherCAT主站IgH解析(一)--主站初始化、状态机与EtherCAT报文_igh ethercat-CSDN博客

EtherCAT IGH 命令行介绍_igh ethercat-CSDN博客

LinuxCNC搭配Igh EtherCat Master开源Ethercat主站通讯控制测试_linuxcnc igh-CSDN博客

【虹科干货】使用Profishark进行EtherCAT主站性能测试 – 宏网络安全信息门户网站2

基于Zynq平台的igh EtherCAT主站的配置和使用方法,包括Preempt RT和Xenomai两种实时内核的介绍和配置示例_ethercat1.5.2中文-CSDN博客

https://www.cnblogs.com/tdyizhen1314/p/17628400.html

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

2核4G云服务器并发能支持多少用户在线?

腾讯云轻量2核4G5M带宽服务器支持多少人在线访问&#xff1f;5M带宽下载速度峰值可达640KB/秒&#xff0c;阿腾云以搭建网站为例&#xff0c;假设优化后平均大小为60KB&#xff0c;则5M带宽可支撑10个用户同时在1秒内打开网站&#xff0c;并发数为10&#xff0c;经阿腾云测试&a…

学点Java打小工_Day4_数组_冒泡排序

1 数组基本概念 程序算法数据结构 算法&#xff1a;解决程序的流程步骤 数据结构&#xff1a;将数据按照某种特定的结构来存储 设计良好的数据结构会导致良好的算法。 ArrayList、LinkedList 数组是最简单的数据结构。 数组&#xff1a;存放同一种类型数据的集合&#xff0c;在…

桌面待办,电脑桌面怎么设置待办事项

在忙碌的工作生活中&#xff0c;我们经常会有许多事情需要处理&#xff0c;为了提高工作效率和管理时间&#xff0c;很多人都有一套自己的桌面待办事项管理方法。那么&#xff0c;如何利用电脑桌面待办事项来提高工作效率&#xff0c;电脑桌面怎么设置待办事项呢&#xff1f; …

【Poi-tl Documentation】自定义占位符来设置图片大小

前置说明&#xff1a; <dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version> </dependency>模板文件&#xff1a; image_test.docx package run.siyuan.poi.tl.policy;imp…

Internet协议的安全性

Internet协议的安全性 文章目录 Internet协议的安全性1. 网络层1. IP*62. ARP*33. ICMP * 3 2. 传输层协议1. TCP1. * SYN-Flood攻击攻击检测* 防御 2. TCP序号攻击攻击 3. 拥塞机制攻击 2. UDP 3. 应用层协议1. DNS攻击*3防范*3: 2. FTP3. TELNET: 改用ssh4. 电子邮件1. 攻击2…

set与zset数据类型

set类型基础 redis集合(set)类型和list列表类型类似&#xff0c;都可以用来存储多个字符串元素的 集合。但是和list不同的是set集合当中不允许重复的元素。而且set集合当中元素是没有顺序的&#xff0c;不存在元素下标。 redis的set类型是使用哈希表构造的&#xff0c;因此复…

每日OJ题_简单多问题dp⑥_力扣714. 买卖股票的最佳时机含手续费

目录 力扣714. 买卖股票的最佳时机含手续费 状态机分析 解析代码 力扣714. 买卖股票的最佳时机含手续费 714. 买卖股票的最佳时机含手续费 难度 中等 给定一个整数数组 prices&#xff0c;其中 prices[i]表示第 i 天的股票价格 &#xff1b;整数 fee 代表了交易股票的手续…

Linux远程连接本地数据库(docker)

1. 安装docker 参考上一篇文章 CentOS安装Docker 2. Linux中安装Mysql 2.1 docker拉取mysql镜像 拉取镜像 docker pull mysql查看镜像列表 docker images2.2 运行mysql容器 运行一个名字为mysql的mysql容器&#xff0c;其连接端口号为3306&#xff0c;密码为123456 docker r…

口腔管理平台 |基于springboot框架+ Mysql+Java+B/S结构的口腔管理平台 设计与实现(可运行源码+数据库+lw文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 会员功能 系统功能设计 数据库E-R图设计 lunwen参考…

RT-Thread之USB组件的使用记录(SD卡和USB同时挂载)

前言 使用usb-host组件读取u盘记录同时挂载sd和u盘用到的芯片为stm32f407zgt6u盘的格式为fat 组件选择 文件相关的宏定义 /* DFS: device virtual file system */ /* 设备虚拟文件系统 */ #define RT_USING_DFS #define DFS_USING_WORKDIR #define DFS_FILESYSTEMS_MAX 3 //…

Pikachu 靶场搭建

文章目录 环境说明1 Pikachu 简介2 Pikachu 安装 环境说明 操作系统&#xff1a;Windows 10PHPStudy 版本: 8.1.1.3Apache 版本&#xff1a;2.4.39MySQL 版本 5.7.26 1 Pikachu 简介 Pikachu是一个使用“PHP MySQL” 开发、包含常见的Web安全漏洞、适合Web渗透测试学习人员练…

印度交易所股票行情数据API接口

1. 历史日线 # Restful API https://tsanghi.com/api/fin/stock/XNSE/daily?token{token}&ticker{ticker}默认返回全部历史数据&#xff0c;也可以使用参数start_date和end_date选择特定时间段。 更新时间&#xff1a;收盘后3~4小时。 更新周期&#xff1a;每天。 请求方式…

python二级备考(3)-综合应用

1 《命运》是著名科幻作家倪匡的作品。这里给出《命运》的一个网络版本文件&#xff0c;文件名为“命运. txt”。 问题1 (5分) :在PY301-1. py文件中修改代码&#xff0c;对“命运. txt”文件进行字符频次统计&#xff0c;输出频次最高的中文字符(不包含标点符号)及其频次&…

初学者必看的python中类型转换

Python中常见的类型转换 int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 complex(real [,imag ]) 创建一个复数 str(x ) 将对象 x 转换为字符串 repr(x ) 将对象 x 转换为表达式字符串 eval(str ) 用来计算在字符串中…

05-延迟任务精准发布文章-黑马头条

延迟任务精准发布文章 1)文章定时发布 2)延迟任务概述 2.1)什么是延迟任务 定时任务&#xff1a;有固定周期的&#xff0c;有明确的触发时间延迟队列&#xff1a;没有固定的开始时间&#xff0c;它常常是由一个事件触发的&#xff0c;而在这个事件触发之后的一段时间内触发…

Docker----Dockerfile构建微服务镜像

目录 一、关键步骤 二、具体步骤 1、准备后端jar包(这里以java后端演示) 2、编写Dockerfile 3、构建镜像 4、运行镜像容器 5、测试是否成功 一、关键步骤 1、准备后端jar包(这里以java后端演示) 2、编写Dockerfile 3、构建镜像 4、运行镜像容器 5、测试是否成功 二…

软件工程(Software Engineering)

一、软件工程概述 1.软件生存周期 软件&#xff1a; 包含程序、数据及相关文档 软件工程&#xff1a; 涉及到软件开发、维护、管理等多方面的原理、工具与环境。最终的目的是开发高质量的软件。 目的&#xff1a; 提高软件生产率、提高软件质量、降低软件成本。 文档的作用&…

2024 Mazing 3 中文版新功能介绍Windows and macOS

iMazing 3中文版(ios设备管理软件)是一款管理苹果设备的软件&#xff0c; Windows 平台上的一款帮助用户管理 IOS 手机的应用程序。iMazing中文版与苹果设备连接后&#xff0c;可以轻松传输文件&#xff0c;浏览保存信息等&#xff0c;软件功能非常强大&#xff0c;界面简洁明晰…

力扣965单值二叉树的小细节

这一段的两个判断条件&#xff0c;一定要root->left!NULL在前 如果root->val!root->left->val在前&#xff0c;root->left为空的时候&#xff0c;就无法拿出root->left->val&#xff0c;在一个NULL的指针里拿不出val。 把root->left!NULL放在前面&am…

文才与口才:谁才是成功的关键因素?

文才与口才&#xff1a;谁才是成功的关键因素&#xff1f; 自古以来&#xff0c;文才与口才一直是人们关注的重要议题。在追求成功的道路上&#xff0c;文才与口才究竟谁才是关键因素&#xff1f;这是一个值得深入探讨的问题。本文将从多个维度出发&#xff0c;分析文才与口才…