Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

银河麒麟桌面版V4远程桌面访问方法

发表于 2026-01-13

对于银河麒麟桌面版4.0.2,可使用系统已集成的 vino-server 进行远程桌面访问。具体步骤如下:

  • 打开终端,输入vino-preferences,配置vnc连接密码
  • 使用vncviewer,输入银河麒麟桌面版4.0.2的ip地址,输入vnc连接密码,即可远程访问银河麒麟。

参考链接

  1. 银河麒麟桌面操作系统:手把手教你开启VNC远程桌面并修改默认端口,by 码农拿铁.

DDS学习笔记

发表于 2026-01-09 | 更新于 2026-01-11

最近接触到 DDS 中间件,学习一下。

定义

针对实时系统的数据分发服务( DDS )是对象管理组织(OMG)的机器对机器(有时称为中间件或连接框架)标准,旨在通过发布-订阅模式实现可靠、高性能、可互操作、实时、可扩展的 数据交换。

DDS 满足航空航天、国防、空中交通管制、自动驾驶车辆、医疗设备、机器人、发电、仿真和测试、智能电网管理、交通运输系统等 应用领域的实时数据交换需求。

开源实现

  • Fast-DDS (原名 Fast RTPS)
  • Dust DDS
  • OpenDDS

编译安装

下面从源代码编译安装 Fast-DDS。

安装依赖

使用 vcpkg 安装 Fast-DDS 所需依赖库。

1
vcpkg install openssl asio tinyxml2 fastcdr foonathan-memory --triplet x64-windows

编译安装

在Windows平台编译安装使用 Visual Studio 2019.

foonathan_memory_vendor (可选,当找不到库时)

FastDDS 依赖 Foonathan Memory(内存管理库),通过源代码编译安装:

1
2
3
4
5
6
cd i:\project\Fast-DDS\
git clone https://github.com/eProsima/foonathan_memory_vendor.git
cd foonathan_memory_vendor
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=i:/install/foonathan_memory_vendor ..
cmake --build . --config Release --target install

FastCDR (可选,当找不到库)

FastDDS 依赖 FastCDR(序列化库),通过源代码编译安装:

1
2
3
4
5
6
cd i:\project\Fast-DDS\
git clone https://github.com/eProsima/Fast-CDR.git
cd Fast-CDR
mkdir build && cd build
cmake -A x64 -DCMAKE_INSTALL_PREFIX=i:/install/fastcdr ..
cmake --build . --config Release --target install

eProsima Fast DDS

当所有依赖库都安装后,开始安装eProsima Fast DDS,打开 VS2019的X64本地命令提示符,按如下步骤输入命令:

1
2
3
4
5
6
cd i:\project\Fast-DDS\
git clone https://github.com/eProsima/Fast-DDS.git
cd Fast-DDS
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=i:/install/fastdds ..
cmake --build . --config Release --target install

当执行 cmake -DCMAKE_INSTALL_PREFIX=i:/install/fastdds .. 可能会报找不到 ASIO 的错误,可以编辑 CMakeLists.txt,注释如下代码,再重新运行。

1
eprosima_find_thirdparty(Asio asio VERSION 1.13.0)

当执行 cmake –build . –config Release –target install 可能会报如下错误:

1
警告 C4819 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失

请参考以下链接进行处理,主要是配置C++编译选项 /utf-8:

  • 警告 C4819 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失

fastddsgen

fastddsgen 是 FastDDS 官方提供的 IDL(Interface Definition Language)编译器,用于将 IDL 定义的数据类型转换为 FastDDS 兼容的代码(支持 C++、Python 等语言),自动生成数据序列化 / 反序列化逻辑、类型注册代码等,是 FastDDS 开发的基础工具。

具体安装步骤请参考:

  • 通信中间件 Fast DDS(三) :fastddsgen的安装与利用

简单示例

Fast-DDS的简单示例请参考:

  • 1.3. Writing a simple C++ publisher and subscriber application

参考链接

  1. Data Distribution Service,by wikipedia.
  2. What is DDS?,by dds.
  3. 通信中间件 Fast DDS(一) :编译、安装和测试,by 流星雨爱编程.
  4. 1. Getting Started,by fast-dds.
  5. Fast DDS官方文档机翻之「入门介绍」,by 卢飞腾.
  6. 1.3. Writing a simple C++ publisher and subscriber application,by fast-dds.
  7. 通信中间件 Fast DDS(三) :fastddsgen的安装与利用 ,by ycfenxi.
  8. 不使用默认路径的 cmake 项目管理,by 怀中落霞.
  9. fastdds在windows下的编译和使用,by 飞羽.
  10. 警告 C4819 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失,by 匈牙利认真的小菠萝.

