正点原子嵌入式linux驱动开发——Linux Regmap驱动
在前面学习I2C和SPI驱动的时候,针对I2C和SPI设备寄存器的操作都是通过相关的API函数进行操作的。这样Linux内核中就会充斥着大量的重复、冗余代码,但是这些本质上都是对寄存器的操作,所以为了方便内核开发人员统一访问I2C/SPI设备的时候,为此引入了Regmap子系统,本章就来学习一下如何使用Regmap API函数来读写I2C/SPI设备寄存器。
Regmap API简介
Regmap
Linux下大部分设备的驱动开发都是操作其内部寄存器,比如I2C/SPI设备的本质都是一样的,通过I2C/SPI接口读写芯片内部寄存器。芯片内部寄存器也是同样的道理,比如STM32MP157的PWM、TIM等外设初始化,最终都是要落到寄存器的设置上。
Linux下使用i2c_transfer来读写I2C设备中的寄存器,SPI接口的话使用spi_write/spi_read等。I2C/SPI芯片又非常的多,因此Linux内核里面就会充斥了大量的i2c_transfer这类的冗余代码,再者,代码的复用性也会降低。比如icm20608这个芯片既支持I2C接口,也支持SPI接口。假设在产品设计阶段一开始将icm20608设计为SPI接口,但是后面发现SPI接口不够用,或者SOC的引脚不够用,需要将icm20608改为I2C接口。这个时候icm20608的驱动就要大改,需要将SPI接口函数换为I2C的,工作量比较大。
基于代码复用的原则,Linux内核引入了regmap模型,regmap将寄存器访问的共同逻辑抽象出来,驱动开发人员不需要再去纠结使用SPI或者I2C接口API函数,统一使用regmap API函数。这样的好处就是统一使用regmap,降低了代码冗余,提高了驱动的可以移植性。regmap模型的重点在于:通过regmap模型提供的统一接口函数来访问器件的寄存器,SOC内部的寄存器也可以使用regmap接口函数来访问。
regmap是Linux内核为了减少慢速I/O在驱动上的冗余开销,提供了一种通用的接口来操作硬件寄存器。另外,regmap在驱动和硬件之间添加了cache,降低了低速I/O的操作次数,提高了访问效率,缺点是实时性会降低。
regmap的应用场景有如下所示:
- 硬件寄存器操作,比如选用通过I2C/SPI接口来读写设备的内部寄存器,或者需要读写SOC内部的硬件寄存器。
- 提高代码复用性和驱动一致性,简化驱动开发过程。
- 减少底层 I/O 操作次数,提高访问效率。
本章教程就来重点学习一下如何将SPI接口的icm20608驱动改为使用regmap API。
Regmap驱动框架
regmap框架结构
regmap驱动框架如下图所示:
regmap框架分为三层:
- 底层物理总线:regmap就是对不同的物理总线进行封装,目前regmap支持的物理总线有i2c、i3c、spi、mmio、sccb、sdw、slimbus、irq、spmi和w1。
- regmap核心层,用于实现regmap,不用关心具体实现。
- regmapAPI抽象层,regmap向驱动编写人员提供的API接口,驱动编写人员使用这些API接口来操作具体的芯片设备,也是驱动编写人员重点要掌握的。
regmap结构体
Linux内核将regmap框架抽象为regmap结构体,这个结构体定义在文件include/linux/regmap.h 中,结构体内容如下(有缩减):
示例代码 55.1.2.1 regmap 结构体
49 struct regmap {
50 union {
51 struct mutex mutex;
52 struct {
53 spinlock_t spinlock;
54 unsigned long spinlock_flags;
55 };
56 };
57 regmap_lock lock;
58 regmap_unlock unlock;
59 void *lock_arg; /* This is passed to lock/unlock functions */
60 gfp_t alloc_flags;
......
89 unsigned int max_register;
90 bool (*writeable_reg)(struct device *dev, unsigned int reg);
91 bool (*readable_reg)(struct device *dev, unsigned int reg);
92 bool (*volatile_reg)(struct device *dev, unsigned int reg);
93 bool (*precious_reg)(struct device *dev, unsigned int reg);
94 bool (*writeable_noinc_reg)(struct device *dev,
unsigned int reg);
95 bool (*readable_noinc_reg)(struct device *dev,
unsigned int reg);
96 const struct regmap_access_table *wr_table;
97 const struct regmap_access_table *rd_table;
98 const struct regmap_access_table *volatile_table;
99 const struct regmap_access_table *precious_table;
100 const struct regmap_access_table *wr_noinc_table;
101 const struct regmap_access_table *rd_noinc_table;
102
103 int (*reg_read)(void *context, unsigned int reg,
unsigned int *val);
104 int (*reg_write)(void *context, unsigned int reg,
unsigned int val);
105 int (*reg_update_bits)(void *context, unsigned int reg,
106 unsigned int mask, unsigned int val);
......
159
160 struct rb_root range_tree;
161 void *selector_work_buf; /* Scratch buffer used for selector */
162
163 struct hwspinlock *hwlock;
164 };
要使用regmap,肯定要先给驱动分配一个具体的regmap结构体实例,一会讲解如何分配regmap实例。可以看到示例代码55.1.2.1中第90-101行有很多的函数以及table,这些需要驱动编写人员根据实际情况选择性的初始化,regmap的初始化通过结构体regmap_config来完成。
regmap_config结构体
regmap_config结构体就是用来初始化regmap的,这个结构体也定义在include/linux/regmap.h 文件中,结构体内容如下:
示例代码 55.1.2.2 regmap_config 结构体
352 struct regmap_config {
353 const char *name;
354
355 int reg_bits;
356 int reg_stride;
357 int pad_bits;
358 int val_bits;
359
360 bool (*writeable_reg)(struct device *dev, unsigned int reg);
361 bool (*readable_reg)(struct device *dev, unsigned int reg);
362 bool (*volatile_reg)(struct device *dev, unsigned int reg);
363 bool (*precious_reg)(struct device *dev, unsigned int reg);
364 bool (*writeable_noinc_reg)(struct device *dev,
unsigned int reg);
365 bool (*readable_noinc_reg)(struct device *dev,
unsigned int reg);
366
367 bool disable_locking;
368 regmap_lock lock;
369 regmap_unlock unlock;
370 void *lock_arg;
371
372 int (*reg_read)(void *context, unsigned int reg,
unsigned int *val);
373 int (*reg_write)(void *context, unsigned int reg,
unsigned int val);
374
375 bool fast_io;
376
377 unsigned int max_register;
378 const struct regmap_access_table *wr_table;
379 const struct regmap_access_table *rd_table;
380 const struct regmap_access_table *volatile_table;
381 const struct regmap_access_table *precious_table;
382 const struct regmap_access_table *wr_noinc_table;
383 const struct regmap_access_table *rd_noinc_table;
384 const struct reg_default *reg_defaults;
385 unsigned int num_reg_defaults;
386 enum regcache_type cache_type;
387 const void *reg_defaults_raw;
388 unsigned int num_reg_defaults_raw;
389
390 unsigned long read_flag_mask;
391 unsigned long write_flag_mask;
392 bool zero_flag_mask;
393
394 bool use_single_read;
395 bool use_single_write;
396 bool can_multi_write;
397
398 enum regmap_endian reg_format_endian;
399 enum regmap_endian val_format_endian;
400
401 const struct regmap_range_cfg *ranges;
402 unsigned int num_ranges;
403
404 bool use_hwlock;
405 unsigned int hwlock_id;
406 unsigned int hwlock_mode;
407 };
Linux内核里面已经对regmap_config各个成员变量进行了详细的讲解,这里只看一些比较重要的:
第353行name:名字。
第355行reg_bits:寄存器地址位数,必填字段。
第356行reg_stride:寄存器地址步长。
第357行pad_bits:寄存器和值之间的填充位数。
第358行val_bits:寄存器值位数,必填字段。
第360行writeable_reg:可选的可写回调函数,寄存器可写的话此回调函数就会被调用,并返回true。
第361行readable_reg:可选的可读回调函数,寄存器可读的话此回调函数就会被调用,并返回true。
第362行volatile_reg:可选的回调函数,当寄存器值不能缓存的时候此回调函数就会被调用,并返回 true。
第363行precious_reg:当寄存器值不能被读出来的时候此回调函数会被调用,比如很多中断状态寄存器读清零,读这些寄存器就可以清除中断标志位,但是并没有读出这些寄存器内部的值。
第372行reg_read:可选的读操作回调函数,所有读寄存器的操作此回调函数就会执行。
第373行reg_write:可选的写操作回调函数,所有写寄存器的操作此回调函数就会执行。
第375行fast_io:快速I/O,使用spinlock替代mutex来提升锁性能。
第377行max_register:有效的最大寄存器地址,可选。
第378行wr_table:可写的地址范围,为regmap_access_table结构体类型。后面的rd_table、volatile_table、precious_table、wr_noinc_table和rd_noinc_table同理。
第384行reg_defaults:寄存器模式值,为reg_default结构体类型,此结构体有两个成员变
量:reg和def,reg是寄存器地址,def是默认值。
第385行num_reg_defaults:默认寄存器表中的元素个数。
第390行read_flag_mask:读标志掩码。
第391行write_flag_mask:写标志掩码。
关于regmap_config 结构体成员变量就介绍这些,其他没有介绍的自行查阅Linux内核中的相关描述。
Regmap操作函数
Regmap申请与初始化
regmap支持多种物理总线,比如I2C和SPI,需要根据所使用的接口来选择合适的regmap初始化函数。Linux内核提供了针对不同接口的regmap初始化函数,SPI接口初始化函数为regmap_init_spi,函数原型如下:
struct regmap * regmap_init_spi(struct spi_device *spi,const struct regmap_config *config)
函数参数和返回值含义如下:
- spi:需要使用regmap的spi_device。
- config:regmap_config结构体,需要程序编写人员初始化一个regmap_config实例,然后将其地址赋值给此参数。
- 返回值:申请到的并进过初始化的regmap。
I2C接口的regmap初始化函数为regmap_init_i2c,函数原型如下:
struct regmap * regmap_init_i2c(struct i2c_client *i2c,const struct regmap_config *config)
函数参数和返回值含义如下:
- i2c:需要使用regmap的i2c_client。
- config:regmap_config结构体,需要程序编写人员初始化一个regmap_config实例,然后将其地址赋值给此参数。
- 返回值:申请到的并进过初始化的regmap。
还有很多其他物理接口对应的regmap初始化函数,这里就不介绍了,可以直接查阅Linux内核即可,基本和SPI/I2C的初始化函数相同。
在退出驱动的时候需要释放掉申请到的regmap,不管是什么接口,全部使用regmap_exit这个函数来释放regmap,函数原型如下:
void regmap_exit(struct regmap *map)
函数参数和返回值含义如下:
- map:需要释放的regmap。
- 返回值:无。
一般会在probe函数中初始化regmap_config,然后申请并初始化regmap。
regmap设备访问API函数
不管是I2C还是SPI等接口,还是SOC内部的寄存器,对于寄存器的操作就两种:读和写。regmap提供了最核心的两个读写操作:regmap_read和regmap_write。这两个函数分别用来读/写寄存器,regmap_read函数原型如下:
int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
函数参数和返回值含义如下:
- map:要操作的regmap。
- reg:要读的寄存器。
- val:读到的寄存器值。
- 返回值:0,读取成功;其他值,读取失败。
regmap_write函数原型如下:
int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
函数参数和返回值含义如下:
- map:要操作的regmap。
- reg:要写的寄存器。
- val:要写的寄存器值。
- 返回值:0,写成功;其他值,写失败。
在regmap_read和regmap_write的基础上还衍生出了其他一些regmap的API函数,首先是regmap_update_bits函数,此函数用来修改寄存器指定的bit,函数原型如下:
int regmap_update_bits (struct regmap *map, unsigned int reg,unsigned int mask, unsigned int val)
函数参数和返回值含义如下:
- map:要操作的regmap。
- reg:要操作的寄存器。
- mask:掩码,需要更新的位必须在掩码中设置为1。
- val:需要更新的位值。
- 返回值:0,写成功;其他值,写失败。
比如要将寄存器的bit1和bit2置1,那么mask应该设置为0X00000011,此时val的bit1和bit2应该设置为1,也就是0Xxxxxxx11。如果要清除寄存器的bit4和bit7,那么mask应该设置为0X10010000,val的bit4和bit7设置为0,也就是0X0xx0xxxx。
接下来看一下regmap_bulk_read函数,此函数用于读取多个寄存器的值,函数原型如下:
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,size_t val_count)
函数参数和返回值含义如下:
- map:要操作的regmap。
- reg:要读取的第一个寄存器。
- val:读取到的数据缓冲区。
- val_count:要读取的寄存器数量。
- 返回值:0,写成功;其他值,读失败。
另外也有多个寄存器写函数regmap_bulk_write,函数原型如下:
int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,size_t val_count)
函数参数和返回值含义如下:
- map:要操作的regmap。
- reg:要写的第一个寄存器。
- val:要写的寄存器数据缓冲区。
- val_count:要写的寄存器数量。
- 返回值:0,写成功;其他值,读失败。
关于regmap常用到API函数就讲解到这里,还有很多其他功能的API函数,可以自行查阅Linux内核即可,内核里面对每个API函数都有详细的讲解。
regmap_config掩码设置
结构体regmap_config里面有三个关于掩码的成员变量:read_flag_mask、write_flag_mask和zero_flag_mask,这三个掩码非常重要,本节来学习一下如何使用这三个掩码。在学习icm20608的时候讲过了,icm20608支持i2c和spi接口,但是当使用spi接口的时候,读取icm20608寄存器的时候地址最高位必须置1,写内部寄存器的是时候地址最高位要设置为0。因此这里就涉及到对寄存器地址最高位的操作,在之前的SPI驱动实验中在使用SPI接口函数读取icm20608内部寄存器的时候手动将寄存器地址的最高位置1,代码如下所示:
示例代码 55.1.4.1 icm20608 驱动
1 static int icm20608_read_regs(struct icm20608_dev *dev, u8 reg,
void *buf, int len)
2 {
3
......
21 txdata[0] = reg | 0x80; /* 写数据的时候首寄存器地址 bit7 要置 1 */
22 t->tx_buf = txdata; /* 要发送的数据 */
23 t->rx_buf = rxdata; /* 要读取的数据 */
24 t->len = len+1; /* t->len=发送的长度+读取的长度 */
25 spi_message_init(&m); /* 初始化 spi_message */
26 spi_message_add_tail(t, &m);
27 ret = spi_sync(spi, &m); /* 同步发送 */
......
39 return ret;
40 }
示例代码55.1.4.1就是标准的SPI驱动,其中第21行,将寄存器的地址bit7置1,表示这是一个读操作。
当使用regmap的时候就不需要手动将寄存器地址的bit7置 1,在初始化regmap_config的时候直接将read_flag_mask设置为0X80即可,这样通过regmap读取SPI内部寄存器的时候就会将寄存器地址与read_flag_mask进行或运算,结果就是将bit7置1,但是整个过程不需要自行操作,全部由regmap框架来完成的。
同理write_flag_mask用法也一样的,只是write_flag_mask用于写寄存器操作。
打开regmap-spi.c文件,这个文件就是regmap的spi总线文件,找到如下所示内容:
第101-110行初始化了一个regmap_bus实例:regmap_spi,重点看一下第107行中read_flag_mask默认为0X80。注意,这里是将regmap_bus的read_flag_mask成员变量设置为0X80。regmap_bus结构体大家自行查看一下,这里就不讲了。
第112-119行__regmap_init_spi函数,前面说了要想在spi总线中使用regmap框架,首先要使用regmap_init_spi函数用于并申请一个SPI总线的regmap。regmap_init_spi函数会调用这里的__regmap_init_spi函数,从第117行可以看出__regmap_init_spi函数只是对__regmap_init的简单封装,因此最终完成regmap申请并初始化的是__regmap_init函数。在__regmap_init函数中找到如下所示内容:
第812-817行就是用regmap_config中的读写掩码来初始化regmap_bus中的掩码。由于regmap_spi默认将read_flag_mask设置为0X80,当所使用的SPI设备不需要读掩码,在初始化regmap_config的时候一定要将read_flag_mask设置为0X00,并且也要将zero_flag_mask设置为true。
regmap框架就讲解到这里,接下来学习如何之前SPI驱动实验中编写的icm20608驱动改为regmap框架。
实验程序编写
修改设备结构体,添加regmap和regmap_config
regmap框架的核心就是regmap和regmap_config结构体,一般都是在自定义的设备结构体里面添加这两个类型的成员变量,所以首先在icm20608_dev结构体里面添加regmap和regmap_config。
只需要在icm20608_dev设备结构体中,添加regmap结构体变量指针regmap,以及regmap_config结构体变量regmap_config就可以了。
初始化regmap
一般在probe函数中初始化regmap,本章节就是icm20608_probe函数。
在原先的基础上,添加regmap_config的初始化,配置icm20608dev这个设备结构体的regmap_config成员变量就好了,设置reg_bits=8,val_bits=8,read_flag_mask=0x80。
然后配置icm20608dev的regmap变量,由regmap_init_spi来进行初始化配置SPI总线的regmap。
同理,需要注销的话就是在remove函数中,添加regmap_exit来注销就可以了。
读写设备内部寄存器
在read的操作函数中,可以直接通过regmap_read来进行寄存器读取;在write的函数中,通过regmap_write来写入。
在最后的readdata函数中,可以通过regmap_buld_read来进行多个寄存器的读取。
运行测试
测试APP直接用之前SPI驱动编写的icm20608App.c即可。测试方法也和之前一样,输入如下命令:
depmod //第一次加载驱动的时候需要运行此命令 modprobe icm20608.ko //加载驱动模块 ./icm20608App /dev/icm20608 //app 读取内部数据 |
如果regmap API工作正常,那么就会正确的初始化icm20608,并且读出传感器数据,结果和SPI驱动是一样的,如下图所示:
IIC总线的regmap框架基本和SPI一样,只是需要使用regmap_init_i2c来申请并初始化对应的regmap,同样都是使用regmap_read和regmap_write来读写I2C设备内部寄存器。
总结
Regmap就是对IIC、SPI总线的再次封装,可以通过regmap_init_xxx(xxx就是你的具体总线名称),然后通过regmap_read和regmap_write来进行单个寄存器的读写操作就可以了。
也就是说,之前的IIC和SPI总线的实验,需要自己去翻手册,然后对寄存器进行读写,如果使用Regmap,就可以用一样的函数来进行读写了,相当于代码复用不用重新编写了。
相关文章:

正点原子嵌入式linux驱动开发——Linux Regmap驱动
在前面学习I2C和SPI驱动的时候,针对I2C和SPI设备寄存器的操作都是通过相关的API函数进行操作的。这样Linux内核中就会充斥着大量的重复、冗余代码,但是这些本质上都是对寄存器的操作,所以为了方便内核开发人员统一访问I2C/SPI设备的时候&…...

京东商品详情API,页面信息采集,优惠券信息获取
京东开放平台提供了API接口来访问京东商品详情。通过这个接口,您可以获取到商品的详细信息,如商品名称、价格、库存量、描述等。额外还附加一个优惠券信息接口。代码如下: 京东获得JD商品详情 API 优惠券接口 公共参数 名称类型必须描述keyString是调…...

Visual Studio 2022 + OpenCV 4.5.2 安装与配置教程
目录 OpenCV的下载与配置Visual Studio 2022的配置新建工程新建文件新建项目属性表环境配置测试先写一个输出将OpenCV的动态链接库添加到项目的 x64 | Debug下测试配置效果 Other OpenCV的下载与配置 参考这个OpenCV的下载与环境变量的配置: Windows10CLionOpenCV4…...
docker 安装 mysql (单体架构)
文章归档:https://www.yuque.com/u27599042/coding_star/nckzqa73g47hgz3x 查询 MySQL 镜像 docker search mysql拉取 MySQL 镜像 docker pull mysql在宿主机创建映射目录 mkdir -p \ /home/docker/mysql/log \ /home/docker/mysql/data \ /home/docker/mysql/co…...

