04_iic子系统
总结
iic_client和iic_driver 加入iic总线的思想和paltform总线的玩法一样
把iic设备和驱动注册到iic总线中 构造出字符设备驱动和设备节点供app进行操作
但是iic硬件设备是挂在iic控制器下面的 所以iic控制器也会有自己的驱动和设备树节点 厂家一般都会帮做好
我们写的iic_driver驱动程序 控制iic硬件的时候 直接使用iic总线提供的api 来控制iic适配器驱动程序 从而控制硬件设备
详细介绍分两部分 一个是iic设备驱动程序 一个是iic控制器驱动介绍
iic控制器驱动
芯片的iic控制器抽象成 一个iic_adapter (一般这个控制器的驱动和设备节点芯片厂商都帮创建好了)
iic_algotithm 也构建好了
linux 上电注册iic总线 drivers/i2c/i2c-core-base.c
static int __init i2c_init(void)bus_register(&i2c_bus_type); //很熟悉的总线注册
IIC总线匹配规则 也就是看总线上的.match函数- of_driver_match_device:设备树匹配方式- 比较 I2C 设备节点的 compatible 属性和 of_device_id 中的 compatible 属性- acpi_driver_match_device : ACPI 匹配方式
- i2c_match_id:i2c总线传统匹配方式- 比较 I2C设备名字和 i2c驱动的id_table->name 字段是否相等
构造iic_适配器设备树节点
下面用IIC1控制器来举例子
i2c1: i2c@21a0000 {#address-cells = <1>;#size-cells = <0>;compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";reg = <0x21a0000 0x4000>; //reg属性记录了IIC寄存器组的地址interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_I2C1>;status = "disabled";};
适配器的驱动与之匹配
这个就是厂商写的适配器驱动 但只是在和设备树匹配后在
/sys/bus/platform/i2c/dev/目录 (这个目录还没查没有板子) 增加新的dev
plantform_driver.probestruct resource *res;void __iomem *base;of_device_id *of_id = of_match_device(i2c_imx_dt_ids,&pdev->dev);res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//获取resource资源,放到设备树就是reg = <0x21a0000 0x4000>;base = devm_ioremap_resource(&pdev->dev, res);//对resource物理地址和虚拟地址映射,此时base记录了虚拟地址phy_addr = (dma_addr_t)res->start;//这里记录物理地址,直接从resource->start拿取i2c_imx = devm_kzalloc(&pdev->dev, sizeof(*i2c_imx), GFP_KERNEL);//分配内存i2c_imx->adapter.algo = &i2c_imx_algo;//初始化运算器,用于直接操作硬件的代码ret = i2c_add_numbered_adapter(&i2c_imx->adapter);//在linux注册一个i2c_adapstatic const struct i2c_algorithm i2c_imx_algo = { //运算器结构体.master_xfer = i2c_imx_xfer,//产生IIC通讯时序,负责数据收发.functionality = i2c_imx_func,//查询iic通信协议类型,iic通讯协议有一大类
};.master_xferresult = i2c_imx_start(i2c_imx);//发送IIC的启动信号...for (i = 0; i < num; i++) { //在for循环里面发送数据if (i == num - 1)is_lastmsg = true;result = i2c_imx_bus_busy(i2c_imx, 1);//判断当前iic总线是否忙if (msgs[i].flags & I2C_M_RD) //不忙判断当前信息需要读还是写result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg);//这里真正控制IIC的寄存器进行发送读取else {if (i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD)result = i2c_imx_dma_write(i2c_imx, &msgs[i]);elseresult = i2c_imx_write(i2c_imx, &msgs[i]);}
IIC核心函数和万能驱动!!! i2c-dev.c
iic适配器 在上面probe后 iic_bus里面的dev有了新的适配器dev
万能驱动通过bus找到所有适配器dev 给这些适配注册字符设备 /proc/devcies
注册class 和device 再分配设备节点 /dev/xxx
具体如下
- 给每个i2c适配器生成设备文件,给app操作!!!
- 内核集成i2c_dev驱动模块,开机自动加载
- 为每个i2c_adapter生成一个设备文件,在用户空间通过该设备文件间接使用IIC核心函数收发数据
- 因为和适配器的驱动加载有先后问题
这个驱动注册i2c总线的通知函数,解决加载顺序问题
对于这个iic万能驱动程序的存在 我的理解是
iic适配器创建出来,但是没有设备节点 为了让iic适配器直接被应用程序调用 所以使用了i2c-dev.c
给每个i2c适配器生成设备文件,给app操作
看看到底干了点什么把
i2c_dev_init()res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);struct char_device_struct *cd; //构建字符设备结构体struct cdev *cdev;__register_chrdev(major, 0, 256, name, fops);__register_chrdev_region(major, baseminor, count, name);cdev = cdev_alloc(); //构建cdev cdev->owner = fops->owner;cdev->ops = fops;kobject_set_name(&cdev->kobj, "%s", name); //这里看cdev继承kobj,并且给kobj名字,创建设备文件cdev_add() //kobj_map结构体!!是用来管理设备号及其对应的设备的,kobj_map函数把指定的设备号加入到该数组用kobject对象,得到包含它的对象如cdevkobj_map(cdev_map, dev, count, NULL,exact_match, exact_lock, p);kobject_get(p->kobj.parent);从上面看 没有注册设备节点 只是创建了/proci2c_dev_class = class_create(THIS_MODULE, "i2c-dev");bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);i2c_for_each_dev(NULL, i2cdev_attach_adapter); //i2cdev_attach_adapter 添加iic适配器就会执行的函数res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn); //从bus下面的链表的devices找bus_type=i2c_bus_type的 dev //看看增加了iic适配器就会执行的函数 这里不知道从哪来的 device *dev 很可疑
i2cdev_attach_adapter(struct device *dev, void *dummy)struct i2c_adapter *adap;struct i2c_dev *i2c_dev;if (dev->type != &i2c_adapter_type) //如果不是iic适配器返回0return 0;adap = to_i2c_adapter(dev);//从dev上面获取iic适配器i2c_dev = get_free_i2c_dev(adap); //给i2c_dev分配内存cdev_init(&i2c_dev->cdev, &i2cdev_fops);//把这个file_operation操作接口,记录在i2c_dev->cdevres = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1); //给这个设备指定设备号,之前分配的没有用,现在才开始用主设备没变,次设备号变成了适配器的编号,构造出/proc/device/xxx设备i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,MKDEV(I2C_MAJOR, adap->nr), NULL,"i2c-%d", adap->nr);//在i2c_dev_class创建新的目录//新目录下xxx/i2c-%d/dev同时记录属性文件 新目录名i2c-%d//有了属性文件,获取设备号,和file_operation//接着kset用kobj_uvevnt()通知用户空间创建设备节点
iic设备驱动程序
设备树构造dev
设备dev转化为dev节点 在iic中转化为iic_client结构体
struct i2c_client
struct device dev; 继承了 struct device 符合linux驱动设备模型
linux根据IIC设备节点自动生成i2c_client节点
//iomuxc子节点
pinctrl_i2c1: i2c1grp {fsl,pins = <MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0>;};
//在i2c控制器下新增 设备节点
&i2c1{clock-frequency = <100000>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_i2c1>;status = "okay";i2c_mpu6050@68 {compatible = "fire,i2c_mpu6050";reg = <0x68>;status = "okay";};
};```c
struct i2c_client {unsigned short flags; /* div., see below */unsigned short addr; /* 7位地址 */char name[I2C_NAME_SIZE];struct i2c_adapter *adapter; /* the adapter we sit on */struct device dev; /* 继承了 struct device 符合linux驱动设备模型 */int init_irq; /* irq set at initialization */int irq; /* irq issued by device */struct list_head detected;
#if IS_ENABLED(CONFIG_I2C_SLAVE)i2c_slave_cb_t slave_cb; /* callback for slave mode */
#endif
};
设备驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/i2c.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/io.h>
#include <linux/device.h>#include <linux/platform_device.h>#include "i2c_mpu6050.h"/*------------------字符设备内容----------------------*/
#define DEV_NAME "I2C1_mpu6050"
#define DEV_CNT (1)/*定义 led 资源结构体,保存获取得到的节点信息以及转换后的虚拟寄存器地址*/
static dev_t mpu6050_devno; //定义字符设备的设备号
static struct cdev mpu6050_chr_dev; //定义字符设备结构体chr_dev
struct class *class_mpu6050; //保存创建的类
struct device *device_mpu6050; // 保存创建的设备
struct device_node *mpu6050_device_node; //rgb_led的设备树节点结构体/*------------------IIC设备内容----------------------*/
struct i2c_client *mpu6050_client = NULL; //保存mpu6050设备对应的i2c_client结构体,匹配成功后由.prob函数带回。/*通过i2c 向mpu6050写入数据
*mpu6050_client:mpu6050的i2c_client结构体。
*address, 数据要写入的地址,
*data, 要写入的数据
*返回值,错误,-1。成功,0
*/
static int i2c_write_mpu6050(struct i2c_client *mpu6050_client, u8 address, u8 data)
{int error = 0;u8 write_data[2];struct i2c_msg send_msg; //要发送的数据结构体/*设置要发送的数据*/write_data[0] = address;write_data[1] = data;/*发送 iic要写入的地址 reg*/send_msg.addr = mpu6050_client->addr; //mpu6050在 iic 总线上的地址send_msg.flags = 0; //标记为发送数据send_msg.buf = write_data; //写入的首地址send_msg.len = 2; //reg长度/*执行发送*/error = i2c_transfer(mpu6050_client->adapter, &send_msg, 1);if (error != 1){printk(KERN_DEBUG "\n i2c_transfer error \n");return -1;}return 0;
}/*通过i2c 向mpu6050写入数据
*mpu6050_client:mpu6050的i2c_client结构体。
*address, 要读取的地址,
*data,保存读取得到的数据
*length,读长度
*返回值,错误,-1。成功,0
*/
static int i2c_read_mpu6050(struct i2c_client *mpu6050_client, u8 address, void *data, u32 length)
{int error = 0;u8 address_data = address;struct i2c_msg mpu6050_msg[2];/*设置读取位置msg*/mpu6050_msg[0].addr = mpu6050_client->addr; //mpu6050在 iic 总线上的地址mpu6050_msg[0].flags = 0; //标记为发送数据mpu6050_msg[0].buf = &address_data; //写入的首地址mpu6050_msg[0].len = 1; //写入长度/*设置读取位置msg*/mpu6050_msg[1].addr = mpu6050_client->addr; //mpu6050在 iic 总线上的地址mpu6050_msg[1].flags = I2C_M_RD; //标记为读取数据mpu6050_msg[1].buf = data; //读取得到的数据保存位置mpu6050_msg[1].len = length; //读取长度error = i2c_transfer(mpu6050_client->adapter, mpu6050_msg, 2);if (error != 2){printk(KERN_DEBUG "\n i2c_read_mpu6050 error \n");return -1;}return 0;
}/*初始化i2c
*返回值,成功,返回0。失败,返回 -1
*/
static int mpu6050_init(void)
{int error = 0;/*配置mpu6050*/error += i2c_write_mpu6050(mpu6050_client, PWR_MGMT_1, 0X00);error += i2c_write_mpu6050(mpu6050_client, SMPLRT_DIV, 0X07);error += i2c_write_mpu6050(mpu6050_client, CONFIG, 0X06);error += i2c_write_mpu6050(mpu6050_client, ACCEL_CONFIG, 0X01);if (error < 0){/*初始化错误*/printk(KERN_DEBUG "\n mpu6050_init error \n");return -1;}return 0;
}/*字符设备操作函数集,open函数实现*/
static int mpu6050_open(struct inode *inode, struct file *filp)
{// printk("\n mpu6050_open \n");/*向 mpu6050 发送配置数据,让mpu6050处于正常工作状态*/mpu6050_init();return 0;
}/*字符设备操作函数集,.read函数实现*/
static ssize_t mpu6050_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
{char data_H;char data_L;int error;short mpu6050_result[6]; //保存mpu6050转换得到的原始数据// printk("\n mpu6050_read \n");i2c_read_mpu6050(mpu6050_client, ACCEL_XOUT_H, &data_H, 1);i2c_read_mpu6050(mpu6050_client, ACCEL_XOUT_L, &data_L, 1);mpu6050_result[0] = data_H << 8;mpu6050_result[0] += data_L;i2c_read_mpu6050(mpu6050_client, ACCEL_YOUT_H, &data_H, 1);i2c_read_mpu6050(mpu6050_client, ACCEL_YOUT_L, &data_L, 1);mpu6050_result[1] = data_H << 8;mpu6050_result[1] += data_L;i2c_read_mpu6050(mpu6050_client, ACCEL_ZOUT_H, &data_H, 1);i2c_read_mpu6050(mpu6050_client, ACCEL_ZOUT_L, &data_L, 1);mpu6050_result[2] = data_H << 8;mpu6050_result[2] += data_L;i2c_read_mpu6050(mpu6050_client, GYRO_XOUT_H, &data_H, 1);i2c_read_mpu6050(mpu6050_client, GYRO_XOUT_L, &data_L, 1);mpu6050_result[3] = data_H << 8;mpu6050_result[3] += data_L;i2c_read_mpu6050(mpu6050_client, GYRO_YOUT_H, &data_H, 1);i2c_read_mpu6050(mpu6050_client, GYRO_YOUT_L, &data_L, 1);mpu6050_result[4] = data_H << 8;mpu6050_result[4] += data_L;i2c_read_mpu6050(mpu6050_client, GYRO_ZOUT_H, &data_H, 1);i2c_read_mpu6050(mpu6050_client, GYRO_ZOUT_L, &data_L, 1);mpu6050_result[5] = data_H << 8;mpu6050_result[5] += data_L;// printk("AX=%d, AY=%d, AZ=%d \n",(int)mpu6050_result[0],(int)mpu6050_result[1],(int)mpu6050_result[2]);// printk("GX=%d, GY=%d, GZ=%d \n \n",(int)mpu6050_result[3],(int)mpu6050_result[4],(int)mpu6050_result[5]);/*将读取得到的数据拷贝到用户空间*/error = copy_to_user(buf, mpu6050_result, cnt);if(error != 0){printk("copy_to_user error!");return -1;}return 0;
}/*字符设备操作函数集,.release函数实现*/
static int mpu6050_release(struct inode *inode, struct file *filp)
{// printk("\n mpu6050_release \n");/*向mpu6050发送命令,使mpu6050进入关机状态*/return 0;
}/*字符设备操作函数集*/
static struct file_operations mpu6050_chr_dev_fops ={.owner = THIS_MODULE,.open = mpu6050_open,.read = mpu6050_read,.release = mpu6050_release,
};/*----------------平台驱动函数集-----------------*/
static int mpu6050_probe(struct i2c_client *client, const struct i2c_device_id *id)
{int ret = -1; //保存错误状态码printk(KERN_EMERG "\t match successed \n");/*---------------------注册 字符设备部分-----------------*///采用动态分配的方式,获取设备编号,次设备号为0,//设备名称为rgb-leds,可通过命令cat /proc/devices查看//DEV_CNT为1,当前只申请一个设备编号ret = alloc_chrdev_region(&mpu6050_devno, 0, DEV_CNT, DEV_NAME);if (ret < 0){printk("fail to alloc mpu6050_devno\n");goto alloc_err;}//关联字符设备结构体cdev与文件操作结构体file_operationsmpu6050_chr_dev.owner = THIS_MODULE;cdev_init(&mpu6050_chr_dev, &mpu6050_chr_dev_fops);// 添加设备至cdev_map散列表中ret = cdev_add(&mpu6050_chr_dev, mpu6050_devno, DEV_CNT);if (ret < 0){printk("fail to add cdev\n");goto add_err;}/*创建类 */class_mpu6050 = class_create(THIS_MODULE, DEV_NAME);/*创建设备 DEV_NAME 指定设备名,*/device_mpu6050 = device_create(class_mpu6050, NULL, mpu6050_devno, NULL, DEV_NAME);mpu6050_client = client;return 0;add_err:// 添加设备失败时,需要注销设备号unregister_chrdev_region(mpu6050_devno, DEV_CNT);printk("\n error! \n");
alloc_err:return -1;
}static int mpu6050_remove(struct i2c_client *client)
{/*删除设备*/device_destroy(class_mpu6050, mpu6050_devno); //清除设备class_destroy(class_mpu6050); //清除类cdev_del(&mpu6050_chr_dev); //清除设备号unregister_chrdev_region(mpu6050_devno, DEV_CNT); //取消注册字符设备return 0;
}/*定义ID 匹配表*/
static const struct i2c_device_id gtp_device_id[] = {{"fire,i2c_mpu6050", 0},{}};/*定义设备树匹配表*/
static const struct of_device_id mpu6050_of_match_table[] = {{.compatible = "fire,i2c_mpu6050"},{/* sentinel */}};/*定义i2c总线设备结构体*/
struct i2c_driver mpu6050_driver = {.probe = mpu6050_probe,.remove = mpu6050_remove,.id_table = gtp_device_id,.driver = {.name = "fire,i2c_mpu6050",.owner = THIS_MODULE,.of_match_table = mpu6050_of_match_table,},
};/*
*驱动初始化函数
*/
static int __init mpu6050_driver_init(void)
{int ret;pr_info("mpu6050_driver_init\n");ret = i2c_add_driver(&mpu6050_driver);return ret;
}/*
*驱动注销函数
*/
static void __exit mpu6050_driver_exit(void)
{pr_info("mpu6050_driver_exit\n");i2c_del_driver(&mpu6050_driver);
}module_init(mpu6050_driver_init);
module_exit(mpu6050_driver_exit);MODULE_LICENSE("GPL");
相关文章:
池化整合多元数据库,zData X 一体机助力证券公司IT基础架构革新
引言 近期,云和恩墨 zData X 多元数据库一体机(以下简称 zData X)在某证券公司的OA、短信和CRM业务系统中成功上线,标志着其IT基础架构完成从集中式存储向池化高性能分布式存储的转变。zData X 成功整合了该证券公司使用的达梦、O…...
用Python将原始边列表转换为邻接矩阵
👽发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在图论和网络分析中,图是一种非常重要的数据结构,它由节点ÿ…...
git 基础知识(全能版)
文章目录 一 、git 有三个分区二、git 基本操作1、克隆—git clone2、拉取—git fetch / git pull3、查看—git status / git diff3.1 多人开发代码暂存技巧 本地代码4、提交—git add / git commit / git push5、日志—git log / git reflog6、删除—git rm ‘name’7、撤销恢…...
ELK 日志分析系统(二)
一、ELK Kibana 部署 1.1 安装Kibana软件包 #上传软件包 kibana-5.5.1-x86_64.rpm 到/opt目录 cd /opt rpm -ivh kibana-5.5.1-x86_64.rpm 1.2 设置 Kibana 的主配置文件 vim /etc/kibana/kibana.yml --2--取消注释,Kiabana 服务的默认监听端口为5601 server.po…...
CF1197E Culture Code
CF1197E Culture Code 无后效性+线性dp+线段树优化 看到求最值以及方案数,考虑 dp。当前的顺序显然是无从下手的,因为套娃的顺序是乱的,考虑能否找到偏序满足无后效性。可以按照 \(in_i\) 从大到小排序,那么存在极大区间 \([1,j]\in[1,i)\), \(in_{j}>out_{i}> in_i…...
双向循环链表队列的接口设计
关于双向循环链表队列的接口设计/*********************************************************************************************************** 该程序实现循环队列元素的增删改查,目的是提高设计程序的逻辑思维,另外为了提高可移植性,所以循环队列中元素* 的数据类型为…...
04_iic子系统
总结 iic_client和iic_driver 加入iic总线的思想和paltform总线的玩法一样 把iic设备和驱动注册到iic总线中 构造出字符设备驱动和设备节点供app进行操作 但是iic硬件设备是挂在iic控制器下面的 所以iic控制器也会有自己的驱动和设备树节点 厂家一般都会帮做好 我们写的iic_dr…...
离散系统的数字PID控制仿真-3
离散PID控制的封装界面如图1所示,在该界面中可设定PID的三个系数、采样时间及控制输入的上下界。仿真结果如图2所示。图1 离散PID控制的封装界面图2 阶跃响应结果仿真图:离散PID控制的比例、积分和微分三项分别由Simulink模块实现。离散PID控制器仿真图&…...
如何好好说话-第12章 理清楚问题就是答案
生活中该不该积极主动与别人展开社交活动?有些时候社交活动并不开心,仅仅只是无聊的闲才。但他确实能拉拢人际关系,帮我们获得近身套路。而且有一种观点认为不善于社交的人是不成功的。注意以上说的这些都是偏见。当我们站在一个更高的维度认…...
ice规则引擎==启动流程和源码分析
启动 git clone代码 创建数据库ice,执行ice server里的sql,修改ice server的配置文件中的数据库信息 启动ice server 和ice test 访问ice server localhost:8121 新增一个app,默认给了个id为1,这个1可以看到在ice test的配置文件中指定…...
进度管理(上)
规划进度管理 定义:规划进度管理是为实施项目进度管理制定计划的过程。 输入: 1、项目管理计划 2、项目章程(包含里程碑,这个和规划进度有直接干系) 3、组织过程资产 4、事业环境因素。 输出:进度管…...
2021 XV6 8:locks
实验有两个任务,都是为了减少锁的竞争从而提高运行效率。Memory allocator一开始我们是有个双向链表用来存储空闲的内存块,如果很多个进程要竞争这一个链表,就会把效率降低很多。所以我们把链表拆成每个CPU一个,在申请内存的时候就…...
JUC面试(十一)——LockSupport
可重入锁 可重入锁又名递归锁 是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提,锁对象得是同一个对象),不会因为之前已经获取过的锁还没释放而阻塞。 Java中ReentrantLock和synchronized都是可重入锁&am…...
Datawhale 202301 设计模式 | 人工智能 现代方法 习题
Exercise 1 绪论 Q:用您自己的话来定义:(a)智能,(b)人工智能,(c)智能体,(d)理性,(e)逻…...
k8s安装dashboard面板
k8s dashboard github地址:https://github.com/kubernetes/dashboard注意:dashboard版本要和k8s版本匹配,具体参考release里的Compatibility:https://github.com/kubernetes/dashboard/releases安装命令wget https://raw.githubus…...
最详细、最仔细、最清晰的几道python习题及答案(建议收藏哦)
名字:阿玥的小东东 学习:python。c 主页:没了 今天阿玥带大家来看看更详细的python的练习题 目录 1. 在python中, list, tuple, dict, set有什么区别, 主要应用在什么样的场景? 2. 静态函数, 类函数, 成员函数、属性函数的区别? 2.1静态…...
逆水寒魔兽老兵服副本攻略及代码分析(英雄武林风云录,后续更新舞阳城、扬州、清明等副本攻略)
文章目录一、武林风云录1)老一:陈斩槐(只有四个机制,dps压力不大,留爆发打影子就行)(1)点名红色扇形区域(2)点名红色长条,注意最后还有一段大劈&a…...
SpringMVC总结
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。SpringMVC是一种web层的mvc框架,用于替代servlet(处理响应请求,获取表单参数,表单验…...
二进制部署kubernetes高可用集群
二进制部署kubernetes高可用集群 一、单节点部署 1、集群节点规划(均是24位掩码) 负载均衡节点Master节点Node节点Harbor私有仓库节点nginx110.4.7.23master110.4.7.11node110.4.7.2110.4.7.200nginx210.4.7.24master210.4.7.12node210.4.7.22 2、基本…...
机器学习(七):Azure机器学习模型搭建实验
文章目录 Azure机器学习模型搭建实验 前言 Azure平台简介 Azure机器学习实验 Azure机器学习模型搭建实验 前言 了解Azure机器学习平台,知道机器学习流程。 Azure平台简介 Azure Machine Learning(简称“AML”)是微软在其公有云Azure上推…...
第二类换元法倒代换专项训练
前置知识:第二类换元法 题1: 计算∫1x10xdx\int\dfrac{1}{x^{10}x}dx∫x10x1dx 解: \qquad令x1tx\dfrac 1txt1,t1xt\dfrac 1xtx1,dx−1t2dtdx-\dfrac{1}{t^2}dtdx−t21dt \qquad原式∫11t101t⋅(−1t2)dt−∫…...
VMware虚拟机无法向宿主机拖放文件
宿主机环境: Windows 10 x64专业工作站版 VMware workstation pro 17 TotalCommander 9.21a 虚拟机环境: Windows 10 x64专业工作站版 TotalCommander 9.21a 现象: 从虚拟机的TC向宿主机TC拖放文件时,光标显示为禁止drop的图…...
Java基础语法——运算符与表达式
目录 Eclipse下载 安装 使用 运算符 键盘录入 Eclipse下载 安装 使用 Eclipse的概述(磨刀不误砍柴工)——是一个IDE(集成开发环境)Eclipse的特点描述(1)免费 (2)纯Java语言编写 (3)免安装 (…...
连通性1(Tarjan 理论版)
目录 一、无向图割点、桥、双连通分量 Tarjan 算法求割点和桥(割边) “割点”代码 边双和点双连通分量 边双连通分量 和 点双连通分量 的缩点 二、有向图强连通分量 1.有向图的弱连通与强连通 2.强连通分量 Kosaraju算法 Tarjan 算法(…...
数据库02_函数依赖,数据库范式,SQL语句关键字,数据库新技术---软考高级系统架构师009
1.首先我们来看这个,给定一个X,能确定一个Y那么就说,X确定Y,或者Y依赖x,那么 比如y = x * x 就是x确定y,或者y依赖于x 2.然后再来看图,那么左边的部分函数依赖,就是,通过A和B能决定C,那么如果A只用给就能决定C,那么就是部分函数依赖. 3.然后再来看,可以看到,A可以决定B,那么…...
王者荣耀入门技能树-解答
前言 前段时间写了一篇关于王者荣耀入门技能树的习题,今天来给大家解答一下。 职业 以下哪个不属于王者荣耀中的职业: 射手法师辅助亚瑟 这道题选:亚瑟 王者荣耀中有6大职业分类,分别是:坦克、战士、刺客、法师、…...
java基础学习 day37 (集合)
集合与数组的区别 长度:数组长度固定,一旦创建完成,就不能改变。集合长度可变,根据添加和删除元素,自动扩容或自动收缩,(添加几个元素就扩容多少,删除几个元素就收缩多少࿰…...
C语言:数组
往期文章 C语言:初识C语言C语言:分支语句和循环语句C语言:函数 目录往期文章前言1. 一维数组的创建和初始化1.1 数组的创建1.2 数组的初始化2. 一维数组的使用3. 一维数组在内存中的存储4. 二维数组的创建和初始化4.1 二维数组的创建4.2 二维…...
斐波那契数列的--------5种算法(又称“兔子数列”)
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:…...
【计算机网络(考研版)】第一站:计算机网络概述(二)
目录 四、OSI参考模型和TCP/IP模型 1.ISO/0SI参考模型 2.TCP/IP模型 3.OSI/RM参考模型和TCP/IP参考模型的区别和联系 4.五层教学模型 5.数据流动示意图 四、OSI参考模型和TCP/IP模型 前面我们已经讨论了体系结构的基木概念,在具体的实施中有两个重要的网络体系…...
Python内置包Tkinter的重要控件(下)
本文将接着介绍剩下的五个重要的控件,包括Canvas,Messagebox,Listbox,Checkbutton,Radiobutton。 目录 前言 控件 1. Canvas 2. Messagebox 3. Listbox 4. Radiobutton 5. Checkbutton 总结 前言 包括但不…...
(Java高级教程)第四章必备前端基础知识-第二节2:CSS属性
文章目录一:CSS属性一览表二:常用属性详解(1)字体属性(2)文本属性(3)背景属性一:CSS属性一览表 W3C:元素属性 A: align-content规定弹性容器内…...
听障人士亲述:我们在VRChat用手语交流,成员规模5000人
如果你在B站上搜索VRChat,排在前面的热门视频几乎都是与老外聊天的内容。除了练习语言、交文化流外,你还能在VRChat上遇到不少哇哇乱叫的小孩。作为一款VR社交应用,除了有趣的小游戏外,说话聊天也是VRChat关键的玩法之一。而有这么…...
设计一个70W在线人数的弹幕系统
背景: 直播业务中增加弹幕系统,支持单房间百万用户同时在线。 问题分析: 带宽压力: 假如说每3秒促达用户一次,那么每次内容至少需要有15条才能做到视觉无卡顿。15条弹幕http包头的大小将超过3k,那么每秒…...
一起自学SLAM算法:第9章-视觉SLAM系统
连载文章,长期更新,欢迎关注: 上一章介绍了以激光雷达做为数据输入的激光SLAM系统,激光雷达的优点在于数据稳定性好、测距精度高、扫描范围广,但缺点是价格昂贵、数据信息量低、安装部署位置不能有遮挡、雨天烟雾等环境…...
LeetCode 437. 路径总和 III
LeetCode 437. 路径总和 III 给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的ÿ…...
LinuxC—高级IO
高级IO 1 非阻塞IO/有限状态机编程 1.1 基本概念 定义 有限状态机(Finite State Machine) 缩写为 FSM,状态机有 3 个组成部分:状态、事件、动作。 状态:所有可能存在的状态。包括当前状态和条件满足后要迁移的状态。事件:也称为…...
WebSocket 入门:简易聊天室
大家好,我是前端西瓜哥,今天我们用 WebSocket 来实现一个简单的聊天室。 WebSocket 是一个应用层协议,有点类似 HTTP。但和 HTTP 不一样的是,它支持真正的全双工,即不仅客户端可以主动发消息给服务端,服务…...
Windows10添加WebDav地址时报错“输入的文件夹无效,请选择另一个”
一、问题描述在使用Windows10添加WebDav网络地址时,报错“输入的文件夹无效,请选择另一个”,如下图所示:二、问题分析这是由于Windows10的WebDav默认只支持https协议,没有支持http协议导致的。三、解决办法3.1、修改注…...
Cadence PCB仿真使用Allegro PCB SI生成串扰总结报告Crosstalk Summary Report及报告导读图文教程
🏡《Cadence 开发合集目录》 🏡《Cadence PCB 仿真宝典目录》 目录 1,概述2,生成报告3,报告导读4,总结1,概述 Crosstalk Summary Report是各种串扰问题的一个简要总结报告。本文简单介绍使用Allegro PCB SI生成Crosstalk Summary Report报告的方法,及其要点导读。…...
【5-卷积神经网络】北京大学TensorFlow2.0
课程地址:【北京大学】Tensorflow2.0_哔哩哔哩_bilibiliPython3.7和TensorFlow2.1六讲:神经网络计算:神经网络的计算过程,搭建第一个神经网络模型神经网络优化:神经网络的优化方法,掌握学习率、激活函数、损…...
C++初阶:vector类
文章目录1 vector介绍2 实现vector2.1 类的定义2.2 默认成员函数2.2.1 构造函数2.2.2 析构函数2.2.3 拷贝构造2.2.4 赋值重载2.3访问接口2.4 容量接口2.5 修改接口2.5.1 尾插尾删2.5.2 任意位置插入2.5.3 任意位置删除2.6 其他接口1 vector介绍 1 vector是表示可变大小数组的序…...
机器学习中软投票和硬投票的不同含义和理解
设置一个场景,比如对于今天音乐会韩红会出现的概率三个人三个观点 A:韩红出现的概率为47% B:韩红出现的概率为57% C:韩红出现的概率为97% 软投票:软投票会认为韩红出现的概率为1/3*(47%57%97%)67% 硬投票:…...
Linux系统之网络客户端工具
Linux系统之网络客户端工具一、Links工具1.Links工具介绍2.安装Links软件3.Links工具的使用4.打印网页源码输出5.打印url版本到标准格式输出二、wget工具1.wget工具介绍2.安装wget软件3.wget工具的使用三、curl工具1.curl工具的介绍2.curl的常用参数3.curl的基本使用四、scp工具…...
c++函数(2)
这里写自定义目录标题默认参数函数重载递归函数变量周期默认参数 可为形参指定默认值,如果在函数调用时,没有指定与形参对应的实参时,就自动使用默认值。 默认参数可简化复杂函数的调用。 默认参数在函数名第一次出现在程序中指定࿰…...
HackTheBox Stocker API滥用,CVE-2020-24815获取用户shell,目录遍历提权
靶机地址: https://app.hackthebox.com/machines/Stocker枚举 使用nmap枚举靶机 nmap -sC -sV 10.10.11.196机子开放了22,80端口,我们本地解析一下这个域名 echo "10.10.11.196 stocker.htb" >> /etc/hosts 去浏览器访问…...
Java线程池应用实例
线程池的学习基本概念好处应用场景ThreadPoolExecutor实例理解:执行流程自定义线程池4大核心参数测试demo结论:ExecutorService常用方法思考获取ExecutorService代码示例ScheduleExecutorService常用获取方式如下ScheduledExecutorService常用方法如下:代…...
数字签名技术
介绍数字签名 数字签名是一种用于确认数据的完整性、确认发送者身份的技术。 签名主要包含两个过程:做摘要、进行非对称加密。 做摘要:签名者使用消息摘要算法对消息做摘要;进行非对称加密,得到签名值:签名者使用私…...
WPF-3D图形
WPF-3D图形 WPF的3D功能可以在不编写任何c#代码的情况下进行绘制,只需要使用xaml即可完成3D图形的渲染。本文主要讲述了WPF-3D中的关键概念, 以及常用到的命中测试、2d控件如何在3D对象中进行渲染,除此之外,还演示了如何导入外部…...
返回值的理解
前言 我们写的函数是怎么返回的,该如何返回一个临时变量,临时变量不是出栈就销毁了吗,为什么可以传递给调用方?返回对象的大小对使用的方式有影响吗?本文将带你探究这些问题,阅读本文需要对函数栈帧有一定…...
前端布局神器display:flex
Flexbox,一种CSS3的布局模式,也叫做弹性盒子模型,用来为盒装模型提供最大的灵活性。首先举一个栗子,之前我们是这样实现一个div盒子水平垂直居中的。在知道对象高宽的情况下,对居中元素绝对百分比定位,然后…...
【Typescript学习】使用 React 和 TypeScript 构建web应用(三)所有组件
教程来自freecodeCamp:【英字】使用 React 和 TypeScript 构建应用程序 跟做,仅记录用 其他资料:https://www.freecodecamp.org/chinese/news/learn-typescript-beginners-guide/ 第三天 以下是视频(0:40-0:60) 的内容 目录第三天1 创建Todo…...
7.3 矩阵范数
定义 向量有范数,矩阵也有范数,定义和向量范数类似,不过多了一条要求。它的定义如下: 正定性positivity,∥A∥≥0\parallel A\parallel\ge 0∥A∥≥0,只有A0A0A0时才取等号;非负齐次性homogeneity或scalin…...
Jetpack架构组件库:Hilt
Hilt Hilt 是基于 Dagger2 的依赖注入框架,Google团队将其专门为Android开发打造了一种纯注解的使用方式,相比 Dagger2 而言使用起来更加简单。 依赖注入框架的主要作用就是控制反转(IOC, Inversion of Control), 那么什么是控制…...
InstanceNorm LayerNorm
InstanceNorm && LayerNorm author: SUFEHeisenberg date: 2023/01/26 先说结论: 将Transformer类比于RNN:一个token就是一层layer,对一整句不如token有意义原生Bert代码或huggingface中用的都是InstanceNorm instead of LayerNormÿ…...
数据结构---堆
堆 定义 基本操作 建堆 堆排序 优先队列 一、堆的定义: 堆必须是一个完全二叉树 还得满足堆序性 什么是完全二叉树呢? 完全二叉树只允许最后一行不为满 且最后一行必须从左到右排序 最后一行元素之间不可有间隔,中间不可有空缺 如下几棵树…...
全志ARM-蜂鸣器
sh操作准备: 1.使Tab键的缩进和批量对齐为4格 在/etc/vim/vimrc 中添加一项配置 set tabstop 4; 也可以再加一行 set nu显示代码的行数 vim的设置,修改/etc/vim/vimrc文件,需要用超级用户权限 /etc/vim/vimrc set shiftwidth4 设置批量…...
DIY高考倒计时小软件python实现
目录 一.前言 二.完整代码 三.代码分析 一.前言 高考倒计时是指从当前日期到高考日期之间的天数倒计时。高考是指中国的普通高等学校招生全国统一考试,是中国教育系统中最为重要和决定性的考试之一。在高考前,学生和家长通常会关注离高考还有多少天,以便合理安排备考时间…...
力扣--N皇后
题目: 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。…...
[解决] 为什么 App Inventor 扩展导入了,但是没啥反应?
大概率是导入拓展后,没有拖动拓展到界面上! 导入拓展后,别忘了拖动拓展到主界面上,这样才算真正创建了拓展对象,这时才能使用拓展的方法。 原文:为什么 App Inventor 扩展导入了,但是没啥反应&…...
在 Linux 上把 Vim 配置为默认编辑器
目录 ⛳️推荐 在 Linux 命令行中编辑 将 Vim 设置为其他程序的默认值 在 Alpine 中编辑电子邮件 总结 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站 我使用 Linux 大概有…...
HTML 中创建 WebSocket服务与接收webSocket发送内容
效果图 服务端 html客户端接受的消息 接下来开始实现服务端 创建server.js const WebSocket require(ws);const wss new WebSocket.Server({ port: 8877 });wss.on(connection, function connection(ws) {console.log(WebSocket connection opened.);// 每隔 5 秒发送一次…...