蓝牙墨水屏上位机学习(3)

main.js中sendimg()函数学习,对应发送图片按钮

函数代码如下:

async function sendimg() {const canvasSize = document.getElementById('canvasSize').value;const ditherMode = document.getElementById('ditherMode').value;const epdDriverSelect = document.getElementById('epddriver');const selectedOption = epdDriverSelect.options[epdDriverSelect.selectedIndex];if (selectedOption.getAttribute('data-size') !== canvasSize) {addLog(`画布尺寸和驱动不匹配,请重新选择。`);return;}if (selectedOption.getAttribute('data-color') !== ditherMode) {addLog(`颜色模式和驱动不匹配,请重新选择。`);return;}startTime = new Date().getTime();const status = document.getElementById("status");status.parentElement.style.display = "block";const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);const processedData = processImageData(imageData);updateButtonStatus(true);if (ditherMode === 'fourColor') {await writeImage(processedData, 'color');} else if (ditherMode === 'threeColor') {const halfLength = Math.floor(processedData.length / 2);await writeImage(processedData.slice(0, halfLength), 'bw');await writeImage(processedData.slice(halfLength), 'red');} else if (ditherMode === 'blackWhiteColor') {await writeImage(processedData, 'bw');} else {addLog("当前固件不支持此颜色模式。");updateButtonStatus();return;}await write(EpdCmd.REFRESH);updateButtonStatus();const sendTime = (new Date().getTime() - startTime) / 1000.0;addLog(`发送完成!耗时: ${sendTime}s`);setStatus(`发送完成!耗时: ${sendTime}s`);addLog("屏幕刷新完成前请不要操作。");setTimeout(() => {status.parentElement.style.display = "none";}, 5000);
}

电子纸图像发送函数 sendimg() 详解

这个 sendimg() 函数实现了通过蓝牙向电子纸显示设备发送图像数据的核心功能。它处理图像预处理、数据分块传输和屏幕刷新命令,是电子纸显示系统的关键部分。下面我将详细解析其功能和实现逻辑。

函数整体功能

sendimg() 函数的主要工作流程:

  1. 验证用户选择的画布尺寸、颜色模式与电子纸驱动是否匹配
  2. 从 Canvas 获取图像数据并进行预处理(如抖动处理)
  3. 根据不同的颜色模式(黑白 / 三色 / 四色)组织和发送数据
  4. 发送屏幕刷新命令触发电子纸更新显示
  5. 记录发送时间并显示操作结果

代码逻辑详解

1. 参数验证与初始化
const canvasSize = document.getElementById('canvasSize').value;
const ditherMode = document.getElementById('ditherMode').value;
const epdDriverSelect = document.getElementById('epddriver');
const selectedOption = epdDriverSelect.options[epdDriverSelect.selectedIndex];// 验证画布尺寸与驱动是否匹配
if (selectedOption.getAttribute('data-size') !== canvasSize) {addLog(`画布尺寸和驱动不匹配,请重新选择。`);return;
}
// 验证颜色模式与驱动是否匹配
if (selectedOption.getAttribute('data-color') !== ditherMode) {addLog(`颜色模式和驱动不匹配,请重新选择。`);return;
}// 记录开始时间并显示状态
startTime = new Date().getTime();
const status = document.getElementById("status");
status.parentElement.style.display = "block";


 补充javascript知识:

HTML DOM Document 对象

HTML DOM 节点
在 HTML DOM (Document Object Model) 中 , 每一个元素都是 节点:

文档是一个文档。
所有的HTML元素都是元素节点。
所有 HTML 属性都是属性节点。
文本插入到 HTML 元素是文本节点。are text nodes。
注释是注释节点。
Document 对象
当浏览器载入 HTML 文档, 它就会成为 document 对象。

document 对象是HTML文档的根节点与所有其他节点(元素节点,文本节点,属性节点, 注释节点)。

Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。

提示:Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问。

Document 对象属性和方法
HTML文档中可以使用以上属性和方法:

属性 / 方法       描述
document.activeElement    返回当前获取焦点元素
document.addEventListener()    向文档添加句柄
document.adoptNode(node)    从另外一个文档返回 adapded 节点到当前文档。
document.anchors    返回对文档中所有 Anchor 对象的引用。
document.applets    返回对文档中所有 Applet 对象的引用。
document.baseURI    返回文档的绝对基础 URI
document.body    返回文档的body元素
document.close()    关闭用 document.open() 方法打开的输出流,并显示选定的数据。
document.cookie    设置或返回与当前文档有关的所有 cookie。
document.createAttribute()    创建一个属性节点
document.createComment()    createComment() 方法可创建注释节点。
document.createDocumentFragment()    创建空的 DocumentFragment 对象,并返回此对象。
document.createElement()    创建元素节点。
document.createTextNode()    创建文本节点。
document.doctype    返回与文档相关的文档类型声明 (DTD)。
document.documentElement    返回文档的根节点
document.documentMode    返回用于通过浏览器渲染文档的模式
document.documentURI    设置或返回文档的位置
document.domain    返回当前文档的域名。
document.domConfig    返回normalizeDocument()被调用时所使用的配置
document.embeds    返回文档中所有嵌入的内容(embed)集合
document.forms    返回对文档中所有 Form 对象引用。
document. getElementsByClassName()    返回文档中所有指定类名的元素集合,作为 NodeList 对象。
document.getElementById()    返回对拥有指定 id 的第一个对象的引用。
document.getElementsByName()    返回带有指定名称的对象集合。
document.getElementsByTagName()    返回带有指定标签名的对象集合。
document.images    返回对文档中所有 Image 对象引用。
document.implementation    返回处理该文档的 DOMImplementation 对象。
document.importNode()    把一个节点从另一个文档复制到该文档以便应用。
document.inputEncoding    返回用于文档的编码方式(在解析时)。
document.lastModified    返回文档被最后修改的日期和时间。
document.links    返回对文档中所有 Area 和 Link 对象引用。
document.normalize()    删除空文本节点,并连接相邻节点
document.normalizeDocument()    删除空文本节点,并连接相邻节点的
document.open()    打开一个流,以收集来自任何 document.write() 或 document.writeln() 方法的输出。
document.querySelector()    返回文档中匹配指定的CSS选择器的第一元素
document.querySelectorAll()    document.querySelectorAll() 是 HTML5中引入的新方法,返回文档中匹配的CSS选择器的所有元素节点列表
document.readyState    返回文档状态 (载入中……)
document.referrer    返回载入当前文档的文档的 URL。
document.removeEventListener()    移除文档中的事件句柄(由 addEventListener() 方法添加)
document.renameNode()    重命名元素或者属性节点。
document.scripts    返回页面中所有脚本的集合。
document.strictErrorChecking    设置或返回是否强制进行错误检查。
document.title    返回当前文档的标题。
document.URL    返回文档完整的URL
document.write()    向文档写 HTML 表达式 或 JavaScript 代码。
document.writeln()    等同于 write() 方法,不同的是在每个表达式之后写一个换行符。


 其中:document.getElementById()   返回对拥有指定 id 的第一个对象的引用。

sendimg()函数的第一行代码:

const canvasSize = document.getElementById('canvasSize').value;

1. document : document 是浏览器提供的一个全局对象,代表当前加载的 HTML 文档。通过这个对象,可以访问和操作文档中的所有元素。
2. getElementById('canvasSize') :这是 document 对象的一个方法,用于通过元素的 id 属性来查找文档中的元素。在这里,它会查找 id 为 canvasSize 的元素。如果找到了该元素,则返回对应的 DOM 元素对象;如果未找到,则返回 null 。
3. .value :这是访问 DOM 元素的 value 属性,通常用于获取表单元素(如 <input> 、 <select> 、 <textarea> 等)的当前值。
4. const canvasSize :使用 const 关键字声明一个常量 canvasSize ,并将 id 为 canvasSize 的元素的 value 属性值赋给它。 const 声明的常量一旦赋值就不能再重新赋值。
### 示例场景
假设 HTML 文档中有如下代码:

```
<input type="number" id="canvasSize" value="800">
```
当执行 const canvasSize = document.getElementById('canvasSize').value; 时, canvasSize 的值将是字符串 "800" 。

在index.html中找到如下 代码:

<select id="canvasSize" onchange="updateCanvasSize()"><option value="1.54_152_152">1.54 (152x152)</option><option value="1.54_200_200">1.54 (200x200)</option><option value="2.13_212_104">2.13 (212x104)</option><option value="2.13_250_122">2.13 (250x122)</option><option value="2.66_296_152">2.66 (296x152)</option><option value="2.9_296_128">2.9 (296x128)</option><option value="2.9_384_168">2.9 (384x168)</option><option value="3.5_384_184">3.5 (384x184)</option><option value="3.7_416_240">3.7 (416x240)</option><option value="3.97_800_480">3.97 (800x480)</option><option value="4.2_400_300" selected>4.2 (400x300)</option><option value="5.79_792_272">5.79 (792x272)</option><option value="7.5_800_480">7.5 (800x480)</option><option value="10.2_960_640">10.2 (960x640)</option><option value="10.85_1360_480">10.85 (1360x480)</option><option value="11.6_960_640">11.6 (960x640)</option><option value="4E_600_400">4E (600x400)</option><option value="7.3E6">7.3E6 (480x800)</option></select>

html语法中<select>标签用法如下 :

如:

<!DOCTYPE html>
<html>
<head> 
<meta charset="utf-8"> 
<title>菜鸟教程(runoob.com)</title> 
</head>
<body><select><option value="volvo">Volvo</option><option value="saab">Saab</option><option value="opel">Opel</option><option value="audi">Audi</option>
</select></body>
</html>

 运行结果是

这是一个下拉选择框。

sendimg()函数的第二行代码:

const ditherMode = document.getElementById('ditherMode').value//抖动模式

1. document : document 是浏览器提供的全局对象,代表当前加载的 HTML 文档。借助该对象,你能访问和操作文档里的所有元素。
2. getElementById('ditherMode') :这是 document 对象的一个方法,作用是通过元素的 id 属性在文档里查找对应的元素。若找到了 id 为 ditherMode 的元素,就会返回对应的 DOM 元素对象;若未找到,则返回 null 。
3. .value :这是在访问 DOM 元素的 value 属性,通常用于获取表单元素(如 <input> 、 <select> 、 <textarea> 等)的当前值。
4. const ditherMode :使用 const 关键字声明一个常量 ditherMode ,并把 id 为 ditherMode 的元素的 value 属性值赋给它。 const 声明的常量一旦赋值,就不能再重新赋值。
### 示例场景
假设 HTML 文档中有如下代码:

```
<select id="ditherMode">
<option value="none">无抖动</option>
<option value="floyd-steinberg" selected>弗洛伊德 - 斯坦伯格抖动</option>
<option value="ordered">有序抖动</option>
</select>
```
当执行 const ditherMode = document.getElementById('ditherMode').value; 时, ditherMode 的值会是字符串 "floyd-steinberg" ,因为该选项当前处于选中状态。

在index.html中找到如下 代码:

<select id="ditherMode" onchange="updateImage(false)"><option value="blackWhiteColor">双色(黑白)</option><option value="threeColor">三色(黑白红)</option><option value="fourColor">四色(黑白红黄)</option><option value="sixColor">六色(黑白红黄蓝绿)</option></select>

sendimg()函数的第三行代码:

 const epdDriverSelect = document.getElementById('epddriver');

1. const :这是 ES6 引入的关键字,用于声明一个常量。常量一旦被赋值,在其作用域内就不能再被重新赋值。
2. epdDriverSelect :这是声明的常量名称,推测该常量可能用于表示与电子纸驱动(EPD Driver)相关的选择器。
3. document : document 是浏览器提供的全局对象,代表当前加载的 HTML 文档。借助这个对象,你可以访问和操作文档中的所有元素。
4. getElementById('epddriver') :这是 document 对象的一个方法,作用是通过元素的 id 属性在文档中查找对应的元素。如果找到了 id 为 epddriver 的元素,就会返回对应的 DOM 元素对象;如果没找到,则返回 null 。
### 示例场景
假设 HTML 文档中有如下代码:

```
<select id="epddriver">
<option value="driver1">驱动 1</option>
<option value="driver2">驱动 2</option>
</select>
```
当执行 const epdDriverSelect = document.getElementById('epddriver'); 时, epdDriverSelect 就会指向这个 <select> 元素,后续可以通过这个常量对该元素进行操作,比如获取或修改其值、添加事件监听器等。



1. 什么是 HTML DOM?
HTML DOM 是浏览器将 HTML 文档解析为一个树形结构的编程接口。它将文档中的每个部分(如元素、属性、文本等)表示为节点(Node),这些节点共同组成了 DOM 树。通过 DOM,开发者可以使用 JavaScript 动态地操作网页内容。

DOM 树的结构
DOM 树由多个节点组成,常见的节点类型包括:

文档节点(Document):整个文档的根节点。
元素节点(Element):HTML 标签(如 <div>、<p> 等)。
属性节点(Attribute):HTML 元素的属性(如 class、id 等)。
文本节点(Text):元素中的文本内容。
注释节点(Comment):HTML 文档中的注释。



在Index.html中找到如下 代码:

<select id="epddriver" onchange="updateDitcherOptions()"><option value="01" data-color="blackWhiteColor" data-size="4.2_400_300">UC8176/UC8276(黑白)</option><option value="03" data-color="threeColor" data-size="4.2_400_300">UC8176/UC8276(三色)</option><option value="04" data-color="blackWhiteColor" data-size="4.2_400_300">SSD1619/SSD1683(黑白)</option><option value="02" data-color="threeColor" data-size="4.2_400_300">SSD1619/SSD1683(三色)</option><option value="05" data-color="fourColor" data-size="4.2_400_300">JD79668(四色)</option></select>

代码第4行

const selectedOption = epdDriverSelect.options[epdDriverSelect.selectedIndex];

代码解析:获取选中的电子纸驱动选项

这行代码从 HTML 的下拉选择框(<select>)中获取用户当前选中的电子纸驱动选项,是前端开发中处理表单选择的典型操作。下面我将详细解析其功能和实现逻辑。

代码功能详解

1. 获取 select 元素引用
const epdDriverSelect = document.getElementById('epddriver');
  • 作用:获取 ID 为 epddriver 的 HTML 元素引用
  • 典型 HTML 结构

    <select id="epddriver"><option value="epd213b" data-size="128x296" data-color="blackWhiteColor">2.13" 黑白</option><option value="epd213c" data-size="128x296" data-color="threeColor">2.13" 三色</option><option value="epd42" data-size="400x300" data-color="blackWhiteColor">4.2" 黑白</option>
    </select>
    
2. 获取选中的选项索引
epdDriverSelect.selectedIndex

  • selectedIndex 属性:返回当前选中选项的索引值(从 0 开始)
  • 示例:如果用户选择了 "2.13" 三色 ",则 selectedIndex 为 1
3. 获取选中的选项元素
const selectedOption = epdDriverSelect.options[epdDriverSelect.selectedIndex];

  • options 属性:是一个类数组对象,包含所有 <option> 子元素
  • 最终结果selectedOption 指向用户当前选中的 <option> 元素

关键属性与应用场景

