Android系统开发(八):从麦克风到扬声器,音频HAL框架的奇妙之旅
引言:音浪太强,我稳如老 HAL!
如果有一天你的耳机里传来的不是《咱们屯里人》,而是金属碰撞般的杂音,那你可能已经感受到了 Android 音频硬件抽象层 (HAL) 出问题的后果!在 Android 音频架构中,HAL 扮演着连接音频应用和硬件的桥梁。这篇文章旨在揭开 Android 音频 HAL 的神秘面纱,解析其实现机制,带你了解背后的技术奥秘和开发技巧。音频是每款 Android 设备的灵魂,而理解音频 HAL 则是开发高品质音频应用的关键。音浪已经到来,快点开文章感受一下吧!
一、技术背景:听得见的技术艺术
Android 的音频架构覆盖了从应用层到硬件的整个链路:
- 应用层:
android.media
提供了高级别的音频 API,例如播放和录制功能。 - 中间层:音频框架与音频服务协调音频流的路由和处理。
- 硬件层:音频 HAL 是软件世界和硬件世界的接口,它定义了与音频驱动程序交互的规则。
随着音频技术的发展,设备厂商需要实现个性化的音频功能,例如 Dolby Atmos、Hi-Res Audio 等。而 HAL 则让 Android 系统不需要关心硬件底层的实现细节,使得音频功能的开发更高效、更灵活。
二、概念原理:HAL 是如何工作的?
音频 HAL 是一种硬件抽象层,位于 Android 音频框架与硬件驱动之间,核心机制包括:
- 接口定义:
audio.h
文件定义了音频 HAL 的标准接口。厂商需要实现这些接口,例如音频输入、输出、音量控制等。 - 模块加载:通过
hw_get_module()
函数加载音频 HAL 模块。 - 音频路由:通过 HAL 实现音频流的正确路由,如耳机、扬声器等。
- 驱动交互:HAL 与音频驱动程序交互,控制硬件执行音频操作。
简单来说,HAL 就像音频架构中的“翻译官”,让音频框架和硬件设备说“同一种语言”。
三、实现方法:如何开发音频 HAL?
开发步骤
-
环境准备:
- 下载并编译 AOSP 源码(需要适配目标设备)。
- 安装 Android NDK 和调试工具。
-
实现音频 HAL 接口:
- 创建音频 HAL 模块(
audio_hw.c
)。 - 实现
audio_hw_device
接口,例如初始化、音频流打开/关闭等。
- 创建音频 HAL 模块(
-
配置设备支持:
- 在
Android.mk
或CMakeLists.txt
中声明模块和依赖项。 - 修改设备树配置,关联 HAL 模块与硬件设备。
- 在
-
调试与验证:
- 使用
adb logcat
查看音频日志输出。 - 使用
tinyplay
、tinymix
工具测试音频流。
- 使用
项目实战:Android 音频 HAL 详细实践
以下是关于 Android 音频 HAL 实现的详细项目实战案例。所有代码都可以直接在编译环境中运行。
案例 1:实现基本的音频输出功能
目标:为设备自定义音频芯片实现基本的音频播放功能。
实现步骤:
-
实现音频输出流的 HAL 接口
在audio_hw.c
中定义并实现 HAL 所需的函数。 -
代码实现
创建音频设备和输出流结构,设置输出流的写入功能。
#include <hardware/audio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>// 定义音频设备结构体
struct audio_device {struct audio_hw_device hw_device;// 其他必要的设备配置
};// 定义音频输出流结构体
struct audio_stream_out {struct audio_stream common;int (*write)(struct audio_stream_out *stream, const void *buffer, size_t bytes);int sample_rate;
};// 打开音频输出流
static int adev_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_devices_t devices, audio_output_flags_t flags,struct audio_config *config, struct audio_stream_out **stream_out) {struct audio_stream_out *out_stream = calloc(1, sizeof(struct audio_stream_out));if (!out_stream) {return -ENOMEM;}out_stream->write = out_write; // 设置写入函数out_stream->sample_rate = config->sample_rate;*stream_out = out_stream;return 0;
}// 实现音频数据写入功能
static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, size_t bytes) {// 模拟将音频数据写入硬件printf("Writing %zu bytes to audio hardware\n", bytes);// 实际场景应调用底层驱动接口return bytes;
}// 关闭音频输出流
static void adev_close_output_stream(struct audio_hw_device *dev, struct audio_stream_out *stream) {free(stream);
}// 打开音频设备
static int adev_open(const hw_module_t *module, const char *name, hw_device_t **device) {struct audio_device *adev = calloc(1, sizeof(struct audio_device));if (!adev) {return -ENOMEM;}adev->hw_device.common.module = (hw_module_t *)module;adev->hw_device.open_output_stream = adev_open_output_stream;adev->hw_device.close_output_stream = adev_close_output_stream;*device = (hw_device_t *)adev;return 0;
}// HAL 模块结构
static struct hw_module_methods_t hal_module_methods = {.open = adev_open,
};struct audio_module HAL_MODULE_INFO_SYM = {.common = {.tag = HARDWARE_MODULE_TAG,.module_api_version = AUDIO_MODULE_API_VERSION_0_1,.hal_api_version = HARDWARE_HAL_API_VERSION,.id = AUDIO_HARDWARE_MODULE_ID,.name = "Custom Audio HAL",.author = "Your Name",.methods = &hal_module_methods,},
};
案例 2:支持音量调节功能
目标:为音频输出流实现音量调节功能。
-
步骤说明
- 修改
audio_stream_out
结构,添加音量设置方法。 - 在
out_set_volume
函数中设置左右声道音量。
- 修改
-
代码实现
// 音量调节功能实现
static int out_set_volume(struct audio_stream_out *stream, float left, float right) {printf("Setting volume: left = %.2f, right = %.2f\n", left, right);// 实际场景中应通过驱动设置硬件音量return 0;
}// 在输出流结构中添加 set_volume 方法
static int adev_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_devices_t devices, audio_output_flags_t flags, struct audio_config *config, struct audio_stream_out **stream_out) {struct audio_stream_out *out_stream = calloc(1, sizeof(struct audio_stream_out));if (!out_stream) {return -ENOMEM;}out_stream->write = out_write;out_stream->set_volume = out_set_volume; // 设置音量调节函数out_stream->sample_rate = config->sample_rate;*stream_out = out_stream;return 0;
}
案例 3:实现麦克风音频输入功能
目标:为设备的麦克风实现音频录制功能。
-
步骤说明
- 创建音频输入流结构,定义输入流的读取方法。
- 通过
adev_open_input_stream
接口打开音频输入流。
-
代码实现
// 定义音频输入流结构
struct audio_stream_in {struct audio_stream common;ssize_t (*read)(struct audio_stream_in *stream, void *buffer, size_t bytes);int sample_rate;
};// 打开音频输入流
static int adev_open_input_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_devices_t devices, struct audio_config *config, struct audio_stream_in **stream_in) {struct audio_stream_in *in_stream = calloc(1, sizeof(struct audio_stream_in));if (!in_stream) {return -ENOMEM;}in_stream->read = in_read; // 设置读取函数in_stream->sample_rate = config->sample_rate;*stream_in = in_stream;return 0;
}// 实现音频数据读取功能
static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t bytes) {printf("Reading %zu bytes from microphone\n", bytes);// 实际场景应从硬件获取音频数据memset(buffer, 0, bytes); // 模拟空数据return bytes;
}// 关闭音频输入流
static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_stream_in *stream) {free(stream);
}// 注册输入流到设备
static int adev_open(const hw_module_t *module, const char *name, hw_device_t **device) {struct audio_device *adev = calloc(1, sizeof(struct audio_device));if (!adev) {return -ENOMEM;}adev->hw_device.common.module = (hw_module_t *)module;adev->hw_device.open_input_stream = adev_open_input_stream;adev->hw_device.close_input_stream = adev_close_input_stream;*device = (hw_device_t *)adev;return 0;
}
如何运行
-
配置设备支持:
在设备树文件中添加音频 HAL 的配置,确保设备能够加载audio_hw.c
编译后的模块。 -
编译并集成:
使用 Android 编译系统将音频 HAL 编译为共享库(.so
文件)。 -
测试功能:
- 使用
adb logcat
查看音频日志。 - 使用工具
tinyplay
播放音频文件验证输出功能。 - 使用
tinycap
录制音频文件验证输入功能。
- 使用
通过这些案例,您可以逐步实现并调试完整的音频 HAL 模块,从而掌握 Android 音频架构的核心开发技巧。
五、那些坑和技巧
- 音频卡检测失败:
- 检查设备树配置是否正确。
- 延迟高问题:
- 优化 HAL 中的缓冲区大小。
- 音质问题:
- 调整驱动程序的采样率和位深配置。
六、适配
- 优点:标准化接口,提升开发效率,易于硬件适配。
- 缺点:抽象层可能增加一定延迟,不适合对时延要求极高的场景。
七、性能评估
- 响应时间:音频 HAL 的延迟通常在 10ms 左右。
- 资源消耗:合理优化后的 HAL 实现对 CPU 和内存的影响较小。
八、展望
随着高分辨率音频和 AI 降噪技术的普及,音频 HAL 的发展方向包括支持更多音频格式、更智能的路由功能以及更高效的音频处理算法。
九、结语
通过本文,了解了 Android 音频 HAL 的实现方法及实际案例。音频 HAL 是 Android 音频架构的核心部分,对开发高品质音频应用至关重要。尝试自己动手实现一个 HAL 模块,感受音频开发的乐趣吧!
参考文献
以下是本文在撰写过程中使用的主要参考资料和资源,涵盖了 Android 音频架构相关的文档、技术书籍和实践案例,帮助读者深入学习和实践。
官方文档与代码仓库
-
Android 官方音频架构文档
- 描述了 Android 音频架构的整体设计与 HAL 的实现方式。
- 包括音频 HAL 接口、相关 API 和功能说明。
-
Android AOSP GitHub 仓库
- 提供音频 HAL 的参考实现代码。
- 重点关注
audio.h
和audio_policy.h
文件,它们定义了 HAL 的接口规范。
-
Android 内核源码仓库
- 具体查看
sound/soc/
目录,了解内核层驱动与音频硬件的交互。
- 具体查看
-
AudioFlinger
- Android 音频服务的核心部分。
- 分析如何与音频 HAL 和媒体服务交互。
书籍与经典参考资料
-
《Android Audio Internals》
- 作者:Karim Yaghmour
- 深入分析 Android 音频子系统的内部实现和工作机制。
-
《Mastering Embedded Linux Programming》
- 作者:Chris Simmonds
- 包括嵌入式音频开发和调试的技巧,适用于 Android 驱动层开发。
-
《Linux Device Drivers》
- 作者:Jonathan Corbet
- 经典书籍,讲解内核模块开发基础,涵盖音频驱动相关的内容。
-
《Android 系统级开发实战》
- 以实战案例讲解 Android 音频架构中的 HAL 和驱动开发。
技术文章与博客
-
《Android Audio HAL 开发详解》
- 链接:文章地址
- 包含从音频流定义到音量控制的完整实现。
-
《AudioFlinger 与 Audio HAL 的交互机制》
- 链接:文章地址
- 专注于分析 AudioFlinger 的工作流程和 HAL 的接口调用。
-
《音频驱动开发:从 Linux 到 Android》
- 链接:文章地址
- 探讨从 Linux 到 Android 音频驱动的移植与优化。
工具与库
-
Tinyalsa
- 链接:https://github.com/tinyalsa/tinyalsa
- 用于测试音频 HAL 的简单工具,可以快速验证音频流的输入与输出功能。
-
ALSA Utils
- 链接:https://alsa-project.org/
- 音频开发和调试的重要工具包,提供诸如
aplay
、arecord
等功能。
-
PulseAudio
- 链接:https://www.freedesktop.org/wiki/Software/PulseAudio/
- 高级音频管理工具,适用于理解音频系统的高级功能。
社区与论坛
-
Android 开发者社区
- 链接:https://developer.android.com/community
- 包括开发者博客、社区答疑等资源。
-
Stack Overflow 音频 HAL 相关问答
- 链接:https://stackoverflow.com/questions/tagged/android-audio
- 解决开发过程中常见的疑难问题。
-
Kernel Newbies
- 链接:https://kernelnewbies.org/
- 提供关于内核开发的入门教程和讨论。
调试与性能优化资料
-
《Android HAL 调试工具使用指南》
- 描述如何使用
adb shell
和日志工具分析音频问题。 - 涉及
dumpsys media.audio_flinger
和dmesg
命令的使用。
- 描述如何使用
-
《音频性能优化与调试最佳实践》
- 详细说明如何优化音频流的延迟、提高采样率以及调试驱动问题。
-
Google Perfetto 工具
- 链接:https://perfetto.dev/
- Android 官方推荐的性能追踪工具,适用于音频流的性能分析。
开发环境与测试平台
-
Android Open Source Project (AOSP)
- 链接:https://source.android.com/
- 配置和编译 AOSP 的完整指南。
-
Linaro Toolchain
- 链接:https://www.linaro.org/downloads/
- 提供高性能的交叉编译工具链,适合音频模块的开发。
-
qemu 和真实设备
- 通过模拟器和开发板(如 Raspberry Pi)进行测试,以确保兼容性。
欢迎关注 GongZhongHao,码农的乌托邦,程序员的精神家园!
相关文章:
Android系统开发(八):从麦克风到扬声器,音频HAL框架的奇妙之旅
引言:音浪太强,我稳如老 HAL! 如果有一天你的耳机里传来的不是《咱们屯里人》,而是金属碰撞般的杂音,那你可能已经感受到了 Android 音频硬件抽象层 (HAL) 出问题的后果!在 Android 音频架构中,…...
使用nginx搭建通用的图片代理服务器,支持http/https/重定向式图片地址
从http切换至https 许多不同ip的图片地址需要统一进行代理 部分图片地址是重定向地址 nginx配置 主站地址:https://192.168.123.100/ 主站nginx配置 server {listen 443 ssl;server_name localhost;#ssl证书ssl_certificate ../ssl/ca.crt; #私钥文件ssl_ce…...
Java-数据结构-二叉树习题(1)
对于二叉树的学习,主要的还是得多多练习~毕竟二叉树属于新的知识,并且也并不是线性结构,再加上经常使用递归的方法解决二叉树的问题,所以代码的具体流程还是无法看到的,只能通过画图想象,所以还是必须多加练…...
ReactiveSwift 简单使用
记录 ReactiveSwift 简单使用 导入 ReactiveSwift 库创建 TestViewModel 文件 enum JKTypeType: Int {case cloudcase devicecase weater }// 通过监听属性变化 class TestViewModel: NSObject {lazy var recordType: Property<JKTypeType> {return Property(recordTy…...
iOS - Objective-C 底层实现中的哈希表
1. 关联对象存储(AssociationsHashMap) // 关联对象的哈希表实现 typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap; typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMa…...
SystemUI 实现音量条同步功能
需求:SystemUI 实现音量条同步功能 具体问题 以前在SystemUI 下拉框添加了音量条控制,目前发现在SystemUI下拉框显示状态的情况下, 按键或者底部虚拟导航点击音量加减时候,SystemUI音量条不更新。 如下图:两个Syste…...
Android SystemUI——车载CarSystemUI加载(八)
Android 系统早期的状态栏和导航栏对于手机设备来说那是相当重要的,但是随着手机版本的不断更新,状态栏和导航栏对于手机的重要性在逐渐降低,特别是在快捷手势出现之后,导航栏几乎变得可有可无。但是对于当前如火如荼的车载系统来说,状态栏和导航栏却几乎是必备的,谷歌自…...
全类别机器人传感器模块推荐
视觉感知 双目视觉模块:常见分辨率1280720,帧率30fps-60fps,水平视场角60-90,垂直视场角40-60,通过USB接口传数据。用于机器人导航、避障等,基于三角测量原理获取三维信息,定位更精准。单目摄像…...
怎么用python写个唤醒睡眠电脑的脚本?
环境: win10 python3.12 问题描述: 怎么用python写个唤醒睡眠电脑的脚本? 解决方案: 1.唤醒处于睡眠状态的电脑通常不是通过编程直接实现的,而是依赖于硬件和操作系统提供的特性。对于Windows系统,可…...
2025春秋杯冬季赛 day1 crypto
文章目录 通往哈希的旅程小哈斯RSA1ez_rsa 通往哈希的旅程 根据提示推断是哈希函数,ai一下,推测大概率是一个sha1,让ai写一个爆破脚本即可 import hashlib# 给定目标 SHA-1 哈希值 target_hash "ca12fd8250972ec363a16593356abb1f3cf…...
C# 条件编译的应用
一、引言 在 C# 的开发领域中,条件编译宛如一位幕后英雄,虽不常被开发者挂在嘴边,却在诸多关键场景中发挥着无可替代的作用。它就像是一把神奇的钥匙,能够依据特定的条件,精准地决定源代码中的某些部分是否被纳入最终…...
C语言编程笔记:文件处理的艺术
大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 本文目录 引言正文一、为什么要用文件二、文件的分…...
了解 .mgJSON 文件
.mgJSON (Motion Graphics JSON)是一个基于标准 JSON 格式的文件扩展名,专门用于存储和交换与动态图形、动画和多媒体应用相关的数据。该格式支持静态和动态数据流,能够精确描述动画、物体变换、图形效果等。 .mgJSON 文件通过层级…...
通信协议之多摩川编码器协议
前言 学习永无止境!本篇是通信协议之多摩川编码器协议,主要介绍RS485硬件层以及软件层帧格式。 注:本文章为学习笔记,部分图片与文字来源于网络/应用手册,如侵权请联系!谢谢! 一、多摩川协议概述…...
dbt Semantic Layer 详细教程-6 :指标(metrics)配置规范及示例
前面几篇博文介绍了语义模型及实体、维度和度量规范及示例,一旦创建了语义模型,就该开始添加度量了。可以在与语义模型相同的YAML文件中定义度量,也可以将度量拆分为单独的YAML文件,放入任何其他子目录中(前提是这些子…...
Redis可视化工具--RedisDesktopManager的安装
需要安装使用,0.9.4以上是要收费的 下载地址:https://github.com/uglide/RedisDesktopManager/releases/download/0.9.3/redis-desktop-manager-0.9.3.817.exe 详情:https://blog.csdn.net/u012688704/article/details/82251338 点击进行安…...
《汽车维护与修理》是什么级别的期刊?是正规期刊吗?能评职称吗?
问题解答: 问:《汽车维护与修理》是不是核心期刊? 答:不是,是知网收录的正规学术期刊。 问:《汽车维护与修理》级别? 答:国家级。主管单位:中国汽车维修行业协会 …...
窥探QCC518x/308x系列与手机之间的蓝牙HCI记录与分析 - 手机篇
今天要介绍给大家的是, 当我们在开发高通耳机时如果遇到与手机之间相容性问题, 通常会用Frontline或Ellisys的Bluetooth Analyzer来截取资料分析, 如果手边没有这样的仪器, 要如何窥探Bluetooth的HCI log.这次介绍的是手机篇. 这次跟QCC518x/QCC308x测试的手机是Samsung S23 U…...
MySQL的不同SQL模式导致行为不同?
现象: 我在两个mysql库都有相同定义的表,其中一个字段是varchar(1200)。当我都对这个表进行insert操作,而且超过此字段的规定长度(此处是1200),这两库的行为是不一样的:库B是直接报错too long&…...
【SPIE出版|EI、Scopus双检索】2025年绿色能源与环境系统国际学术会议(GEES 2025)
2025年绿色能源与环境系统国际学术会议(GEES 2025) 会议时间:2025年6月20-22日 会议地点:中国-湖北 最终截稿日期:2025年6月8日 注册截止时间:2025年6月8日 提交检索类型:EI Compendex 和 …...
搭建一个基于Spring Boot的书籍学习平台
搭建一个基于Spring Boot的书籍学习平台可以涵盖多个功能模块,例如用户管理、书籍管理、学习进度跟踪、笔记管理、评论和评分等。以下是一个简化的步骤指南,帮助你快速搭建一个基础的书籍学习平台。 — 1. 项目初始化 使用 Spring Initializr 生成一个…...
SDL2:PC端编译使用 -- SDL2多媒体库使用音频实例
更多内容:XiaoJ的知识星球 SDL2:PC端编译使用 1. SDL2:PC端编译使用1.1 安装必要的依赖1.2 下载编译SDL21.3 SDL2使用示例:Audio1.4 运行示例程序 1. SDL2:PC端编译使用 1.1 安装必要的依赖 首先,确保安装…...
考研计算机组成原理——零基础学习的笔记
第一章 研究计算机硬件的学科。 1.计算机系统概述 计算机系统硬件软件(系统软件:比如操作系统、数据库管理系统、标准程序库等,应用软件:QQ等) 1.2计算机的层次结构 1.2.1计算机硬件的基本组成 冯诺伊曼计算机&a…...
STM32 FreeROTS Tickless低功耗模式
低功耗模式简介 FreeRTOS 的 Tickless 模式是一种特殊的运行模式,用于最小化系统的时钟中断频率,以降低功耗。在 Tickless 模式下,系统只在有需要时才会启动时钟中断,而在无任务要运行时则完全进入休眠状态,从而降低功…...
GAN 用于图像增强
工程需求,临时学一下gan的原理和基于图像增强的实现 原理 论文链接 Generative Adversarial Nets 我们提出了一个通过对抗过程来估计生成模型的新框架,其中我们同时训练两个模型:捕获数据分布的生成模型G和估计样本来自训练数据而不是G的…...
【RAG落地利器】向量数据库Qdrant使用教程
TrustRAG项目地址🌟:https://github.com/gomate-community/TrustRAG 可配置的模块化RAG框架 环境依赖 本教程基于docker安装Qdrant数据库,在此之前请先安装docker. Docker - The easiest way to use Qdrant is to run a pre-built Docker i…...
Day30下 - RAG系统
一、入库文档,问答查询 1. 数据读取 from langchain_core.documents import Document import randomfile_name"knowledge/熬夜救星护肤霜.txt" with open(filefile_name, mode"r", encoding"utf-8") as f:data f.read()# 随机生成…...
linux 安装PrometheusAlert配置钉钉告警
在 Linux 上安装 PrometheusAlert 并配置钉钉告警的步骤如下: 1. 准备工作 钉钉机器人: 在钉钉群中创建一个机器人,获取 Webhook URL。示例 Webhook URL:https://oapi.dingtalk.com/robot/send?access_token=your_dingtalk_token。PrometheusAlert 安装包: 从 Prometheus…...
EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成
EAMM: 通过基于音频的情感感知运动模型实现的一次性情感对话人脸合成 1所有的材料都可以在EAMM: One-Shot Emotional Talking Face via Audio-Based Emotion-Aware Motion Model网站上找到。 摘要 尽管音频驱动的对话人脸生成技术已取得显著进展,但现有方法要么忽…...
Linux提权-02 sudo提权
文章目录 1. sudo 提权原理1.1 原理1.2 sudo文件配置 2. 提权利用方式2.1 sudo权限分配不当2.2 sudo脚本篡改2.3 sudo脚本参数利用2.4 sudo绕过路径执行2.5 sudo LD_PRELOAD环境变量2.6 sudo caching2.7 sudo令牌进程注入 3. 参考 1. sudo 提权原理 1.1 原理 sudo是一个用于在…...
【Pandas】pandas Series apply
Pandas2.2 Series Function application, GroupBy & window 方法描述Series.apply()用于将一个函数应用到 Series 的每个元素或整个 Series pandas.Series.apply pandas.Series.apply 是 Pandas 库中 Series 对象的一个方法,用于将一个函数应用到 Series 的…...
Git学习笔记
Git学习笔记 目录 版本控制 本地版本控制 集中版本控制 分布式版本控制 基本使用方式 Git Config Git Remote Git Add Objects Refs Annotation Tag 追溯历史版本 修改历史版本 Git GC Git Clone & Pull & Fetch Git Push 常见问题 不同的工作流 集…...
HTML5 Canvas实现的跨年烟花源代码
以下是一份基于HTML5 Canvas实现的跨年烟花源代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">…...
javaEE初阶————多线程初阶(2)
今天给大家带来第二期啦,保证给大家讲懂嗷; 1,线程状态 NEW安排了工作还未开始行动RUNNABLE可工作的,或者即将工作,正在工作BLOCKED排队等待WAITING排队等待其他事TIMED_WAITING排队等待其他事TERMINATED工作完成了 …...
linux下的NFS和FTP部署
目录 NFS应用场景架构通信原理部署权限认证Kerberos5其他认证方式 命令serverclient查看测试系统重启后自动挂载 NFS 共享 高可用实现 FTP对比一些ftp服务器1. **vsftpd (Very Secure FTP Daemon)**2. **ProFTPD (Professional FTP Daemon)**3. **Pure-FTPd**4. **WU-FTPD (Was…...
《Java核心技术II》可中断套接字
4.2.4 可中断套接字 SocketChannel可以中断套接字 SocketChannel channel.open(new InetSocketAddress(host,port)); 通道(channel)并没有与之相关联的流,实际上,所拥有的read和write方法都是通过Buffer对象实现的。 如果不想处理缓冲区,…...
电梯系统的UML文档05
Dispatcher 不控制实际的电梯组件,但它在软件系统中是重要的。每一个电梯有一个ispatcher,主要功能是计算电梯的移动方向、移动目的地以及保持门的打开时间。它和系统中除灯控制器以外的几乎所有控制对象交互。 安全装置也是一个环境对象,它…...
浅谈云计算19 | OpenStack管理模块 (上)
OpenStack管理模块(上) 一、操作界面管理架构二、认证管理2.1 定义与作用2.2 认证原理与流程2.2.1 认证机制原理2.2.2 用户认证流程 三、镜像管理3.1 定义与功能3.2 镜像服务架构3.3 工作原理与流程3.3.1 镜像存储原理3.3.2 镜像检索流程 四、计算管理4.…...
1.5 GPT 模型家族全解析:从 GPT-1 到 GPT-4 的演进与创新
GPT 模型家族全解析:从 GPT-1 到 GPT-4 的演进与创新 随着人工智能技术的飞速发展,GPT(Generative Pre-trained Transformer)模型家族已经成为了现代自然语言处理(NLP)领域的标杆。从初代的 GPT-1 到最新的 GPT-4,每一代模型的发布都标志着人工智能技术的一个飞跃,并推…...
C#如何调用执行命令行窗口(CMD)
一、引言 在 C# 的编程世界里,我们常常会遇到需要与操作系统底层进行交互的场景。这时,调用命令行窗口(CMD)就成为了一个强大的工具。无论是自动化日常任务,还是执行外部程序和批处理文件,通过 C# 调用 CM…...
归子莫的科技周刊#2:白天搬砖,夜里读诗
归子莫的科技周刊#2:白天搬砖,夜里读诗 本周刊开源,欢迎投稿。 刊期:2025.1.5 - 2025.1.11。原文地址。 封面图 下班在深圳看到的夕阳,能遇到是一种偶然的机会,能拍下更是一种幸运。 白天搬砖,…...
Spring Boot + Apache POI 实现 Excel 导出:BOM物料清单生成器(支持中文文件名、样式美化、数据合并)
目录 引言 Apache POI操作Excel的实用技巧 1.合并单元格操作 2.设置单元格样式 1. 创建样式对象 2. 设置边框 3. 设置底色 4. 设置对齐方式 5. 设置字体样式 6.设置自动换行 7. 应用样式到单元格 3. 定位和操作指定单元格 4.实现标签-值的形式 5.列宽设置 1. 设…...
OpenVela——专为AIoT领域打造的开源操作系统
目录 一、系统背景与开源 1.1. 起源 1.2. 开源 二、系统特点 2.1. 轻量化 2.2. 标准兼容性 2.3. 安全性 2.4. 高度可扩展性 三、技术支持与功能 3.1. 架构支持 3.2. 异构计算支持 3.3. 全面的连接套件 3.4. 开发者工具 四、应用场景与优势 4.1. 应用场景 4.2. …...
02UML图(D1_结构图)
目录 学习前言 ---------------------------------- 讲解一:类图 一、类图的组成结构 1. 类(Class) 1.1. 类的成员变量的表示方式 1.2. 类的成员方法的表示方式 2. 接口(Interface) 3. 包(Package) 二、UML类…...
二十三种设计模式-装饰器模式
一、定义与核心思想 装饰器模式是一种结构型设计模式,其核心思想是动态地给一个对象添加一些额外的职责。通过这种方式,可以在不改变原有对象结构的基础上,灵活地增加新的功能,使得对象的行为可以得到扩展,同时又保持…...
SSM课设-酒店管理系统功能设计
【课设者】SSM课设-酒店管理系统 分为用户端管理员端 技术栈: 后端: Spring Spring MVC MyBatis Mysql JSP 前端: HtmlCssJavaScriptAjax 功能: 用户端主要功能包括: 登录注册 客房预订 客房评论 首页 管理员端主要功能包括: 会员信息管理 客房信息…...
R语言的文件操作
R语言的文件操作 引言 在数据科学和分析的过程中,文件操作是不可或缺的一部分。R语言作为一种强大的统计计算和图形作图的编程语言,提供了丰富的文件操作函数,使得用户能够方便地读取和保存数据。本文将详细介绍R语言中的文件操作ÿ…...
[javaWeb]初识Web
将该图片在浏览器中打印出来 代码: <html> <head> <title>HTML初识</title> </head> <body> <h1>猫猫</h1> <img src "img/1.jpg"> </body> &l…...
基于微信小程序的摄影竞赛系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
.netframwork模拟启动webapi服务并编写对应api接口
在.NET Framework环境中模拟启动Web服务,可以使用几种不同的方法。一个常见的选择是利用HttpListener类来创建一个简单的HTTP服务器,或者使用Owin/Katana库来自托管ASP.NET Web API或MVC应用。下面简要介绍Owin/Katana示例代码。这种方法更加灵活&#x…...