Linux学习第58天:Regmap API 实验

news2024/11/15 11:21:11

Linux版本号4.1.15   芯片I.MX6ULL                                 大叔学Linux    品人间百味  思文短情长


本章思维导图如下:

一、Regmap API简介

1、什么是Regmap

        寄存器设置

        Linux 下使用 i2c_transfer 来读写 I2C 设备中的寄存器, SPI 接口的话使用 spi_write/spi_read等。

        基于代码复用的原则, Linux 内核引入了 regmap 模型, regmap 将寄存器访问的共同逻辑抽象出来,驱动开发人员不需要再去纠结使用 SPI 或者 I2C 接口 API 函数,统一使用 regmap API函数。这样的好处就是统一使用 regmap,降低了代码冗余,提高了驱动的可以移植性。

        通过 regmap 模型提供的统一接口函数来访问器件的寄存器, SOC 内部的寄存器也可以使用 regmap 接口函数来访问。

        种通用的接口来操作硬件寄存器。

        什么情况下会使用 regmap:

①、硬件寄存器操作,比如选用通过 I2C/SPI 接口来读写设备的内部寄存器,或者需要读写 SOC 内部的硬件寄存器。

②、提高代码复用性和驱动一致性,简化驱动开发过程。

③、减少底层 I/O 操作次数,提高访问效率。

2、Regmap驱动框架

1)框架结构体

2)结构体

51 struct regmap {
52 union {
53 struct mutex mutex;
54 struct {
55 spinlock_t spinlock;
56 unsigned long spinlock_flags;
57 };
58 };
59 regmap_lock lock;
60 regmap_unlock unlock;
61 void *lock_arg; /* This is passed to lock/unlock functions */
62
63 struct device *dev; /* Device we do I/O on */
64 void *work_buf; /* Scratch buffer used to format I/O */
65 struct regmap_format format; /* Buffer format */
66 const struct regmap_bus *bus;
67 void *bus_context;
68 const char *name;
69
70 bool async;
71 spinlock_t async_lock;
72 wait_queue_head_t async_waitq;
73 struct list_head async_list;
74 struct list_head async_free;
75 int async_ret;
......
89 unsigned int max_register;
/*
第 90~100 行有很多的函数以及 table,这些需
要驱动编写人员根据实际情况选择性的初始化, regmap 的初始化通过结构体 regmap_config 来
完成。
*/
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 const struct regmap_access_table *wr_table;
95 const struct regmap_access_table *rd_table;
96 const struct regmap_access_table *volatile_table;
97 const struct regmap_access_table *precious_table;
98
99 int (*reg_read)(void *context, unsigned int reg,
unsigned int *val);
100 int (*reg_write)(void *context, unsigned int reg,
unsigned int val);
......
147 struct rb_root range_tree;
148 void *selector_work_buf; /* Scratch buffer used for selector */
149 };

 3)regmap_config 结构体

         regmap_config 结构体就是用来初始化 regmap 的:

186 struct regmap_config {
187 const char *name;
188
189 int reg_bits;
190 int reg_stride;//第 190 行 reg_stride:寄存器地址步长。
191 int pad_bits;//第 191 行 pad_bits:寄存器和值之间的填充位数。
192 int val_bits;//第 192 行 val_bits:寄存器值位数,必填字段。
193
194 bool (*writeable_reg)(struct device *dev, unsigned int reg);//第 194 行 writeable_reg:可选的可写回调函数,寄存器可写的话此回调函数就会被调用,
并返回 true。
195 bool (*readable_reg)(struct device *dev, unsigned int reg);//第 195 行 readable_reg:可选的可读回调函数,寄存器可读的话此回调函数就会被调用,并
返回 true。
196 bool (*volatile_reg)(struct device *dev, unsigned int reg);//第 196 行 volatile_reg:可选的回调函数,当寄存器值不能缓存的时候此回调函数就会被调
用,并返回 true。
197 bool (*precious_reg)(struct device *dev, unsigned int reg);
/*
第 197 行 precious_reg:当寄存器值不能被读出来的时候此回调函数会被调用,比如很多中
断状态寄存器读清零,读这些寄存器就可以清除中断标志位,但是并没有读出这些寄存器内部
的值。
*/
198 regmap_lock lock;
199 regmap_unlock unlock;
200 void *lock_arg;
201
202 int (*reg_read)(void *context, unsigned int reg, unsigned int//第 202 行 reg_read:可选的读操作回调函数,所有读寄存器的操作此回调函数就会执行。
*val);
203 int (*reg_write)(void *context, unsigned int reg, unsigned int//第 203 行 reg_write:可选的写操作回调函数,所有写寄存器的操作此回调函数就会执行
val);
204
205 bool fast_io;//第 205 行 fast_io:快速 I/O,使用 spinlock 替代 mutex 来提升锁性能。
206
207 unsigned int max_register;//第 207 行 max_register:有效的最大寄存器地址,可选。
208 const struct regmap_access_table *wr_table;//第 208 行 wr_table:可写的地址范围,为 regmap_access_table 结构体类型。
209 const struct regmap_access_table *rd_table;
210 const struct regmap_access_table *volatile_table;
211 const struct regmap_access_table *precious_table;
212 const struct reg_default *reg_defaults;//第 212 行 reg_defaults:寄存器模式值,为 reg_default 结构体类型,此结构体有两个成员变
量: reg 和 def, reg 是寄存器地址, def 是默认值。
213 unsigned int num_reg_defaults;
214 enum regcache_type cache_type;
215 const void *reg_defaults_raw;
216 unsigned int num_reg_defaults_raw;//第 216 行 num_reg_defaults:默认寄存器表中的元素个数。
217
218 u8 read_flag_mask;//第 218 行 read_flag_mask:读标志掩码。
219 u8 write_flag_mask;//第 219 行 write_flag_mask:写标志掩码。
220
221 bool use_single_rw;
222 bool can_multi_write;
223
224 enum regmap_endian reg_format_endian;
225 enum regmap_endian val_format_endian;
226
227 const struct regmap_range_cfg *ranges;
228 unsigned int num_ranges;
229 };

3、Regmap操作函数

1)Regmap 申请与初始化

SPI 接口初始化函数为 regmap_init_spi,函数原型如下:

struct regmap * regmap_init_spi(struct spi_device *spi,
const struct regmap_

/*
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,不管是什么接口,全部使用 regmap_exit 这个函数来释放 regmap,函数原型如下:

void regmap_exit(struct regmap *map)
/*
map: 需要释放的 regmap
返回值:无。
*/

2)regmap 设备访问 API 函数



        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_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,写成功;其他值,写失败。
*/

        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,写成功;其他值,读失败。
*/

4、Regmap掩码设置

        使用 spi 接口的时候,读取 icm20608 寄存器的时候地址最高位必须置 1,写内部寄存器的是时候地址最高位要设置为 0。
        

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 }

        使用 regmap 的时候就不需要手动将寄存器地址的 bit7 置 1,由 regmap 框架自动来完成的.
        要想在 spi 总线中使用 regmap 框架,首先要使用 regmap_init_spi 函数用于并申请一个 SPI 总线的 regmap。从第 128 行可以看出regmap_init_spi 函数只是对 regmap_init 的简单封装,因此最终完成 regmap 申请并初始化的是regmap_init 函数。

105 static struct regmap_bus regmap_spi = {
106 .write = regmap_spi_write,
107 .gather_write = regmap_spi_gather_write,
108 .async_write = regmap_spi_async_write,
109 .async_alloc = regmap_spi_async_alloc,
110 .read = regmap_spi_read,
111 .read_flag_mask = 0x80,
112 .reg_format_endian_default = REGMAP_ENDIAN_BIG,
113 .val_format_endian_default = REGMAP_ENDIAN_BIG,
114 };
......
125 struct regmap *regmap_init_spi(struct spi_device *spi,
126 const struct regmap_config *config)
127 {
128 return regmap_init(&spi->dev, &regmap_spi, &spi->dev, config);
129 }

        regmap_init 函数中找到如下所示内容:

598 if (config->read_flag_mask || config->write_flag_mask) {
599 map->read_flag_mask = config->read_flag_mask;
600 map->write_flag_mask = config->write_flag_mask;
601 } else if (bus) {
602 map->read_flag_mask = bus->read_flag_mask;
603 }

/*
第 598~601 行就是用 regmap_config 中的读写掩码来初始化 regmap_bus 中的掩码。由于
regmap_spi 默认将 read_flag_mask 设置为 0X80,当你所使用的 SPI 设备不需要读掩码,在初始
化 regmap_config 的时候一定要将 read_flag_mask 设置为 0X00。
*/

二、驱动编写

1、修改设备结构体,添加 regmap 和 regmap_config


        regmap 框架的核心就是 regmapregmap_config 结构体,我们一般都是在自定义的设备结构体里面添加这两个类型的成员变量:

1 struct icm20608_dev {
2 struct spi_device *spi; /* spi 设备 */
3 dev_t devid; /* 设备号 */
4 struct cdev cdev; /* cdev */
5 struct class *class; /* 类 */
6 struct device *device; /* 设备 */
7 struct device_node *nd; /* 设备节点 */
8 signed int gyro_x_adc; /* 陀螺仪 X 轴原始值 */
9 signed int gyro_y_adc; /* 陀螺仪 Y 轴原始值 */
10 signed int gyro_z_adc; /* 陀螺仪 Z 轴原始值 */
11 signed int accel_x_adc; /* 加速度计 X 轴原始值 */
12 signed int accel_y_adc; /* 加速度计 Y 轴原始值 */
13 signed int accel_z_adc; /* 加速度计 Z 轴原始值 */
14 signed int temp_adc; /* 温度原始值 */
15 struct regmap *regmap;
/*
第 15 行, regmap 指针变量, regmap 我们需要使用 regmap_init_spi 函数来申请和初始化,
所以这里是指针类型
*/
16 struct regmap_config regmap_config;
17 };

2、初始化 regmap


         一般在 probe 函数中初始化 regmap:

1 static int icm20608_probe(struct spi_device *spi)
2 {
3 int ret;
4 struct icm20608_dev *icm20608dev;
5 6
/* 分配 icm20608dev 对象的空间 */
7 icm20608dev = devm_kzalloc(&spi->dev, sizeof(*icm20608dev),
GFP_KERNEL);
8 if(!icm20608dev)
9 return -ENOMEM;
10
11 /* 初始化 regmap_config 设置 

第 11~14 行, regmap_config 的初始化, icm20608 的寄存器地址长度为 8bit,寄存器值也是
8bit,因此 reg_bits 和 val_bits 都设置为 8。由于 icm20608 通过 SPI 接口读取的时候地址寄存器
最高位要设置为 1,因此 read_flag_mask 设置为 0X80。
*/
12 icm20608dev->regmap_config.reg_bits = 8; /* 寄存器长度 8bit */
13 icm20608dev->regmap_config.val_bits = 8; /* 值长度 8bit */
14 icm20608dev->regmap_config.read_flag_mask = 0x80; /* 读掩码 *//*第 17 行,通过 regmap_init_spi 函数来申请并初始化 SPI 总线的 regmap。*/
15
16 /* 初始化 IIC 接口的 regmap */
17 icm20608dev->regmap = regmap_init_spi(spi,
&icm20608dev->regmap_config);
18 if (IS_ERR(icm20608dev->regmap)) {
19 return PTR_ERR(icm20608dev->regmap);
20 }
21
22 /* 注册字符设备驱动 */
23 /* 1、创建设备号 */
24 ret = alloc_chrdev_region(&icm20608dev->devid, 0, ICM20608_CNT,
ICM20608_NAME);
25 if(ret < 0) {
26 pr_err("%s Couldn't alloc_chrdev_region, ret=%d\r\n",
ICM20608_NAME, ret);
27 goto del_regmap;
28 }
......
61
62 return 0;
63 destroy_class:
64 device_destroy(icm20608dev->class, icm20608dev->devid);
65 del_cdev:
66 cdev_del(&icm20608dev->cdev);
67 del_unregister:
68 unregister_chrdev_region(icm20608dev->devid, ICM20608_CNT);
69 del_regmap:
70 regmap_exit(icm20608dev->regmap);/*第 70 行,如果要删除 regmap 就使用 regmap_exit 函数。*/
71 return -EIO;
72 }

        icm20608_remove 函数:

1 static int icm20608_remove(struct spi_device *spi)
2 {
3 struct icm20608_dev *icm20608dev = spi_get_drvdata(spi);
4
......
12 /* 4、注销类 */
13 class_destroy(icm20608dev->class);
14 /* 5、删除 regmap */
15 regmap_exit(icm20608dev->regmap);/*第 17 行,卸载驱动的时候使用 regmap_exit 删除掉 probe 函数中申请的 regmap。*/
16 return 0;
17 }

3、读写设备内部寄存器


        直接使用 regmap_read、 regmap_write 等函数读写icm20608 内部寄存器。

1 /*
2 * @description : 读取 icm20608 指定寄存器值,读取一个寄存器
3 * @param – dev : icm20608 设备
4 * @param – reg : 要读取的寄存器
5 * @return : 读取到的寄存器值
6 */
7 static unsigned char icm20608_read_onereg(struct icm20608_dev *dev,
u8 reg)
8 {
9 u8 ret;
10 unsigned int data;
11
12 ret = regmap_read(dev->regmap, reg, &data);
13 return (u8)data;
14 }
15
16 /*
17 * @description : 向 icm20608 指定寄存器写入指定的值,写一个寄存器
18 * @param – dev : icm20608 设备
19 * @param – reg : 要写的寄存器
20 * @param – data : 要写入的值
21 * @return : 无
22 */
23
24 static void icm20608_write_onereg(struct icm20608_dev *dev, u8 reg,
u8 value)
25 {
26 regmap_write(dev->regmap, reg, value);
27 }
28
29 /*
30 * @description : 读取 ICM20608 的数据,读取原始数据,包括三轴陀螺仪、
31 * : 三轴加速度计和内部温度。
32 * @param - dev : ICM20608 设备
33 * @return : 无。

第 35~49 行, icm20608_readdata 函数用于读取 icm20608 内部陀螺仪、加速度计和温度计
的数据,从 ICM20_ACCEL_XOUT_H 寄存器开始,连续读取 14 个寄存器。这里直接使用
regmap_bulk_read 函数来显示多个寄存器的读取。
34 */
35 void icm20608_readdata(struct icm20608_dev *dev)
36 {
37 u8 ret;
38 unsigned char data[14];
39
40 ret = regmap_bulk_read(dev->regmap, ICM20_ACCEL_XOUT_H, data,
14);
41
42 dev->accel_x_adc = (signed short)((data[0] << 8) | data[1]);
43 dev->accel_y_adc = (signed short)((data[2] << 8) | data[3]);
44 dev->accel_z_adc = (signed short)((data[4] << 8) | data[5]);
45 dev->temp_adc = (signed short)((data[6] << 8) | data[7]);
46 dev->gyro_x_adc = (signed short)((data[8] << 8) | data[9]);
47 dev->gyro_y_adc = (signed short)((data[10] << 8) | data[11]);
48 dev->gyro_z_adc = (signed short)((data[12] << 8) | data[13]);
49 }

        采用 regmap API 以后驱动程序精简了很多。具体涉及到 SPI 总线的部分全部由 regmap 来处理了,驱动编写人员不用管,极大的方便了我们的驱动编写。而且驱动的可以执行提高了很多,即使将来更换为 IIC 接口,也只需要更改很少的一部分即可。