图解大模型读书笔记

发表于 2025-12-24 | 更新于 2026-01-08

阅读书籍《图解大模型:生成式AI原理与实战》,做些笔记。

第一章:大语言模型入门

第二章:词元和嵌入

第三章:图解大语言模型

第四章:文本分类

第五章:文本聚类和主题建模

第六章:提示工程

第七章:高级文本生成技术和工具

第八章:语义搜索和检索增强生成(RAG)

第九章:多模态大语言模型

第十章:创建文本嵌入模型

第十一章:为分类任务微调表示型模型

第十二章:微调生成模型

参考链接

  1. 《图解大模型》配套阅读——大模型面试题 200 问,by 李博杰.
  2. Prompt caching: 10x cheaper LLM tokens, but how?,by Sam Rose.

DLL导入库生成的方法

发表于 2025-12-23

当使用隐式链接的方法调用 DLL 中的导出函数时,需要代码的头文件、导入库lib和动态链接库。如何缺失导入库lib,将无法使用隐式链接的方式调用 DLL中的函数。幸运的是,通过一些手段可以从DLL中直接生成导入库lib。

生成导入库流程

步骤如下:

  • 从Dll中生成对应def文件,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
include '..\implib.inc'

; XYZLIBRARY.??4CXyz@@QAEAAV0@$$QAV0@@Z ord.1
implib XyzLibrary.dll, ??4CXyz@@QAEAAV0@$$QAV0@@Z
; XYZLIBRARY.??4CXyz@@QAEAAV0@ABV0@@Z ord.2
implib XyzLibrary.dll, ??4CXyz@@QAEAAV0@ABV0@@Z
; XYZLIBRARY.?Foo@CXyz@@QAEHH@Z ord.3
implib XyzLibrary.dll, ?Foo@CXyz@@QAEHH@Z
; XYZLIBRARY.GetXyz ord.4
implib XyzLibrary.dll, GetXyz
; XYZLIBRARY._GetXyz@0 ord.5
implib XyzLibrary.dll, _GetXyz@0
; XYZLIBRARY._XyzFoo@8 ord.6
implib XyzLibrary.dll, _XyzFoo@8
; XYZLIBRARY._XyzRelease@4 ord.7
implib XyzLibrary.dll, _XyzRelease@4

endlib
  • 根据def文件生成DLL的导入库lib

自动生成导入库

生成DLL导入库lib的方案有很多,最便利的方法是使用 ImpLib SDK 工具。具体教程如下:

  • 从官网下载最新的 ImpLib SDK 并解压,将 ImpLib SDK 的bin目录添加到系统环境变量 PATH 下。
  • 使用工具dll2def自动生成DLL的def文件
1
\bin\dll2def c:\windows\system32\kernel32.dll kernel32.def
  • 将生成的kernel32.def文件复制到 ImpLib SDK\src\Win32 文件下,然后运行 build_libs.bat,或者运行如下命令:
1
\bin\fasm kernel32.def kernel32.lib

参考链接

  1. DLL导出类和函数,by huangwang.
  2. ImpLib SDK Guide,by implib.

CPlusPlus多线程编程

发表于 2025-12-14 | 更新于 2025-12-15

最近需要使用C++的多线程编写一个处理程序,因此学习记录一下C++多线程的编程知识。

基本概念

多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。

应用场景

  • Web服务与服务器:
    • Web服务器: Tomcat等处理大量用户请求,每个请求分配一个线程。
    • 游戏服务器: 同时处理多个玩家的连接和游戏逻辑。
  • 后台与异步处理:
    • 定时任务: 定期发送邮件、数据备份、数据分析。
    • 日志记录: 将写日志操作放到后台线程,不阻塞主程序。
    • 异步操作: 发送消息、处理图片上传。
  • 桌面应用与用户界面:
    • 响应性: 将耗时计算移到后台线程,前台显示进度条,避免UI冻结。
    • Swing/JavaFX: 事件处理和耗时操作。
  • 数据处理与计算:
    • CPU密集型任务: 图像/视频处理、密码破解、大规模数据分析(利用多核)。
    • I/O密集型任务: 并行下载文件、同时读写多个文件/数据库。
  • 网络爬虫:
    • 并行抓取: 同时爬取多个网页或API接口,提高效率。
  • 数据库与中间件:
    • 连接池管理: 并发管理数据库连接。
    • 数据迁移与分析: 分块处理大数据。