城市内涝怎么预警?万宾科技内涝积水监测仪
在城市运行过程中,城市内涝问题频繁出现,影响城市管理水平的提升,也会进一步减缓城市基础设施建设。尤其近几年来,城市内涝灾害频繁出现,在沿海地区内涝所带来的安全隐患成为城市应急管理部门的心头大患。城市内涝的背…...

Spring基础(2):放弃XML,走向注解
上一篇并没有实际地带大家去看源码,而是介绍了两个概念: BeanDefinitionBeanPostProcessor 当然,我介绍得非常笼统,不论是BeanDefinition还是BeanPostProcessor其实都有着较为复杂的继承体系,种类也很多。作为Spring…...

【线性代数】分块矩阵总结
...

Redis-命令操作Redis->redis简介,redis的安装(Linux版本windows版本),redis的命令
redis简介redis的安装(Linux版本&windows版本)redis的命令 1.redis简介 Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。 它支持字符串、哈…...

17、Python虚拟环境:为何要用虚拟环境、如何使用virtualenv
文章目录 在Python开发中,虚拟环境是一个独立的目录树,可以在其中安装Python模块。每个虚拟环境都有自己的Python二进制文件和一组安装的库。使用虚拟环境的主要原因是为了避免项目间的依赖冲突,允许每个项目有其特定的依赖,而不影响全局安装的模块。 为何要用虚拟环境 依…...
elasticSearch 接口实现查询热词统计
前面讲过使用elasticsearch可视化工具可以直接写语法查询如下: GET robot-demand/_search { "size":10, //查询多少条数据 "aggs":{ "hot_words":{ "terms":{ "field": "title" } }…...

10年测试经验分享:新手如何找到适合自己的软件测试项目?
每一个测试新手(特别是自学测试的人)来说,往往不知道到哪里去找项目练手,这应该是最大的困扰了。 实话讲,这个目前没有非常好的、直接的解决办法,不过在这我可以结合我自己之前的一些工作经历,…...
【MySQL】查询语句
文章目录 选择语句 / 子句比较运算符AND,OR,NOT运算符IN运算符BETWEEN运算符LIKE运算符REGEXP运算符 选择语句 / 子句 USE:选择使用的databaseSELECT:选择查询的列FROM:选择查询的表WHERE:条件查询ORDER B…...
金蝶云星空的网络控制设置
文章目录 金蝶云星空的网络控制设置说明网控参数加入网络控制清除网络控制清除网络控制(单个)清除网络控制(批量)清除网络控制(批量,参数是拼接好的业务对象) 金蝶云星空的网络控制设置 说明 …...

linux服务器国内源安装nvm,又快又方便
国内安装nvm的话,如果你的服务器不能访问github,那么使用gitee快速安装还是很方便的: # 能方位github的话,使用这条命令 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash# 不能访问github的话…...

noip模拟赛多校第八场 T3 遥控机器人 (最短路 + 技巧拆点)
题面 简要题意: 给你一个 n n n 个点 m m m 条边的图。边 i i i 有颜色 c i c_i ci。你可以选择一些边改变它们的颜色成为区间 [ 1 , m ] [1, m] [1,m] 中的任意颜色,改变一条边 i i i 一次的代价是 w i w_i wi。询问你能否在一些改变…...

高防IP的原理
高防IP,把域名解析到高防IP上(web事务只要把域名指向高防IP 即可。非web事务,把事务IP换成高防IP即可)一起在高防IP上设置转发规矩;所有公网流量都会走高防IP,通过端口协议转发的方法将用户的拜访通过高防IP转发到源站IP,一起将歹…...

Apache Doris (五十一): Doris数据缓存
🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1....
一、配置环境
一、配置Java环境 确保安装了Java开发工具包(JDK),并且设置了JAVA_HOME环境变量。 二、配置FFmpeg环境 如果使用了FFmpeg相关的功能,需要确保系统中已经安装了FFmpeg,并且设置了FFMPEG_HOME环境变量。 ffmpeg安装教…...
各种 sql 语句
sql 语句: SELECT max(val) as level_max_val from (select greatest(level1,level2,level3,level4,level5,level6,level7,level8,level9,level10) as val from kbt_2020cv52_data) k;...

CentOS/RHEL7环境下更改网卡名称为CentOS6的传统命名规则
图片 CentOS/RHEL7网卡命名规则介绍 图片 传统的Linux服务器网卡的名称命名方式是从eth0,eth1,eth2....这种方式命名的,但是这个编号往往不一定准确对应网卡接口的物理顺序,常规模式下我们使用的服务器设备可能只有一张网卡,若网卡较多的情…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...