三、驱动测试


        输入如下命令:

depmod //第一次加载驱动的时候需要运行此命令
modprobe icm20608.ko //加载驱动模块
./icm20608App /dev/icm20608 //app 读取内部数据

   如果 regmap API 工作正常,那么就会正确的初始化 icm20608,并且读出传感器数据:

        IIC 总线的 regmap 框架基本和 SPI 一样,只是需要使用 regmap_init_i2c 来申请并初始化对应的 regmap,同样都是使用 regmap_read 和 regmap_write 来读写 I2C 设备内部寄存器。
 


本笔记为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,未经允许不得用于商业用途。

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

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

相关文章

Java:设计模式(单例,工厂,代理,命令,桥接,观察者)

模式是一条由三部分组成的通用规则&#xff1a;它代表了一个特定环境、一类问题和一个解决方案之间的关系。每一个模式描述了一个不断重复发生的问题&#xff0c;以及该问题解决方案的核心设计。 软件领域的设计模式定义&#xff1a;设计模式是对处于特定环境下&#xff0c;经常…

Spring统一功能处理:拦截器、响应与异常的统一管理

目录 一.拦截器 二.统一数据返回格式 三.统一异常处理 一.拦截器 拦截器是Spring框架提供的核⼼功能之⼀&#xff0c;主要⽤来拦截⽤⼾的请求&#xff0c;在指定⽅法前后&#xff0c;根据业务需要执⾏预先设定的代码。 也就是说&#xff0c;允许开发⼈员提前预定义⼀些逻辑…

全球情境感知计算市场规划预测:未来六年CAGR为17.0%

随着全球数字化转型的加速和物联网技术的广泛应用&#xff0c;情境感知计算作为一种能够理解和响应环境变化的智能技术&#xff0c;正逐渐受到更多关注。本文旨在通过深度分析情境感知计算行业的各个维度&#xff0c;揭示行业发展趋势和潜在机会。 【市场趋势的演变】 1. 市场…

C++——string类及其使用

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件iostream的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

体系结构论文导读(三十一)(上):Soft errors in DNN accelerators: A comprehensive review

Soft errors in DNN accelerators: A comprehensive review DNN 加速器中的软错误&#xff1a;全面回顾 一、文章核心 深度学习任务覆盖了广泛应用。DNN算法被实现于不同系统上&#xff0c;从小型嵌入式设备到数据中心。DNN加速器&#xff08;例如GPU、FPGA、ASIC&#xff0…

JetBrains:Wrong tag。注释告警

报错信息如下&#xff1a; Wrong tag ‘copyright:’ &#xff0c;这个是alt enter 选择 Add copyright:to custom tags&#xff0c;虽然能解决问题&#xff0c;如果创建一个新项目又回出现这个告警提示。 其实这个问题的就是这个在Java Doc里面不存在&#xff0c;才会出现这…

Bugku-CTF-聪明的php

pass a parameter and maybe the flag files filename is random :> 传递一个参数&#xff0c;可能标记文件的文件名是随机的: 于是传一下参&#xff0c;在原网页后面加上/?a1,发现网页出现了变化 3.传入参数&#xff0c;一般情况下是文件包含&#xff0c;或者命令执行&…

linux安装weblogic

文章目录 weblogic是干什么用的weblogic安装前置条件1. 安装jdk2.安装weblogic2.1.创建用户组及用户2.2.切换用户上传安装jar包到目录下&#xff0c;配置文件进行安装准备配置文件2.3保证安装配置文件和安装jar包在同一目录&#xff0c;执行安装命令 3. 创建域来启动页面3.1 构…

Science Robotics 封面论文:美国宇航局喷气推进实验室开发了自主蛇形机器人,用于冰雪世界探索

人们对探索冰冷的卫星&#xff08;如土卫二&#xff09;的兴趣越来越大&#xff0c;这可能具有天体生物学意义。然而&#xff0c;由于地表或冰口内的环境极端&#xff0c;获取样本具有挑战性。美国宇航局的喷气推进实验室正在开发一种名为Exobiology Extant Life Surveyor&…

【分巧克力】

题目 代码 #include<bits/stdc.h> using namespace std;const int N 1e510; int n, k; int h[N], w[N]; bool check(int mid) {int cnt 0;for(int i 1; i < n; i){cnt (h[i] / mid) * (w[i] / mid); //切块一定是切出长方形洞才最省料&#xff0c;这样的话能切几…

等保测评练习卷27

等级保护初级测评师试题27 姓名&#xff1a; 成绩&#xff1a; 一、判断题&#xff08;10110分&#xff09; 1.对于大型物联网来说&#xff0c;处理应用层一般由云计算平台和业务应用终端设备构成。&#xff08; T &#xff09; …

企业数据接口:股权穿透

支持查询公司名称&#xff0c;股权路径&#xff0c;股东出资比例&#xff0c;层级等信息&#xff0c;呈现出公司多层次股权结构&#xff0c;高效理清企业投资股权关系

部署服务器项目及发布

当技术总监直接丢给我一个服务器账号密码时&#xff0c;我该怎么完成映射本机&#xff1b;配置网关&#xff1b;配置代理和发布项目呢&#xff1f; 我使用的是putty远程登录到服务器 输入ip后&#xff0c;点open 输入账号密码 登录的账号如果不是root&#xff1b;使用sudo su…

表中记录的操作

一、查询表中的记录 二、在表中插入记录&#xff0c;删除记录&#xff0c;修改记录 三、常用的运算符 四、数据类型

string.format()拼接参数

string.format()拼接参数 private static void testString() {String queryParams String.format("?pwdErrNum%s&userSts%s&lockSts%s", 123, 1, 1);System.out.println(queryParams);}打印结果

事务的原理(学习笔记)

redo log 如果没有redo log 我们在执行完增删改查语句后会将脏页直接刷新到磁盘中&#xff0c;此时用户事务已经提交&#xff0c;一旦刷新失败则无法修复数据。如果不适用redo log 还会存在性能问题&#xff0c;事务中的一组操作都是随机操作数据页&#xff0c;涉及到大量随机…

DeepSeek Coder V2开源发布,首超GPT4-Turbo的代码能力

击败GPT4-Turbo&#xff0c;最强开源代码模型DeepSeek-Coder-V2问世&#xff5c;SiliconCloud上新 6月17日&#xff0c;深度求索正式开源了DeepSeek-Coder-V2模型。 根据相关评测榜单&#xff0c;这是全球首个在代码、数学能力上超越GPT-4-Turbo、Claude3-Opus、Gemini-1.5Pro…

DolphinDB 编程进阶:掌握这十个细节,让你的代码更出色

众所周知&#xff0c;编程细节不仅关乎代码的美观与整洁&#xff0c;更是确保软件质量、提升开发效率、减少维护成本以及保障系统稳定性的基石。 今天和大家分享的内容是&#xff1a;使用 DolphinDB 编程时&#xff0c;十个常被忽略但至关重要的细节。本文涵盖了元编程技巧、数…

攻防演练号角吹响,聚铭铭察高级威胁检测系统助您零失分打赢重保攻坚战

在数字化浪潮中&#xff0c;攻防演练成为了衡量网络安全防御力的核心标尺&#xff0c;其重要性与日俱增。这项由政府、行业监管或企业内部主导的安全活动&#xff0c;随着互联网普及而兴起&#xff0c;现已发展成为全球公认的检验网络安全体系效能的标准。它不仅关乎技术实力的…

JaCoCo - Java Code Coverage Library

概述 JaCoCo&#xff08;Java Code Coverage&#xff09;是一个开源的Java代码覆盖率库。它可以帮助开发人员测量单元测试和集成测试中代码的覆盖情况。通过使用JaCoCo&#xff0c;开发人员可以识别哪些代码没有被测试覆盖&#xff0c;从而提高代码的质量和可靠性。 功能 1.…