编程实现

传统的C++(C++11标准之前)中并没有引入线程这个概念,在C++11出来之前,如果我们想要在C++中实现多线程,需要借助操作系统平台提供的API,比如Linux的<pthread.h>,或者windows下的<windows.h> 。

C++11提供了语言层面上的多线程,包含在头文件中。它解决了跨平台的问题,提供了管理线程、保护共享数据、线程间同步操作、原子操作等类。C++11 新标准中引入了5个头文件来支持多线程编程。

这5个头文件分别是:

  • thread
  • mutex
  • atomic
  • condition_variable
  • future

创建线程

创建线程的基本方法如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 示例1

std::thread myThread ( thread_fun);
//函数形式为void thread_fun()
myThread.join();
//同一个函数可以代码复用,创建多个线程

# 示例2

std::thread myThread ( thread_fun(100));
myThread.join();
//函数形式为void thread_fun(int x)
//同一个函数可以代码复用,创建多个线程

# 示例3

std::thread (thread_fun,1).detach();
//直接创建线程,没有名字
//函数形式为void thread_fun(int x)

主线程与子线程的处理方法:

  • detach方式,启动的线程自主在后台运行,当前的代码继续往下执行,不等待新线程结束。
  • join方式,等待启动的线程完成,才会继续往下执行。

可以使用joinable判断是join模式还是detach模式。

1
if (myThread.joinable()) foo.join();

多线程编程示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>                // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx; // 全局互斥锁.
std::condition_variable cv; // 全局条件变量.
bool ready = false; // 全局标志位.

void do_print_id(int id)
{
std::unique_lock <std::mutex> lck(mtx);
while (!ready) // 如果标志位不为 true, 则等待...
cv.wait(lck); // 当前线程被阻塞, 当全局标志位变为 true 之后,
// 线程被唤醒, 继续往下执行打印线程编号id.
std::cout << "thread " << id << '\n';
}

void go()
{
std::unique_lock <std::mutex> lck(mtx);
ready = true; // 设置全局标志位为 true.
cv.notify_all(); // 唤醒所有线程.
}

int main()
{
std::thread threads[10];
// spawn 10 threads:
for (int i = 0; i < 10; ++i)
threads[i] = std::thread(do_print_id, i);

std::cout << "10 threads ready to race...\n";
go(); // go!

for (auto & th : threads)
th.join();

return 0;
}

创建线程池

因为程序边运行边创建线程是比较耗时的,所以我们通过池化的思想:在程序开始运行前创建多个线程,这样,程序在运行时,只需要从线程池中拿来用就可以了.大大提高了程序运行效率.一般线程池都会有以下几个部分构成:

  • 线程池管理器(ThreadPoolManager):用于创建并管理线程池,也就是线程池类
  • 工作线程(WorkThread): 线程池中线程
  • 任务队列task: 用于存放没有处理的任务。提供一种缓冲机制。
  • append:用于添加任务的接口

线程池示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>


class ThreadPool {
public:
ThreadPool(size_t numThreads) : stop(false) {
for (size_t i = 0; i < numThreads; ++i) {
workers.emplace_back([this] {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queueMutex);
condition.wait(lock, [this] { return stop || !tasks.empty(); });
if (stop && tasks.empty()) {
return;
}
task = std::move(tasks.front());
tasks.pop();
}
task();
}
});
}
}

template<typename F, typename... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
using return_type = typename std::result_of<F(Args...)>::type;

auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));

std::future<return_type> result = task->get_future(); // 返回一个futur对象,result通过result.get()获取线程函数的返回值 如果线程函数没有执行完就会阻塞在result.get()
{
std::unique_lock<std::mutex> lock(queueMutex);
if (stop) {
throw std::runtime_error("enqueue on stopped ThreadPool");
}
tasks.emplace([task]() { (*task)(); }); // Lambda函数是一种可调用对象 Lambda函数的语法为[捕获列表](参数列表) { 函数体 }。
}
condition.notify_one();
return result;
}

~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queueMutex);
stop = true;
}
condition.notify_all();
for (std::thread& worker : workers) {
worker.join();
}
}

private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queueMutex;
std::condition_variable condition;
bool stop;
};

// 示例任务函数
int printHello(int num) {
std::cout << "Hello from thread " << std::this_thread::get_id() << "! Num: " << num << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
return num;
}