1. 常用的 <option> 属性
  • value:选项的值(如 "epd213b"
  • text:显示给用户的文本(如 "2.13" 黑白"
  • 自定义数据属性
    • data-size:兼容的画布尺寸(如 "128x296"
    • data-color:支持的颜色模式(如 "blackWhiteColor"
2. 在电子纸系统中的应用

获取选中的驱动选项后,通常会读取其自定义数据属性进行验证:

// 验证画布尺寸与驱动是否匹配
if (selectedOption.getAttribute('data-size') !== canvasSize) {addLog(`画布尺寸和驱动不匹配,请重新选择。`);return;
}// 验证颜色模式与驱动是否匹配
if (selectedOption.getAttribute('data-color') !== ditherMode) {addLog(`颜色模式和驱动不匹配,请重新选择。`);return;
}

代码示例与交互逻辑

下面是一个完整的示例,展示如何监听驱动选择变化并动态更新 UI:

javascript

// 获取select元素
const driverSelect = document.getElementById('epddriver');// 监听选择变化事件
driverSelect.addEventListener('change', function() {const selectedOption = this.options[this.selectedIndex];// 获取驱动信息const driverValue = selectedOption.value;const driverName = selectedOption.text;const supportedSize = selectedOption.getAttribute('data-size');const supportedColor = selectedOption.getAttribute('data-color');// 更新UI显示document.getElementById('driverInfo').textContent = `已选择: ${driverName}支持尺寸: ${supportedSize}支持颜色: ${supportedColor}`;// 自动调整画布尺寸(可选)resizeCanvas(supportedSize);
});// 初始化显示当前选择
function initDriverInfo() {const event = new Event('change');driverSelect.dispatchEvent(event);
}// 页面加载后初始化
window.addEventListener('DOMContentLoaded', initDriverInfo);

常见问题与最佳实践

1. 常见错误
  • 未选择任何选项selectedIndex 为 -1,需添加检查
  • 属性拼写错误:如 data-size 写成 dataSize
  • 兼容性问题:旧版浏览器可能不支持某些属性
2. 最佳实践
  • 添加默认选项:确保 select 有一个默认选中项

    html

    预览

    <option value="" selected disabled>请选择驱动</option>
    

  • 使用 dataset 属性:更简洁地访问自定义数据属性

    javascript

    const supportedSize = selectedOption.dataset.size; // 代替 getAttribute
    

  • 实时验证:在用户选择变化时立即验证,而不是等到提交时

通过这行代码,系统能够准确获取用户选择的电子纸驱动信息,并据此进行后续的数据处理和验证,确保图像数据能正确适配目标硬件。

  • 关键验证点:确保用户选择的画布尺寸(如 200×200)和颜色模式(如黑白、三色)与电子纸驱动支持的参数一致,避免因不匹配导致显示异常。

2. 图像数据处理

javascript

// 从Canvas获取原始图像数据
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 处理图像数据(如转换为适合电子纸的格式、应用抖动算法)
const processedData = processImageData(imageData);// 禁用按钮防止重复操作
updateButtonStatus(true);

  • processImageData() 函数
    • 将 RGB/A 图像数据转换为电子纸支持的颜色空间
    • 应用抖动算法(如 Floyd-Steinberg)减少颜色位数
    • 为不同的电子纸驱动格式优化数据排列
3. 根据颜色模式发送数据

javascript

if (ditherMode === 'fourColor') {await writeImage(processedData, 'color');
} else if (ditherMode === 'threeColor') {// 三色模式需要分两次发送:黑白数据和红色数据const halfLength = Math.floor(processedData.length / 2);await writeImage(processedData.slice(0, halfLength), 'bw');await writeImage(processedData.slice(halfLength), 'red');
} else if (ditherMode === 'blackWhiteColor') {await writeImage(processedData, 'bw');
} else {addLog("当前固件不支持此颜色模式。");updateButtonStatus();return;
}

  • 多色模式处理
    • 三色电子纸通常需要分别发送黑白层和红色层数据
    • 四色模式则一次性发送所有颜色数据
    • 不同模式调用 writeImage() 函数时会传递不同的参数(如 'bw' 表示黑白数据)
4. 发送刷新命令与状态更新

javascript

// 发送刷新命令,触发电子纸物理刷新
await write(EpdCmd.REFRESH);
updateButtonStatus();// 计算发送耗时并显示结果
const sendTime = (new Date().getTime() - startTime) / 1000.0;
addLog(`发送完成!耗时: ${sendTime}s`);
setStatus(`发送完成!耗时: ${sendTime}s`);
addLog("屏幕刷新完成前请不要操作。");// 5秒后隐藏状态显示
setTimeout(() => {status.parentElement.style.display = "none";
}, 5000);

  • 刷新命令EpdCmd.REFRESH 是一个特殊指令,通知电子纸控制器根据接收到的图像数据更新物理显示。
  • 时间记录:精确计算数据发送耗时,帮助用户评估系统性能。

关键函数解析

1. writeImage(data, type)

这个函数负责将图像数据分块发送到电子纸设备:

javascript

async function writeImage(data, type) {const chunkSize = 20; // 每包20字节(受蓝牙MTU限制)const cmd = type === 'bw' ? EpdCmd.WRITE_BW : type === 'red' ? EpdCmd.WRITE_RED : EpdCmd.WRITE_COLOR;// 发送开始命令await write(cmd);// 分块发送数据for (let i = 0; i < data.length; i += chunkSize) {const chunk = data.slice(i, i + chunkSize);await write(chunk);// 更新进度显示const percent = ((i / data.length) * 100).toFixed(1);setStatus(`发送中: ${percent}%`);}// 发送结束命令await write(EpdCmd.END_DATA);
}

  • 数据分块:将大图像数据拆分为小数据包(通常≤20 字节),适应蓝牙低功耗的传输限制
  • 命令类型:根据数据类型(黑白 / 红色 / 彩色)发送不同的命令前缀
  • 进度反馈:实时更新 UI 显示发送进度,提升用户体验
2. write(data)

这个底层函数负责通过蓝牙发送数据:

javascript

async function write(data) {if (!epdCharacteristic) {throw new Error('未连接到电子纸特征');}// 将数据转换为ArrayBufferconst buffer = data instanceof ArrayBuffer ? data : typeof data === 'number' ? new Uint8Array([data]).buffer : new TextEncoder().encode(data.toString()).buffer;// 写入数据到蓝牙特征return await epdCharacteristic.writeValueWithResponse(buffer);
}

  • 数据格式转换:支持多种数据类型(数字、字符串、ArrayBuffer),统一转换为蓝牙可传输的格式
  • 带响应的写入:使用 writeValueWithResponse() 确保数据可靠传输

电子纸显示原理补充

电子纸(如 E Ink)与传统显示屏的区别:

  1. 双稳态特性:刷新后无需持续供电即可保持显示内容
  2. 低刷新频率:刷新过程较慢(通常需要 1-2 秒),但功耗极低
  3. 特殊驱动要求
    • 需要特定的波形驱动信号才能正确显示
    • 不同颜色模式(黑白、三色、四色)需要不同的数据格式和处理方式

优化建议

  1. 增加数据校验机制

    • 在发送大块数据后,添加 CRC 校验确保数据完整性
    • 实现错误重传机制,提高可靠性
  2. 优化刷新流程

    • 实现部分刷新功能,仅更新屏幕变化区域
    • 根据显示内容智能选择刷新模式(如快速刷新或高质量刷新)
  3. 增强用户反馈

    • 添加视觉指示器显示电子纸刷新状态
    • 提供刷新完成的声音提示或震动反馈
  4. 性能优化

    • 实现数据压缩算法,减少传输时间
    • 优化蓝牙 MTU(最大传输单元),提高单次传输数据量

这个函数实现了电子纸图像传输的核心逻辑,通过合理组织数据和控制传输流程,确保图像能正确、高效地显示在电子纸设备上。

编辑

分享

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

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

相关文章

Linux应用基础

1. 基础概念 1.1 系统调用 系统调用实际上是Linux内核为上层应用程序提供的API接口&#xff0c;方便应用程序进行调用&#xff0c;类似于SVC。 1.2 库函数 库函数是应用层里边的东西&#xff0c;在系统调用的上层&#xff0c;通常以动态库文件&#xff08;.so&#xff09;形式…

【时间序列数据处理的噩梦与救赎:一次复杂数据可视化问题的深度复盘】

时间序列数据处理的噩梦与救赎&#xff1a;一次复杂数据可视化问题的深度复盘 创建时间: 2025/7/3 技术栈: Vue 3 TypeScript UniApp ECharts 问题级别: &#x1f534; 系统性架构问题 &#x1f3af; 引言&#xff1a;当简单需求变成技术噩梦 “老哥&#xff0c;这个图表时…

Redis--黑马点评--基于stream消息队列的秒杀优化业务详解

基于redis的stream结构作为消息队列&#xff0c;实现异步秒杀下单 需求&#xff1a; 创建一个Stream类型的消息队列&#xff0c;名为stream.oreders 修改之前的秒杀下单Lua脚本&#xff0c;在认定有抢够资格后&#xff0c;直接向stream.orders中添加消息&#xff0c;内容包括…

Zephyr RTOS 防止中断影响数据写入

目录 概述 1 中断保护核心策略 1.1 中断锁定/解锁 (IRQ Locking) 1.2 自旋锁 (Spin Locks) 2 高级保护技术 2.1 双重缓冲技术 2.2 RCU (Read-Copy-Update) 模式 3 中断安全数据写入模式 3.1 FIFO队列保护 3.2 原子操作保护 4 性能优化策略 4.1 分区数据保护 4.2 中断…

Hinge×亚矩云手机:以“深度连接”为名,重构云端社交的“真实感”

当传统婚恋社交应用困于“浅层匹配”“硬件性能瓶颈”与“信任成本高企”&#xff0c;当Z世代对“灵魂共鸣、沉浸体验、隐私安全”的需求愈发迫切&#xff0c;以“设计让你删除的应用”为理念的Hinge&#xff0c;正携手亚矩云手机开启一场“云端深度社交革命”——用云端算力破…

OpenSSL 内存泄漏修复全景:119 个历史 Commit 的类型分析与防御启示

1 前言 openssl 开源库作为 C/C 项目中常用的组件库&#xff0c;截至 2025年7月4日 &#xff0c;openssl 的提交记录包含 119 个 Fix memory leak 。 本文基于源码 Commit 分析&#xff0c;揭示了 OpenSSL 内存泄漏修复从被动应对到主动防御的演进趋势&#xff0c;给各位 C/C…

十一、Python 3.13 的新特性和更新内容

1. 性能提升 1.1 解释器性能优化 更快的启动速度&#xff1a;Python 3.13 启动时间比 3.12 快约 10-15%。内存使用优化&#xff1a;减少了内存占用&#xff0c;特别是在处理大型数据结构时。 1.2 字节码优化 新的字节码指令&#xff1a;引入了更高效的字节码指令&#xff0…

后端 Maven打包 JAR 文件、前端打包dist文件、通过后端服务访问前端页面、Nginx安装与部署

打包 JAR 文件通常使用 Maven 或 Gradle 构建工具&#xff08;Spring Boot 项目默认推荐 Maven&#xff09;。以下是详细步骤和常见问题解答&#xff1a; 一、后端 Maven打包 JAR 文件 1. 确保项目是 Spring Boot 项目 项目结构应包含 pom.xml&#xff08;Maven 配置文件&am…

大数据系列 | 日志数据采集工具Filebeat的架构分析及应用

大数据系列 | 日志数据采集工具Filebeat的架构分析及应用 1. Filebeat的由来2. Filebeat原理架构分析3. Filebeat的应用3.1. 安装Filebeat3.2. 实战采集应用程序日志1. Filebeat的由来 在介绍Filebeat之前,先介绍一下Beats。Beats是一个家族的统称,Beats家族有8个成员,早期的…

基于 Vue + RuoYi 架构设计的商城Web/小程序实训课程

以下是基于 Vue RuoYi 架构设计的商城Web/小程序实训课程方案&#xff0c;结合企业级开发需求与教学实践&#xff0c;涵盖全栈技术栈与实战模块&#xff1a; &#x1f4da; 一、课程概述 目标&#xff1a;通过Vue前端 RuoYi后端&#xff08;Spring Boot&#xff09;开发企业…

Puppeteer 相关漏洞-- Google 2025 Sourceless

题目的代码非常简单,核心只有这一句 page.goto(url, { timeout: 2000 });方案1 Puppeteer 是一个常用的自动化浏览器工具&#xff0c;默认支持 Chrome&#xff0c;但也可以配置支持 Firefox。然而&#xff0c;当 Puppeteer 运行在 Firefox 上时&#xff0c;会自动关闭一些安全特…

LucidShape 2024.09 最新

LucidShape的最新版本2024.09带来了一系列新功能与增强功能&#xff0c;旨在解决光学开发者面临的最常见和最复杂的挑战。从微透镜阵列&#xff08;MLA&#xff09;的自动掩模计算&#xff0c;到高级分析功能的改进&#xff0c;LucidShape 2024.09致力于简化工作流程并增强设计…

mini-electron使用方法

把在官方群里“官方132版”目录里下载的包里的minielectron_x64.exe解压到你本地某个目录&#xff0c;改名成electron.exe&#xff0c;比如G:\test\ele_test\mini_electron_pack\electron.exe。 修改你项目的package.json文件。一个例子是&#xff1a; {"name": &q…

Android 网络全栈攻略(七)—— 从 OkHttp 拦截器来看 HTTP 协议二

Android 网络全栈攻略系列文章&#xff1a; Android 网络全栈攻略&#xff08;一&#xff09;—— HTTP 协议基础 Android 网络全栈攻略&#xff08;二&#xff09;—— 编码、加密、哈希、序列化与字符集 Android 网络全栈攻略&#xff08;三&#xff09;—— 登录与授权 Andr…

45-使用scale实现图形缩放

45-使用scale实现图形缩放_哔哩哔哩_bilibili45-使用scale实现图形缩放是一次性学会 Canvas 动画绘图&#xff08;核心精讲50个案例&#xff09;2023最新教程的第46集视频&#xff0c;该合集共计53集&#xff0c;视频收藏或关注UP主&#xff0c;及时了解更多相关视频内容。http…

软件开发早期阶段,使用存储过程的优势探讨:敏捷开发下的利器

在现代软件开发中&#xff0c;随着持续集成与敏捷开发的深入推进&#xff0c;开发团队越来越重视快速响应需求变更、快速上线迭代。在这种背景下&#xff0c;传统将业务逻辑全部放在应用层的方式在某些阶段显得笨重。本文将探讨在软件开发初期&#xff0c;特别是在需求尚不稳定…

『 C++入門到放棄 』- string

C 學習筆記 - string 一、什麼是string ? string 是 C 中標準函數庫中的一個類&#xff0c;其包含在 中 該類封裝了C語言中字符串操作&#xff0c;提供內存管理自動化與更多的操作 支持複製、比較、插入、刪除、查找等功能 二、常用接口整理 類別常用方法 / 說明建立與指…

ARM架构下C++程序堆溢出与栈堆碰撞问题深度解析

ARM架构下C程序堆溢出与栈堆碰撞问题深度解析 一、问题背景&#xff1a;从崩溃现象到内存异常 在嵌入式系统开发中&#xff0c;程序崩溃是常见但棘手的问题。特别是在ARM架构设备上&#xff0c;一种典型的崩溃场景如下&#xff1a;程序在执行聚类算法或大规模数据处理时突然终…

.NET9 实现排序算法(MergeSortTest 和 QuickSortTest)性能测试

在 .NET 9 平台下&#xff0c;我们对两种经典的排序算法 MergeSortTest&#xff08;归并排序&#xff09;和 QuickSortTest&#xff08;快速排序&#xff09;进行了性能基准测试&#xff08;Benchmark&#xff09;&#xff0c;以评估它们在不同数据规模下的执行效率、内存分配及…

RabbitMQ - SpringAMQP及Work模型

一、概述RabbitMQ是一个流行的开源消息代理&#xff0c;支持多种消息传递协议。它通常用于实现异步通信、解耦系统组件和分布式任务处理。Spring AMQP是Spring框架下的一个子项目&#xff0c;提供了对RabbitMQ的便捷访问和操作。本文将详细介绍RabbitMQ的工作模型&#xff08;W…