Qt学习笔记-1
1. 第一个Qt程序
1.1 Hello Qt
1 |
|
测试程序
在源码根目录打开命令提示符执行qmake -project生成hello.pro项目文件,然后执行qmake hello.pro从这个项目文件生成makefile文件,在输入make命令就可以构建该应用。
1 | #include <QApplication> // 头文件引用, 每个Qt类都有对应的头文件,类的定义 |
测试程序
在源码根目录打开命令提示符执行qmake -project生成hello.pro项目文件,然后执行qmake hello.pro从这个项目文件生成makefile文件,在输入make命令就可以构建该应用。
安装docker时,docker会默认创建一个内部的桥接网络docker0,每创建一个容器分配一个虚拟网卡,容器之间可以根据ip互相访问。
1 | # ifconfig |
运行一个centos镜像, 查看ip地址得到:172.17.0.7
1 | # docker run -it --name centos-1 docker.io/centos:latest |
以同样的命令再起一个容器,查看ip地址得到:172.17.0.8
1 | # docker run -it --name centos-2 docker.io/centos:latest |
容器内部ping测试结果如下:
1 | # ping 172.17.0.7 |
这种方式必须知道每个容器的ip,在实际使用中并不实用。
运行容器的时候加上参数link
运行第一个容器
1 | docker run -it --name centos-1 docker.io/centos:latest |
运行第二个容器
1 | docker run -it --name centos-2 \ |
--link:参数中第一个centos-1是 容器名 ,第二个centos-1是定义的 容器别名 (使用别名访问容器),为了方便使用,一般别名默认容器名。
测试结果如下:
1 | # ping centos-1 |
此方法对容器创建的顺序有要求,如果集群内部多个容器要互访,使用就不太方便。
1 | docker network create testnet |
查询到新创建的bridge testnet。

1 | docker run -it --name <容器名> \ |
1 | docker run -it --name centos-1 --network testnet \ |
1 | # ping centos-1 |
推荐使用这种方法,自定义网络,因为使用的是网络别名,可以不用顾虑ip是否变动,只要连接到docker内部bright网络即可互访。bridge也可以建立多个,隔离在不同的网段。
quay.io/coreos/etcd:3.2.7
bitname/etcd
1 | # data 存储容器持久化数据 |
配置文件路径为 /usr/local/docker/etcd/config/etcd.config.yml
1 | name: etcd # etcd member 名称,可根据实际情况修改 |
1 | docker run -d --name etcd -p 2379:2379 -p 2380:2380 -v /usr/local/docker/etcd/data:/var/etcd -v /usr/local/docker/etcd/config:/var/lib/etcd/config quay.io/coreos/etcd: 3.5.12 |
创建Docker-compose
1 | version: '3' |
基于环境变量配置, 配置参考配置文件方式
1 | version: '3' |
创建并启动etcd
1 | cd {docker-compose文件所在目录} |
1 | etcdctl --endpoints=192.168.1.2:2379 --write-out=table endpoint health |
1 | # 读取视频流 |
获取摄像头编号可使用ls -al /dev/ |grep video,输出信息以video开头其后缀为数字即为可能的摄像头编号。
1 | # 校验获取VideoCapture类实例 |
1 | # 获取视频帧的宽 |
1 | success, frame = capture.read() |
当需要同时处理多路摄像头时一般使用grab()和retrieve()代替
1 | success_1 = capture.grab() |
1 | # 设置摄像头分辨率的宽 |
无论是视频文件存储还是摄像头画面保存都是用VideoWriter类,初始化时需要传入文件名(包含文件格式)、视频编解码器、视频保存帧率 、分辨率,保存视频的帧率最好和读入的帧率一致,分辨率可以更改,只是要求写入的帧大小要与分辨率保持一致。
若指定的文件名已存在则会覆盖文件。
1 | writer = cv2.VideoWriter('output.mp4', |
不管是VideoCapture还是VideoWriter类,使用完都应该释放资源
1 | # 释放VideoCapture资源 |
1 | # -*- coding: utf-8 -*- |
此处使用设备 Tesla P40 + Debian 12为例
显卡驱动:下载 NVIDIA 官方驱动 | NVIDIA
CUDA Toolkit: CUDA Toolkit Archive | NVIDIA Developer
![[Docke种使用GPU运行Ollama/IMG-20260105103041635.png]]
注意CUDA版本对应,否则可能会导致CUDA在容器内无法运行
1 | curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ |
禁用 nouveau
参考[[../Linux/Ubuntu禁用Nouveau驱动|Ubuntu禁用Nouveau驱动]]
验证环境是否安装成功
1 | docker run --rm --gpus all nvidia/cuda:12.2.0-runtime-ubuntu22.04 nvidia-smi |
![[Docke种使用GPU运行Ollama/IMG-20260105103041714.png]]
1 | docker run --gpus=all -d -e OLLAMA_MODEL:qwen2.5-coder:7b -e OLLAMA_ENV:production -v=qwen-coder:/root/.ollama -p 11437:11434 --name qwen-coder -d ollama/ollama:latest |
--gpus=all即可1 | ollama run qwen2.5-coder:7b |
1 | services: |
在docker-compose.yml所在目录运行以下命令:
1 | docker-compose up -d |
验证是否使用GPU启动Ollama
1 | docker exec -it <ollama容器ID> bash # 进入已启动的容器 |
如果PROCESSOR中显示为GPU则启动成功
![[Docke种使用GPU运行Ollama/IMG-20260105103041772.png]]
Ollama运行deepseek-r1示例
1 | # CPU运行 |
1 | sudo nano /etc/modprobe.d/blacklist-nouveau.conf |
1 | blacklist nouveau |
1 | sudo update-initramfs -u |
1 | sudo reboot |
重启后,检查Nouveau模块是否已禁用:
1 | lsmod | grep nouveau |
如果没有输出,说明Nouveau已成功禁用。
注意事项
禁用Nouveau后,可以安装NVIDIA专有驱动以获得更好的性能。
如果需要恢复Nouveau驱动,只需删除_/etc/modprobe.d/blacklist-nouveau.conf_文件并重新更新initramfs。
1 | <!-- 默认保留两位小数 输出: $12.34 --> |
1 | <!-- 固定前缀 输出: 单价:$12.34 --> |
1 | <!-- 固定位数,仅支持整形 输出: 086723 --> |
1 | <!-- 输出: 0123.46 --> |
1 | <!-- 输出: 5/4/2015 --> |
1 | <!-- |
热更新指在不重新发布客户端安装包(APK/IPA)的情况下,通过下发补丁或脚本,在线修复Bug或更新部分功能。
核心驱动力:
技术机遇(iOS侧):2013年iOS 7引入的 JavaScriptCore 框架是关键转折点。它使得原生Objective-C与JavaScript之间的高效、无缝通信成为可能,为基于JS脚本的热更新方案(如JSPatch)铺平了道路。随着Swift的发布和iOS 7+用户成为主流,热更新技术开始爆发。
这类方案适合小范围Bug修复和逻辑更新,通过JS脚本调用/替换原生方法。
| 方案 | 脚本语言 | 特点 | 现状 |
|---|---|---|---|
| Rollout.io | JavaScript | 支持OC和Swift,已平台化,有商业化产品使用。 | 成熟,持续维护。 |
| JSPatch | JavaScript | 仅支持OC,在国内广泛使用(腾讯系等),平台化成熟。 | 成熟,但苹果审核政策收紧后使用需谨慎。 |
| DynamicCocoa | OC -> JS | 滴滴内部方案。最大亮点:提供工具将OC代码转译为JS,无需手写JS;支持xib/storyboard、图片资源更新。 | 曾计划开源,需关注其后续动态。 |
共同原理:利用 JavaScriptCore 建立JS与OC的桥接,通过运行时(Runtime)动态替换方法实现(method swizzling)。
这类方案旨在用一套代码开发iOS、Android(及Web)应用,天然支持热更新。
| 方案 | 发起方 | 核心特点 | 性能与生态 |
|---|---|---|---|
| React Native (RN) | 使用React语法和JSX,重视各平台原生体验。 | 性能持续优化,生态庞大(Facebook、腾讯、京东等大量应用使用)。早期性能有槽点,现已大幅改善。 | |
| Weex | 阿里巴巴 | 目标:一次编写,生成iOS、Android、Web三端代码。采用Vue.js语法。 | 经阿里系产品(如2016年双11)大规模验证。旨在解决RN代码复用率、性能优化被动等问题。 |
选型提示:Weex 在代码复用和跨平台一致性上追求更极致;RN 则更强调遵循各平台原生设计规范,生态更成熟。
关于脚本语言的思考:
Clang 是LLVM的前端,负责将OC代码编译成抽象语法树(AST)。DynamicCocoa 的高明之处在于直接利用 Clang 生成的AST进行解析和转译,从而实现了“用OC写补丁”的体验。
Android方案主要围绕DEX补丁的生成、下发和加载展开。
| 方案 | 出品方 | 核心原理 | 优点 | 缺点 |
|---|---|---|---|---|
| 百川Hotfix | 阿里巴巴 | 融合热部署(AndFix)与冷部署,支持类、资源、SO文件修复。 | 功能全面,可视化打补丁,接入简单。 | - |
| Robust | 美团 | 为每个方法插入“跳转”逻辑,通过改变跳转目标实现修复。 | 实时生效,兼容性高,稳定性好。 | 侵入打包流程,增加包体积和方法数。 |
| Tinker | 微信 | 全量替换DEX。通过自研DexDiff算法生成极小差量包。 | 补丁包小,功能强大(支持类、资源、SO)。 | 不实时生效,需重启。合并DEX时消耗内存/磁盘,可能失败。 |
| QFix (类) | 手机QQ空间 | 类似Google Multidex,将补丁作为新的DEX加载。 | 兼容性高,稳定性好。 | 不实时生效。Dalvik下性能问题;Art下补丁包大;需侵入打包。 |

关键概念:
| 平台 | 需求场景 | 推荐方案 | 关键考量 |
|---|---|---|---|
| iOS | 紧急Bug修复,小功能更新 | JSPatch (需注意审核风险) 或评估 Rollout | 苹果官方对热更新审核政策严格,需谨慎使用。 |
| iOS | 新功能模块,跨平台需求 | React Native 或 Weex | RN生态更成熟;Weex追求更高代码复用。 |
| Android | 紧急Bug修复,要求实时生效 | Robust | 平衡了实时性、兼容性和稳定性。 |
| Android | 常规版本更新,修复范围大 | Tinker | 补丁包小,功能全面,社区活跃。 |
| Android | 追求简单接入,功能全面 | 百川Hotfix | 阿里系产品,提供平台化支持。 |
核心建议:
日志是程序产生的、遵循特定格式(通常包含时间戳)的文本数据。在分布式系统中,日志通常分为:
传统日志管理的痛点:
grep/sed/awk 等工具手动搜索| 组件 | 角色 | 特点 |
|---|---|---|
| Elasticsearch | 分布式搜索引擎 | 高可扩展、高可靠、支持全文检索和结构化查询 |
| Logstash | 数据收集处理引擎 | 支持多种数据源、强大的过滤和转换能力 |
| Kibana | 数据可视化平台 | 丰富的图表类型、交互式仪表板 |
| Filebeat | 轻量级数据收集器 | 资源消耗低、专为日志收集优化 |
版本信息:
1 | Input → Filter → Output |
grok:正则表达式解析date:时间处理json:JSON编解码mutate:数据修改Grok 示例:
1 | grok { |
1 | 应用服务器 → Logstash → Elasticsearch → Kibana |
特点:
1 | 多台服务器 → Logstash Shipper → Elasticsearch集群 → Kibana |
改进:
1 | 多台服务器 → Logstash Shipper → Kafka集群 → Logstash Indexer → Elasticsearch集群 → Kibana |
关键改进:
1 | 机房A:应用 → Logstash → Kafka → Logstash → Elasticsearch → Kibana |
单元化设计原则:
Logstash 的问题:
Filebeat 的优势:
1 | filebeat.prospectors: |
测试环境:
测试结果:
| 指标 | Logstash | Filebeat | 对比 |
|---|---|---|---|
| CPU使用率 | 53.7% | 38.0% | Filebeat低30% |
| 处理时间 | 210秒 | 30秒 | Filebeat快7倍 |
| 收集速度 | 1.6万行/秒 | 11万行/秒 | Filebeat快7倍 |
1 | 应用服务器 → Filebeat → Kafka集群 → Logstash Indexer → Elasticsearch集群 → Kibana |
Filebeat 到 Kafka:
1 | output.kafka: |
Kafka 到 Logstash:
1 | input { |
| 问题 | 现象 | 解决方案 |
|---|---|---|
| Indexer 挂掉 | 日志停止消费 | 使用 Supervisor 监控进程 |
| Java异常换行 | 异常日志被分割 | 使用 multiline codec |
| 时区问题 | 日志时间差8小时 | Kibana 使用浏览器时区 |
| Grok解析失败 | 日志格式不一致 | 统一日志格式,使用在线调试 |
处理多行日志:
1 | input { |
时区处理:
1 | date { |
1 | curl -X GET "localhost:9200/_cluster/health?pretty" |
通过从 ELK 到 EFK 的演进,我们构建了一个高性能、高可靠、易维护的日志系统。这个系统不仅解决了传统日志管理的痛点,还为业务监控、故障排查和安全审计提供了强大支持。随着技术的不断发展,日志系统将继续演进,为企业数字化转型提供更强大的数据支撑。
每个提交消息都由一个标题、一个正文和一个页脚组成。而标题又具有特殊格式,包括修改类型、影响范围和内容主题:
1 | 修改类型(影响范围): 标题 |
标题是强制性的,但标题的范围是可选的。
每个类型值都表示了不同的含义,类型值必须是以下的其中一个:
代码回滚比较特殊,如果本次提交是为了恢复到之前的某个提交,那提交消息应该以revert:开头,后跟要恢复到的那个提交的标题。然后在消息正文中,应该写上This reverts commit <hash>,其中<hash>是要还原的那个提交的SHA值。
范围不是固定值,它可以是你提交代码实际影响到的任何内容。例如$location、$browser、$compile、$rootScope、ngHref、ngClick、ngView等,唯一需要注意的是它必须足够简短。
当修改影响多个范围时,也可以使用*。
标题是对变更的简明描述:
正文是对标题的补充,但它不是必须的。和标题一样,它也要求使用祈使句且现在时态,正文应该包含更详细的信息,如代码修改的动机,与修改前的代码对比等。
任何Breaking Changes(破坏性变更,不向下兼容)都应该在页脚中进行说明,它经常也用来引用本次提交解决的GitHub Issue。
Breaking Changes应该以“BREAKING CHANGE:”开头,然后紧跟一个空格或两个换行符,其他要求与前面一致。
master: 长期分支,用于对外版本发布,所有版本出自此版本库。此分支不允许直接提交代码,只从bugfix分支和develop分支合并。
develop: 长期分支,用于日常代码开发,与master分支 保持同步,当新功能开发完成后线合并到此分支,经过测试后再合并到master分支。
bugfix: 临时分支,当出现bug时基于master分支新建bugfix/bug-1,bug分支可根据bug编号命名。bug测试完毕合并进入develop分支和master分支
feature: 临时分支,开发新功能时从develop分支新建feature/feature-1,feature分支可根据功能命名。新特性开发完成合并进入develop分支并删除feature分支。
release: 临时分支,需要发布版本时从master分支新建release/release-1.0.0,release分支根据版本号命名。
release分支禁止再合并功能,只提交bug修改,版本发布完成后合并进入master和develop,并再对应的提交上打版本Tag。
参考格式
1 | <type>: <subject> |
type: 本次commit的类型,如bugfix,docs,style等
feat: 添加新特性
fix: 修复bug
docs: 修改文档
style: 修改格式缩进,不改变代码逻辑
refactor: 代码重构,没有添加新下功能或者修复bug
perf: 增加代码进行性能测试
test: 增加测试用例
chore: 改变构建流程或者增加依赖库、工具等
scope: 本次commit波及范围
subject: 简明扼要阐述本次commit的主旨
body: 详细描述本次commit,如需换行则使用|
footer: 描述下与之关联的 issue 或 breadk change
标题行: 50个字符以内,描述主要变更内容
主体内容: 更详细下说明文本,建议72个字符以内。需要描述信息包括:
如果需要的话可以添加一个连接到issue或其他文档
示例
1 | docs(README): README添加代码提交规范 |