int main() {
ThreadPool pool(4);

std::vector<std::future<int>> results;

// 提交任务到线程池
std::cout << "Enqueuing tasks..." << std::endl;
for (int i = 0; i < 8; ++i) {
results.push_back(pool.enqueue(printHello, i));
}

for (int i = 0; i < 8; ++i) {
int num = results[i].get(); // 获取线程函数的返回值
std::cout<< "获取到线程函数的返回值:" << num << std::endl; // 获取线程函数的返回值
}

// 等待任务完成
std::this_thread::sleep_for(std::chrono::seconds(5));

return 0;
}

参考链接

  1. c++中的多线程:概念、基本用法、锁以及条件变量和优先级调度策略,by 青山牧云人.
  2. 【C++】多线程(thread)使用详解,by OpenC++.
  3. C++多线程详解(全网最全),by cpp后端技术.
  4. 多线程,by wikipedia.
  5. 详解 C++ 多线程的condition_variable,by CPP加油站.
  6. C++11之std::future对象使用说明,by Jimmy1224.
  7. C++11实现的简单线程池、模板的使用实例:1.向队列中放待执行函数,2.取出队列中待执行函数,by 好人~.
  8. 手把手带你实现std::function,弄懂底层原理,by QZQ54188.
  9. 一文读懂C++11的Lambda表达式的原理与使用场景,by linux.
  10. C++ 函数声明(后置返回类型),by CG6316.
  11. 【C++11 多线程】future与promise(八),by fengMisaka.
  12. C++ 中 typename 关键字的完整指南,by 香草美人.
  13. std::future和std::promise详解(原理、应用、源码),by 孙梓轩.
  14. 1. std::result_of是什么?为什么它出现?,by 讳疾忌医_note.
  15. C++之std::queue::emplace,by jzjhome.
  16. c++11多线程之packaged_task<>介绍与实例,by 荆楚闲人.
  17. 【C++】std::make_shared 详解,by 快起床啊你.
  18. C++11中的std::bind 简单易懂,by 云飞扬_Dylan.
  19. C++编程系列笔记(3)——std::forward与完美转发详解,by 小龙爱学习​.

GO语言安装配置

发表于 2025-11-27

最近找了一个 NTP 时间同步工具,使用 GO 语言编写,能够跨平台在 Windows 、 Linux 、 Mac 上运行,挺实用的,但是需要配置 GO 语言环境,于是记录一下过程。

安装

GO 语言环境的安装请参考:

  • Download and install

配置

加速下载

下载 GO 语言相关模块时可能被墙,需要设置代理加速下载,方法如下:

1
2
3
4
5
# 执行下面的指令
go env -w GOPROXY=https://goproxy.cn,direct

# 输出确认一下,找到有 GOPROXY 的这一行,看是否有https://goproxy.cn,direct
go env

参考链接

  1. ntp-timer,by seraphique.
  2. Go设置GOPROXY国内加速,by ShengOasis.

IDEA控制台中文乱码解决方法

发表于 2025-09-27

使用 IDEA 集成开发环境运行 Sprint Boot 应用程序时,控制台中文乱码,参考文章1分钟解决IntelliJ IDEA 控制台中文乱码,统一设置 utf-8,再也不会乱码了中第一种方法解决了中午乱码问题。

参考链接

  1. 1分钟解决IntelliJ IDEA 控制台中文乱码,统一设置 utf-8,再也不会乱码了,by 程序员徐师兄.

消息队列学习笔记

发表于 2025-09-26

消息队列是一种常用的软件架构,有必要了解和学习它。

基本知识

定义

消息队列(Message Queue,简称MQ)是一种在计算机系统中用于在不同应用程序或服务之间进行异步通信的中间件技术,它通过一个存储消息的队列作为中间人,允许发送者(生产者)将消息放入队列,接收者(消费者)则在准备好时从队列中取出并处理,从而实现系统解耦、异步处理和流量削峰等目标。消息队列的出现解决了分布式系统中数据丢失、服务故障、处理能力不足以及业务系统间强耦合等问题。

核心概念

  • 生产者(Producer):负责创建和发送消息到消息队列的应用程序或服务。
  • 消费者(Consumer):负责从消息队列中接收消息并进行处理的应用程序或服务。
  • 消息(Message):在应用程序之间传递的数据包,可以是简单的文本或复杂的数据结构。
  • 消息队列(Message Queue):一个存储消息的容器,它本身是一个队列(先进先出)数据结构。
  • 代理(Broker):消息队列的核心组件,负责存储消息、确认消息的传递和重试等。

主要作用

  • 系统解耦:生产者和消费者之间不需要直接通信,降低了系统之间的依赖性。
  • 异步通信:消息的发送和接收不需要同时发生,大大提高了系统的吞吐量和响应速度。
  • 削峰填谷:在高并发场景下,消息队列能够缓冲瞬时的大量请求,将高并发的流量“削峰”,让后端系统有足够的时间处理。
  • 流量控制:通过控制消费者对消息的处理速度,可以有效避免后端服务因过载而崩溃。
  • 可靠投递:消息队列能够持久化存储消息,即使接收者暂时不可用,消息也不会丢失,保证了数据的安全。

常见用例

  • 分布式事务::实现不同服务之间的数据最终一致性。
  • 日志处理::将日志数据异步地从各个服务发送到集中的日志处理系统。
  • 实时数据处理::在流处理和大数据场景下,用于数据流的缓冲和转发。

主流技术

  • RabbitMQ:一个老牌的开源消息队列,功能强大,支持多种消息协议。
  • Kafka:由LinkedIn开发,以高性能和高吞吐量著称,常用于大数据流式处理场景。
  • RocketMQ:由阿里巴巴开发,是轻量级的高性能分布式消息中间件。
  • ActiveMQ:一个由Apache开发的开源消息中间件,支持多种传输协议。

与模型对比

消息队列与发布/订阅的对比

消息队列使用点对点消息传递模式,在该模式中,一个应用程序(称为“发送者”)向队列提交消息,另一个应用程序(称为“接收者”)则从队列中获取并使用消息。发送者和使用者之间存在紧密耦合的一对一关系,并且每条消息只能使用一次。

如果您的应用程序需要将消息分发给多方,则可以组合多个消息队列,或者使用发布/订阅 (pub/sub) 消息传递模型。

在发布/订阅消息传递中,生成消息的应用程序称为发布者,而使用该消息的应用程序称为订阅者。每条消息都会发布到一个主题,订阅该主题的每个应用程序都会获得发布到它的所有消息的副本。

大多数消息传递中间件解决方案都支持消息队列(点对点)和发布/订阅消息模型。

消息队列与消息总线的对比

消息总线是一种企业服务总线 (ESB),它允许服务随处访问数据,同时确保它们在分布式系统架构中保持解耦和独立运行。当使用消息总线时,所有服务或应用程序必须共用通用数据类型、通用命令集和通用通信协议(尽管它们可能用不同的语言编写)。使用者可以决定如何使用信息。

如果解耦的应用程序要通过消息总线进行通信,则必须转换消息以使其归属于同一类型。相反,消息队列可传输各类消息,无论其类型是否相同。

参考链接

  1. Kafka、ActiveMQ、RabbitMQ、RocketMQ 区别以及高可用原理,by 爱撸猫的杰.
  2. 消息队列,by wikipedia.
  3. 什么是消息队列?,by ibm.
  4. 消息总线和消息队列有何区别?,by kimmking.
  5. 企业服务总线,by wikipedia.

Vlan配置方法

发表于 2025-09-22

最近单位有一台计算机,只有一个网卡,但是需要通三个网段通信,为了避免各个网段之间的组播通信流量占用带宽,拟采用Vlan技术,使用三次交换机进行逻辑隔离。具体过程记录如下。

具体方法

使用 VLAN 接口。

核心思想是:在计算机的网络接口上创建多个虚拟接口,并将每个虚拟接口关联到不同的VLAN。

这种方法适用于支持802.1Q VLAN标记的交换机和操作系统。它在单个物理网卡上创建多个逻辑接口。

  • 物理连接:服务器通过一根网线连接到支持802.1Q的交换机端口。该交换机端口需要被配置为Trunk模式,允许携带多个VLAN的流量。

  • 服务器端配置:在服务器的操作系统上,你需要创建VLAN虚拟接口。

1
2
3
4
5
6
7
8
9
10
11
例如:

物理网卡名:eth0

创建的虚拟接口:

eth0.10 (对应VLAN 10)

eth0.20 (对应VLAN 20)

eth0.30 (对应VLAN 30)

对于Realtek网卡,可使用realtek diagnostic utility工具,创建多个vlan网口。具体请参考 realtek adapter的vlan设定。

  • IP地址分配:为每个虚拟接口分配一个属于相应VLAN网段的IP地址。
1
2
3
4
5
eth0.10 -> 192.168.10.100/24 (VLAN 10的网关可能是 192.168.10.1)

eth0.20 -> 192.168.20.100/24 (VLAN 20的网关可能是 192.168.20.1)

eth0.30 -> 192.168.30.100/24 (VLAN 30的网关可能是 192.168.30.1)

工作原理: 当服务器要发送一个数据包到VLAN 10的网络时,它会通过 eth0.10 发出,操作系统会自动给这个数据包打上VLAN 10的标签。交换机的Trunk端口收到后,会根据标签将数据包转发到VLAN 10。反之,当交换机发送一个带有VLAN 20标签的数据包给服务器时,只有服务器的 eth0.20 接口能接收到它。

跨Vlan通信

  • 方式一:使用三层交换机(推荐方案)
  • 方式二:使用路由器(“单臂路由”)
  • 方式三:使用防火墙

参考链接

  1. realtek adapter的vlan设定,by helloweifa.
  2. 什么是VLAN,by huawei.
  3. 什么是组播?,by huawei.
  4. 配置终端直连三层网关设备进行VLAN间通信示例,by huawei.

NTP时间同步设置方法

发表于 2025-09-20 | 更新于 2025-09-24

对于分布式系统的运转而言,各个分布式的实体基于同一时间标准是必要条件,如果各个分布式实体的时间标准不统一,整个系统必然分崩离析。下面介绍在不同操作系统平台设置 NTP 客户端的方法。

Windows平台

  • 设置 NTP 时间服务器
1
2
3
4
5
打开日期和时间设置

找到Internet时间设置

选择NTP服务器并同步
  • 调整时间同步频率
1
2
3
4
5
打开注册表编辑器(regedit)。

导航到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient。

找到名为 SpecialPollInterval 的DWORD值,双击打开,在“数值数据”中填入期望的同步间隔(以秒为单位)即可调整同步频率。

注意: SpecialPollInterval 值的设置必须在位于 MinPollInterval 和 MaxPollInterval 之间,否则 NTP 客户端不会按 SpecialPollInterval 预期同步。具体请参考:京准电钟课堂:NTP时钟同步时客户端未按预期同步 。

Linux平台

chrony 既可作时间服务器服务端,也可作客户端。性能比 ntp 好,且配置管理方便。chrony 由两个程序组成,分别是 chronyd 和 chronyc。chronyd 是一个后台运行的守护进程,用于调整内核中运行的系统时钟和时钟服务器同步。它确定计算机增减时间的比率,并对此进行补偿。chronyc 提供了一个用户界面,用于监控性能并进行多样化的配置。它可以在 chronyd 实例控制的计算机上工作,也可以在一台不同的远程计算机上工作。

以 NTP 工具 Chrony 为例,具体步骤如下:

  • 安装chrony
1
2
3
4
5
6
7
8
9
10
11
# 查看 chrony 依赖的包
apt-cache depends chrony

# 安装chrony,观察chrony依赖的包
sudo apt-get install chrony

# 下载 chrony及其依赖包
apt-get download chrony

# 离线安装chrony
sudo dpkg -i *.deb
  • 修改配置文件 /etc/chrony/chrony.conf
1
2
# 注释默认的 NTP 服务器pool,配置上级时间服务器
server 192.168.1.30 iburst
  • 重启chrony服务
1
2
3
4
5
6
7
8
9
10
11
# 获取 chronyd 的PID
pgrep chronyd

# 直接终止(推荐)
kill <chronyd的PID>

# 强制终止(如果进程没有响应)
kill -9 <chronyd的PID>

# 启动 chronyd
sudo chronyd
  • 查看并等待与NTP服务器同步
1
2
3
4
# 确保你的chrony服务器自身已经成功与上层服务器同步。可以通过 chronyc sources 命令检查,服务端需要先成功同步时间,才能为客户端提供同步服务, NTP服务器前设置 ^* 表示已与该服务区时钟同步。

chronyc sources -v
chronyc sourcestats -v
  • 手动同步NTP客户端时间
1
sudo chronyc -a makestep

参考链接

  1. NTP协议学习笔记,by jackhaung.
  2. WINDOWS 10如何配置NTP服务(Server&Client),by 胡浪波.
  3. windows系统时间同步及同步频率设置,by li88811.
  4. 第三章:ubuntu 24.04.1 ntp服务安装,by 王小二.
  5. Ubuntu部署NTP服务器和客户端,by lsgxeva.
  6. 京准电钟课堂:NTP时钟同步时客户端未按预期同步 , by 安徽京准2024.
12…54下一页

Jack Huang

534 日志
69 标签
© 2026 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse