Linux时钟与时间API
深入理解 Linux 时钟与时间 API
时间是计算领域的基础概念之一。在 Linux 系统中,精确可靠的时间管理对于系统日志记录、任务调度、网络通信、性能分析、文件系统操作乃至应用程序的正确运行都至关重要。本文将深入探讨 Linux 中的时钟类型、相关的 C API、使用示例、流程、常见应用场景以及注意事项。
1. Linux 中的时钟概念
Linux 系统中主要涉及两种类型的时钟:
-
硬件时钟 (Hardware Clock - RTC):
- 也称为实时时钟 (Real-Time Clock) 或 CMOS 时钟。
- 这是一个由电池供电的物理硬件芯片,通常位于主板上。
- 作用: 即使在系统关机或断电的情况下,也能持续记录时间。它主要用于在系统启动时初始化系统时钟。
- 交互: 用户通常通过
hwclock
命令来读取或设置硬件时钟。内核在启动时读取 RTC 来设置系统时间,在关机时(可选)将系统时间写回 RTC。
-
系统时钟 (System Clock / Software Clock):
- 也称为内核时钟。这是操作系统内核维护的时钟。
- 来源: 系统时钟通常由硬件定时器(如 PIT - Programmable Interval Timer, HPET - High Precision Event Timer, 或 CPU 的 TSC - Time Stamp Counter)产生的中断驱动。系统启动时,它会根据硬件时钟进行初始化。
- 运行期间: 系统运行时,应用程序和内核主要依赖系统时钟。为了保持准确性,系统时钟通常会通过网络时间协议 (NTP - Network Time Protocol) 与外部时间服务器进行同步,这可能导致系统时钟发生跳变(向前或向后调整)。
- 特性: 系统时钟是易变的,并且精度和分辨率取决于底层的硬件定时器和内核实现。
系统时钟内部又可以根据不同的参照系和特性细分为多种类型(clockid_t
),其中最重要的是:
CLOCK_REALTIME
: 系统范围的实时时钟(挂钟时间 Wall-clock time)。它表示自 Unix Epoch (1970-01-01 00:00:00 +0000 UTC) 以来的秒数和纳秒数。这个时钟是可调的,意味着它可以因为系统管理员手动修改、NTP 同步、闰秒调整等原因而发生不连续的跳变(向前或向后)。因此,它适合表示日历时间,但不适合测量精确的时间间隔。CLOCK_MONOTONIC
: 系统范围的单调时钟。它表示自系统启动(或其他未指定起点)以来的时间。这个时钟保证是单调递增的,不受 NTP 调整或管理员手动修改时间的影响(除非系统重启)。它非常适合用来测量时间间隔、设置超时等场景。它的起点是未定义的,所以其绝对值没有意义,只有差值有意义。CLOCK_MONOTONIC_RAW
: 类似于CLOCK_MONOTONIC
,但它试图提供更接近硬件的原始单调时间,不受 NTP 频率调整(skew)的影响。NTP 为了让CLOCK_REALTIME
更平滑地接近目标时间,可能会微调CLOCK_MONOTONIC
的前进速率,而CLOCK_MONOTONIC_RAW
则不受此影响。CLOCK_PROCESS_CPUTIME_ID
: 测量当前进程所消耗的 CPU 时间(用户态 + 内核态)。CLOCK_THREAD_CPUTIME_ID
: 测量当前线程所消耗的 CPU 时间(用户态 + 内核态)。
2. 关键 C/C++ 时间 API
Linux 提供了丰富的 C API 来与这些时钟交互。需要包含 <time.h>
头文件。
2.1 time()
- 获取低精度日历时间
#include <time.h>time_t time(time_t *tloc);
功能: 获取 CLOCK_REALTIME 的当前时间,但精度只有秒级别。它是最古老、最简单的获取日历时间的方式。
参数:
time_t *tloc
: 如果非NULL
,获取到的时间值也会存储在tloc
指向的位置。
返回值:
- 成功: 返回自 Unix Epoch 以来的秒数 (
time_t
类型,通常是long int
)。 - 失败: 返回
(time_t)-1
。
2.2 gettimeofday()
- 获取较高精度日历时间 (已不推荐)
#include <sys/time.h> // 注意头文件int gettimeofday(struct timeval *tv, struct timezone *tz);struct timeval {time_t tv_sec; /* seconds */suseconds_t tv_usec; /* microseconds */
};
功能: 获取 CLOCK_REALTIME 的当前时间,精度可以达到微秒。在 POSIX.1-2008 标准中,此函数已被标记为过时 (obsolete),推荐使用 clock_gettime()
替代。
参数:
struct timeval *tv
: 指向timeval
结构体的指针,用于存储获取到的秒数和微秒数。struct timezone *tz
: 此参数已废弃,应始终传递NULL
。它以前用于获取时区信息,但现在不应再使用。
返回值:
- 成功: 返回 0。
- 失败: 返回 -1,并设置
errno
。
2.3 clock_gettime()
- 获取指定时钟的高精度时间 (推荐)
#include <time.h>int clock_gettime(clockid_t clk_id, struct timespec *tp);struct timespec {time_t tv_sec; /* seconds */long tv_nsec; /* nanoseconds */
};
功能: 获取由 clk_id
指定的时钟的当前时间,精度可达纳秒。这是目前推荐使用的获取高精度时间的主要接口。
参数:
clockid_t clk_id
: 指定要获取哪个时钟的时间。常用的值包括:CLOCK_REALTIME
: 挂钟时间。CLOCK_MONOTONIC
: 单调递增时间。CLOCK_PROCESS_CPUTIME_ID
: 进程 CPU 时间。CLOCK_THREAD_CPUTIME_ID
: 线程 CPU 时间。CLOCK_MONOTONIC_RAW
: 原始单调时间。- 还有其他特定用途的时钟 ID。
struct timespec *tp
: 指向timespec
结构体的指针,用于存储获取到的秒数和纳秒数 (0-999,999,999)。
返回值:
- 成功: 返回 0。
- 失败: 返回 -1,并设置
errno
(例如EINVAL
表示clk_id
无效)。
2.4 clock_getres()
- 获取时钟分辨率
#include <time.h>int clock_getres(clockid_t clk_id, struct timespec *res);
功能: 获取由 clk_id
指定的时钟的分辨率(即能够区分的最小时间间隔)。
参数:
clockid_t clk_id
: 指定要查询哪个时钟。struct timespec *res
: 指向timespec
结构体的指针,用于存储获取到的时钟分辨率。例如,如果分辨率是 1 纳秒,则res->tv_sec
为 0,res->tv_nsec
为 1。
返回值:
- 成功: 返回 0。
- 失败: 返回 -1,并设置
errno
。
2.5 nanosleep()
/ clock_nanosleep()
- 高精度睡眠
#include <time.h>int nanosleep(const struct timespec *req, struct timespec *rem);
int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *request, struct timespec *remain);
nanosleep()
功能: 使当前线程暂停执行指定的相对时间段 (req
)。它基于 CLOCK_REALTIME
,可能会受系统时间调整影响,且易被信号中断。
nanosleep()
参数:
const struct timespec *req
: 指向timespec
结构体,指定需要睡眠的时长。struct timespec *rem
: 如果睡眠被信号中断,剩余未睡够的时间会存储在这里(如果非NULL
)。
nanosleep()
返回值:
- 成功 (睡足时间): 返回 0。
- 失败 (通常是被信号中断): 返回 -1,
errno
设置为EINTR
。
clock_nanosleep()
功能: 更强大的睡眠函数,允许指定基于哪个时钟 (clockid
) 进行睡眠,并且可以指定是相对时间还是绝对时间 (flags
)。推荐使用它替代 nanosleep
,特别是需要基于单调时钟的精确延时。
clock_nanosleep()
参数:
clockid_t clockid
: 指定用于计时的时钟,通常使用CLOCK_MONOTONIC
来避免CLOCK_REALTIME
的跳变问题。int flags
: 控制睡眠类型:0
: 表示request
是一个相对时间间隔。TIMER_ABSTIME
: 表示request
是一个绝对时间点(基于clockid
指定的时钟)。线程将睡眠直到指定时钟到达request
的时间。
const struct timespec *request
: 指向timespec
结构体,指定睡眠时长(相对时间)或目标唤醒时间点(绝对时间)。struct timespec *remain
: 类似于nanosleep
,如果睡眠被信号中断(仅对相对睡眠有效),剩余时间会存储在这里(如果非NULL
)。
clock_nanosleep()
返回值:
- 成功 (睡足时间或到达绝对时间点): 返回 0。
- 失败: 返回错误码 (正数,与
errno
不同)。常见的错误码包括EINTR
(被信号中断),EINVAL
(参数无效),ENOTSUP
(不支持指定的时钟或标志)。
3. C 代码测试用例
测试用例 1: 获取不同时钟的当前时间
#include <stdio.h>
#include <time.h>
#include <sys/time.h> // for gettimeofday
#include <unistd.h> // for sleepint main() {// 1. Using time() (seconds precision)time_t current_time_t = time(NULL);if (current_time_t == (time_t)-1) {perror("time failed");} else {// ctime converts time_t to a string (includes newline)printf("time() : %s", ctime(¤t_time_t));}// 2. Using gettimeofday() (microseconds precision - obsolete)struct timeval tv;if (gettimeofday(&tv, NULL) == -1) {perror("gettimeofday failed");} else {printf("gettimeofday() : %ld seconds, %ld microseconds\n", (long)tv.tv_sec, (long)tv.tv_usec);}// 3. Using clock_gettime() (nanoseconds precision - recommended)struct timespec ts_realtime, ts_monotonic;// Get CLOCK_REALTIMEif (clock_gettime(CLOCK_REALTIME, &ts_realtime) == -1) {perror("clock_gettime CLOCK_REALTIME failed");} else {printf("CLOCK_REALTIME : %ld seconds, %ld nanoseconds\n", (long)ts_realtime.tv_sec, ts_realtime.tv_nsec);}// Get CLOCK_MONOTONICif (clock_gettime(CLOCK_MONOTONIC, &ts_monotonic) == -1) {perror("clock_gettime CLOCK_MONOTONIC failed");} else {// Note: Monotonic time's absolute value isn't meaningful, only its differenceprintf("CLOCK_MONOTONIC : %ld seconds, %ld nanoseconds (since boot/epoch)\n", (long)ts_monotonic.tv_sec, ts_monotonic.tv_nsec);}// 4. Get Clock Resolutionstruct timespec res;if (clock_getres(CLOCK_MONOTONIC, &res) == -1) {perror("clock_getres failed");} else {printf("CLOCK_MONOTONIC resolution: %ld seconds, %ld nanoseconds\n", (long)res.tv_sec, res.tv_nsec);}return 0;
}
编译: gcc time_example1.c -o time_example1 -lrt
(需要链接 librt 库,因为 clock_* 函数在其中)
测试用例 2: 使用 CLOCK_MONOTONIC 测量时间间隔
#include <stdio.h>
#include <time.h>
#include <unistd.h> // for sleep// Helper function to calculate difference between two timespecs
void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result) {if ((stop->tv_nsec - start->tv_nsec) < 0) {result->tv_sec = stop->tv_sec - start->tv_sec - 1;result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;} else {result->tv_sec = stop->tv_sec - start->tv_sec;result->tv_nsec = stop->tv_nsec - start->tv_nsec;}
}int main() {struct timespec start_time, end_time, elapsed_time;// Record start time using monotonic clockif (clock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {perror("clock_gettime start failed");return 1;}printf("Starting operation...\n");// Simulate some work (e.g., sleep for 1.5 seconds)sleep(1); // Standard sleep uses secondsusleep(500000); // usleep uses microseconds// Record end time using monotonic clockif (clock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {perror("clock_gettime end failed");return 1;}printf("Operation finished.\n");// Calculate elapsed timetimespec_diff(&start_time, &end_time, &elapsed_time);printf("Elapsed time: %ld seconds, %ld nanoseconds\n", (long)elapsed_time.tv_sec, elapsed_time.tv_nsec);// Convert to milliseconds for easier readingdouble elapsed_ms = (double)elapsed_time.tv_sec * 1000.0 + (double)elapsed_time.tv_nsec / 1000000.0;printf("Elapsed time: %.3f milliseconds\n", elapsed_ms);return 0;
}
编译: gcc time_example2.c -o time_example2 -lrt
测试用例 3: 使用 clock_nanosleep 进行精确延时
#include <stdio.h>
#include <time.h>
#include <errno.h> // For errnoint main() {struct timespec start_time, end_time, sleep_duration, elapsed_time;int ret;// Define sleep duration: 0 seconds, 500 million nanoseconds (0.5 seconds)sleep_duration.tv_sec = 0;sleep_duration.tv_nsec = 500000000; // 0.5 secondsprintf("Attempting to sleep for %ld ns using clock_nanosleep with CLOCK_MONOTONIC...\n", sleep_duration.tv_nsec);// Record start timeif (clock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {perror("clock_gettime start failed");return 1;}// Use clock_nanosleep for relative sleep based on CLOCK_MONOTONICdo {ret = clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep_duration, &sleep_duration);// Keep sleeping for the remaining duration if interrupted by a signal} while (ret == EINTR);if (ret != 0) {fprintf(stderr, "clock_nanosleep failed with error: %d\n", ret);return 1;}// Record end timeif (clock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {perror("clock_gettime end failed");return 1;}printf("Sleep finished.\n");// Calculate actual elapsed timetimespec_diff(&start_time, &end_time, &elapsed_time);printf("Actual elapsed time: %ld seconds, %ld nanoseconds\n", (long)elapsed_time.tv_sec, elapsed_time.tv_nsec);return 0;
}// Include the timespec_diff function from Example 2 here
void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result) {if ((stop->tv_nsec - start->tv_nsec) < 0) {result->tv_sec = stop->tv_sec - start->tv_sec - 1;result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;} else {result->tv_sec = stop->tv_sec - start->tv_sec;result->tv_nsec = stop->tv_nsec - start->tv_nsec;}
}
编译: gcc time_example3.c -o time_example3 -lrt
4. 流程图:测量代码块执行时间
下面是一个使用 CLOCK_MONOTONIC 测量代码块执行时间的简化流程图(使用 Mermaid 语法):
graph TDA[Start] --> B{Call clock_gettime(CLOCK_MONOTONIC, &start_time)};B --> C[Execute Code Block to Measure];C --> D{Call clock_gettime(CLOCK_MONOTONIC, &end_time)};D --> E[Calculate Difference: elapsed_time = end_time - start_time];E --> F[Use/Display elapsed_time];F --> G[End];B -- Error Handling --> H{Handle Error};D -- Error Handling --> H;
流程图解释:
- 程序开始。
- 调用
clock_gettime
获取基于单调时钟的起始时间点,并检查错误。 - 执行需要测量时间的代码块。
- 再次调用
clock_gettime
获取结束时间点,并检查错误。 - 计算结束时间与起始时间的差值,得到精确的时间间隔。
- 使用或显示计算出的时间间隔。
- 程序结束。
5. 开源项目中的使用方式
Linux 时间 API 在几乎所有类型的开源项目中都有广泛应用:
- 日志系统 (e.g., systemd-journald, rsyslog): 使用
CLOCK_REALTIME
(通常通过gettimeofday
或clock_gettime
) 为每条日志消息打上精确的时间戳,用于事件排序和问题诊断。有时也会记录CLOCK_MONOTONIC
时间戳用于启动相关的事件排序。 - Web 服务器 (e.g., Nginx, Apache): 记录请求到达和响应发出的时间戳 (通常是
CLOCK_REALTIME
) 用于访问日志;使用CLOCK_MONOTONIC
实现连接超时、请求超时、keep-alive 超时等。 - 数据库 (e.g., PostgreSQL, MySQL): 使用
CLOCK_REALTIME
记录事务提交时间、行版本时间戳;使用CLOCK_MONOTONIC
实现内部操作的超时(如锁等待超时、查询执行超时)。 - 调度器与作业队列 (e.g., cron, systemd timers, Celery): 使用
CLOCK_REALTIME
来决定何时触发预定的任务。内部可能使用CLOCK_MONOTONIC
实现等待间隔。 - 性能监控工具 (e.g., perf, eBPF tools, Prometheus node_exporter): 大量使用
CLOCK_MONOTONIC
或CLOCK_MONOTONIC_RAW
来精确测量函数执行时间、系统调用耗时、网络延迟等性能指标。CLOCK_(THREAD/PROCESS)_CPUTIME_ID
用于测量 CPU 使用率。 - 网络协议栈: 使用
CLOCK_MONOTONIC
来管理 TCP 重传超时 (RTO)、keep-alive 定时器等。 - 实时系统 (RTOS features in Linux with PREEMPT_RT patch): 对时钟精度和定时器延迟有极高要求,大量依赖高精度定时器和
clock_nanosleep(TIMER_ABSTIME)
实现精确的周期性任务和截止时间调度。
6. 常用场景总结
- 日志记录: 需要知道事件发生的确切日历时间 ->
clock_gettime(CLOCK_REALTIME)
。 - 测量时间间隔/代码耗时: 需要精确测量一个操作持续了多长时间,不受时钟调整影响 ->
clock_gettime(CLOCK_MONOTONIC)
。 - 设置超时: 需要等待一段时间或等到某个未来时间点,且不受时钟调整影响 ->
clock_nanosleep(CLOCK_MONOTONIC, ...)
。 - 任务调度: 需要在特定的日历时间执行任务 -> 基于
CLOCK_REALTIME
检查。 - 性能分析: 需要测量 CPU 消耗 ->
clock_gettime(CLOCK_PROCESS_CPUTIME_ID / CLOCK_THREAD_CPUTIME_ID)
;需要测量代码段执行时间 ->clock_gettime(CLOCK_MONOTONIC)
。 - 网络通信: 实现协议超时 ->
CLOCK_MONOTONIC
。 - 需要与外部世界同步的时间: 显示给用户、与其他系统交换基于日历时间的数据 ->
CLOCK_REALTIME
。
7. 注意事项
- CLOCK_REALTIME 的不连续性: 切记
CLOCK_REALTIME
可能随时向前或向后跳变。绝不能用它来测量时间间隔。 - CLOCK_MONOTONIC 的起点: 它的起点未定义(通常是系统启动时间),不同系统或同系统重启后起点会变。只能用于测量时间差。
- 时钟分辨率 vs. 精度:
clock_getres
返回的是理论上的最小可分辨单位,但实际精度可能受硬件、内核调度延迟等因素影响。 - API 调用开销:
clock_gettime
通常比旧的gettimeofday
或time
更快(因为它可能通过 VDSO 在用户空间执行,避免陷入内核),但频繁调用仍有开销。对于极高性能敏感的代码,有时会直接读取 TSC(但需处理 CPU 频率变化和多核同步问题,通常更复杂)。 - 时间类型溢出: 对于非常长的运行时间,
time_t
(秒) 最终也会溢出(例如 32 位系统的 Y2038 问题)。struct timespec
的tv_sec
同样受time_t
限制。 - 链接库: 使用
clock_*
系列函数通常需要链接librt
(-lrt
)。较新的 glibc 版本可能已将其集成到主 libc 中,不再需要显式链接。
8. 总结
Linux 提供了强大而灵活的时间管理机制。理解硬件时钟和系统时钟(特别是 CLOCK_REALTIME
和 CLOCK_MONOTONIC
)的区别是正确使用时间 API 的基础。clock_gettime()
和 clock_nanosleep()
是现代 Linux 编程中处理高精度时间和延时的首选工具。根据具体需求(需要日历时间还是时间间隔?是否需要抵抗时钟调整?)选择合适的时钟 ID 和 API,并注意错误处理和潜在的时钟跳变问题,是编写健壮、可靠的 Linux 应用程序的关键一环。
相关文章:
Linux时钟与时间API
深入理解 Linux 时钟与时间 API 时间是计算领域的基础概念之一。在 Linux 系统中,精确可靠的时间管理对于系统日志记录、任务调度、网络通信、性能分析、文件系统操作乃至应用程序的正确运行都至关重要。本文将深入探讨 Linux 中的时钟类型、相关的 C API、使用示例…...
闭包(Closure)及其作用和影响
一、闭包是什么 闭包(Closure)指的是一个函数能够记住并访问其词法作用域(lexical scope),即使该函数在其词法作用域之外执行。换句话说,闭包让函数可以“记住”它被创建时的环境。 闭包的核心特…...
toLua笔记
基本 LuaState luaStatenew LuaState(); luaState.Start(); luaState.DoString("xxx"); luaState.DoFile("yyy.lua"); luaState.Require("zzz");//不要加.lua后缀 luaState.CheckTop();//检查解析器栈顶为空 luaState.Dispose(); luaStatenull;…...
20:深度学习-多层感知器原理
深度学习-多层感知器的原理 ------------------常州龙熙机器视觉培训班-课程资料 1.单层感知机 多层感知机是由感知机推广而来,感知机学习算法(PLA: Perceptron Learning Algorithm)用神经元的结构进行描述的话就是一个单独的。 首先了解下单层感知机: b--常量 …...
高频数据冲击数据库的技术解析与应对方案
目录 前言一、问题现象与影响分析1.1 典型场景表现1.2 核心问题分类 二、失效根源深度剖析2.1 架构设计缺陷2.2 缓存策略缺陷 三、解决方案与最佳实践3.1 缓存架构设计3.1.1 分层缓存架构3.1.2 热点数据识别 3.2 缓存策略优化3.2.1 动态过期时间算法3.2.2 缓存更新策略对比 3.3…...
(37)VTK C++开发示例 ---纹理地球
文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容👉内容导航 👈👉VTK开发 👈 1. 概述 将图片纹理贴到球体上,实现3D地球的效果。 该代码使用了 VTK (Visualization Toolkit) 库来创建一个纹理…...
LeetCode - 1137.第N个泰波那契数
目录 题目 解法 动态规划解法 核心思想 执行流程 具体例子 时间复杂度和空间复杂度 代码 题目 1137. 第 N 个泰波那契数 - 力扣(LeetCode) 解法 动态规划解法 核心思想 动态规划是一种通过将复杂问题分解为更小子问题来解决的算法方法。我将…...
智能决策支持系统的系统结构:四库架构与融合范式
前文我们已经了解了智能决策支持系统的基本概念以及基本构件,接下来我们了解一下系统结构。 有关“智能决策支持系统的基本概念”的内容,可看我文章:智能决策支持系统的基本概念与理论体系-CSDN博客 有关“智能决策支持系统的基本构建”的…...
单片机裸机环境下临界区保护
目录 1、直接中断屏蔽法 2、嵌套计数优化法 3、BASEPRI寄存器应用 4、动态优先级调整策略 5、LDREX/STREX指令应用 6、位带别名区原子访问 7、上下文感知保护 8、中断延迟优化技术 在嵌入式系统开发中,临界区保护是确保系统可靠性的关键技术。本文以ARM Cor…...
【数字电路】第六章 时序逻辑电路
一、时序逻辑电路概述 1.逻辑电路的分类 2.时序逻辑电路的一般结构形式 3.时序逻辑电路的描述方法 4.时序逻辑电路按触发器动作特点分类 5.时序逻辑电路按输出信号特点分类 6.常用时序逻辑电路 二、同步时序逻辑电路的分析 1.同步时序逻辑电路的分析方法 TTL触发器允许输入端…...
Spring Boot的GraalVM支持:构建低资源消耗微服务
文章目录 引言一、GraalVM原生镜像技术概述二、Spring Boot 3.x的GraalVM支持三、适配GraalVM的关键技术点四、构建原生镜像微服务实例五、性能优化与最佳实践总结 引言 微服务架构已成为企业应用开发的主流模式,但随着微服务数量的增加,资源消耗问题日…...
MySQL中的窗口函数
深入理解窗口函数(Window Functions) 窗口函数确实经常用于分组后为行分配序号(如1,2,3…),但它的功能远不止于此。窗口函数是SQL中极其强大的分析工具,可以让你在不减少行数的情况下进行复杂计算。 窗口函…...
WITH在MYSQL中的用法
WITH 子句(也称为公共表表达式,Common Table Expression,简称 CTE)是 SQL 中一种强大的查询构建工具,它可以显著提高复杂查询的可读性和可维护性。 一、基本语法结构 WITH cte_name AS (SELECT ... -- 定义CTE的查询…...
人工智能:如何快速筛选出excel中某列存在跳号的单元格位置?
前提: 电脑上必须提前安装好了【office AI】软件工具 方法如下: 1、打开要操作的excel表格,点击上方的【officeAI】,再点击左边的【右侧面板】按钮,就会出现如下右侧的【OfficeAI助手】 2、在OfficeAI助手的聊天框…...
动态功耗与静态功耗
0 英文缩写 SOI(Silicon on Insulator)绝缘体上硅FET(Field-Effect Transistor)场效应管CMOS(Complementary Metal Oxide Semiconductor)互补金属氧化物半导体 1 功耗分类 CMOS电路功耗主要可以通过如下…...
Webug4.0靶场通关笔记10- 第14关链接注入
目录 第14关 链接注入 1.打开靶场 2.源码分析 3.渗透实战 (1)方法1:跳转外部网页 (2)方法2:获取cookie 4.漏洞防御 本文通过《webug靶场第14关 链接注入》来进行渗透实战。 第14关 链接注入 链接注…...
PyTorch_指定运算设备 (包含安装 GPU 的 PyTorch)
PyTorch默认会将张量创建在 CPU 控制的内存中,即:默认的运算设备为 CPU。我们也可以将张量创建在 GPU 上,能够利用对于矩阵计算的优势加快模型训练。 将张量移动到 GPU 上有两种方法: 使用 cuda 方法直接在 GPU 上创建张量使用 …...
Pytorch-CUDA版本环境配置
Pytorch-CUDA版本环境配置 电脑如果是Windows平台下的Nvidia GPU的用户,需配置Pytorch的CUDA版本,分为三步: 1. 安装或更新NVIDA显卡驱动 官方驱动下载地址: https://www.nvidia.cn/Download/index.aspx?langcn 2. 安装CUDA To…...
力扣:24两两交换链表的节点
目录 1.题目描述: 2.算法思路: 3.代码展示: 1.题目描述: 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能…...
SETNX的存在问题和redisson进行改进的原理
首先分布式锁的原理就是当锁不存在时则创建,创建到锁的线程则执行业务。但是在这些操作中会有一些问题,下面是redis命令setNX设置锁的代码片段 if(缓存中有){返回缓存中的数据 }else{获取分布式锁if(获取锁成功){try{查询数据库}finally{释放…...
抽象工厂模式(Abstract Factory Pattern)
很好!你现在已经开始接触设计模式了,而**抽象工厂模式(Abstract Factory Pattern)是一种常用于“创建一系列相关产品”**的经典设计模式。 我会一步步帮你理解: 🧠 一句话解释 抽象工厂模式:提…...
AVIOContext 再学习
这个目前阶段用的不多,暂时不要花费太多精力。 url 的格式不同,使用的传输层协议也不同。这块看代码还没看到自己想的这样。 目前看的信息是:avformatContext 的 io_open 回调函数 在默认情况下叫 io_open_default,在解复用的 av…...
Power Query精通指南1:查询结构设计、数据类型、数据导入与迁移(平面文件、Excel、Web)
文章目录 零、Power Query简介0.1 Power Query 主要功能0.2 Power Query 的优势0.3 Power Query 组件 一、Power Query数据处理基本流程1.1 前期准备1.2 提取1.3 转换1.3.1 Power Query 编辑器界面1.3.2 默认转换1.3.3 自定义转换 1.4 加载1.4.1 自动检测数据类型1.4.2 重命名查…...
Linux 内核升级问题
一、内核升级后启动失败 原因:initramfs 镜像未正确生成或 GRUB 配置错误。 处理步骤如下: 1、进入旧内核启动系统。 2、重新生成 initramfs: sudo dracut -f --regenerate-all 3、更新 GRUB 配置: sudo grub2-mkconfig -o /boo…...
Linux 进程间通信(IPC)详解
进程间通信(IPC)深入解析 一、进程间通信概述 在操作系统里,不同进程间常常需要进行数据交换、同步协调等操作,进程间通信(Inter - Process Communication,IPC)机制应运而生。在Linux系统中&a…...
第3章 Python 3 基础语法001
文章目录 一、缩进规则1. 基本规则2. 示例3. 多级缩进4. 常见错误二、注释规则1. 单行注释2. 多行注释3. 特殊注释4. 注释规范三、代码块规则1. 控制结构2. 函数定义3. 类定义4. 上下文管理器四、总结与最佳实践五、调试技巧以下是 Python 3 基础语法规则的详细说明,涵盖 缩进…...
数据库介绍以及windows下mysql安装
文章目录 1. 前言2. MySQL概述2.1 相关概念2.2 DBMS的分类2.3 数据库交互图2.4 MySQL 介绍 3. MySQL 安装 数据库介绍以及windows下mysql安装 1. 前言 我们浏览的淘宝商品页面详情、刷视频网站的一个个视频,这些数据其实都是存储在公司的存储系统中的。想象一下&…...
list的两种设计
1. 内存布局对比 (1) MSVC 的实现 cpp class _List_node {_List_node* _Next; // 指向下一个节点_List_node* _Prev; // 指向前一个节点_Value_type _Value; // 存储的数据 }; 特点: 每个节点包含两个指针和一个数据成员。 Debug 模式:可能添加迭代…...
【C#】一个类中的接口方法使用static和不使用static的区别
在C#中,类中的接口方法是否使用 static 修饰符会带来显著的区别。这是因为接口方法的实现和调用方式与普通方法不同,而 static 关键字的使用进一步改变了这些行为。 以下是两者的区别: 1. 不使用 static 的接口方法 在这种情况下࿰…...
共铸价值:RWA 联合曲线价值模型,撬动现实资产生态
摘要 本文提出了一种针对真实资产(RWA)产业的联合曲线激励模型,将劳动与数据贡献映射为曲线价值,并基于固定档位与指数衰减奖励发放总计 2.1亿积分。该模型结合了去中心化定价与平滑递减机制,不仅为早期贡献者提供更高…...
【libuv】基于libuv的exe链接错误
vs2017构建 基于libuv的exe链接错误 1>libuv.lib(util.obj) : error LNK2019: unresolved external symbol __imp__GetAdaptersAddresses20 referenced in function _uv_interface_addresses 1>libuv.lib(util.obj) : error LNK2019: unresolved external symbol __imp__…...
什么是生成式 AI (GenAI)?
在科技飞速发展的今天,人工智能(AI)已不再是一个遥远的概念,而是悄然融入了我们的日常生活。从智能语音助手到自动驾驶汽车,从个性化推荐系统到医疗诊断辅助,AI正以前所未有的速度改变着世界。然而,在AI的广阔领域中,有一个分支正逐渐崭露头角,成为推动未来创新的关键…...
爬虫准备前工作
1.Pycham的下载 网址:PyCharm: The only Python IDE you need 2.Python的下载 网址:python.org(python3.9版本之后都可以) 3.node.js的下载 网址:Node.js — 在任何地方运行 JavaScript(版本使用18就可…...
JVM——JVM 是如何处理异常的?
JVM 是如何处理异常的? 在 Java 编程语言中,异常处理是一种强大的机制,用于应对程序运行时出现的错误和意外情况。而 Java 虚拟机(JVM)作为 Java 程序运行的核心环境,在异常处理过程中扮演着至关重要的角色…...
网络基础-----C语言经典题目(12)
一、MTU,IP 协议头中 TTL是什么? MTU 指的是网络层能够接收的最大数据包大小,单位为字节。主要作用是限制数据链路层一次能够传输的数据量。 IP 协议头中的 TTL 是 IP 数据头部的一个 8 位字段,最初它的设计目的是限制数据包在网络…...
【第十六届蓝桥杯省赛】比赛心得与经验分享(PythonA 组)
文章目录 一、我的成绩二、我的备赛经历三、如何备赛(个人观点)1. 基础语法2. 数据结构3. 算法4. 数学 四、做题技巧与注意事项五、我的题解试题A 偏蓝 🏆100%试题B IPV6 🏆0%试题C 2025图形 🏆100%试题D 最大数字 &am…...
解决Maven项目中报错“java不支持版本6即更高的版本 7”
错误背景 当Maven项目编译或运行时出现错误提示 Java不支持版本6即更高的版本7,通常是由于项目配置的JDK版本与当前环境或编译器设置不一致导致的。例如: 项目配置的Java版本为6或7,但实际使用的是JDK 17。Maven或IDE的编译器未正确指定目标…...
MySQL--索引入门
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。 Mysql在存储数据之外,数据库系统各种还维护着满足特定查找算法的数据结构,这些数据结构以某种引用(指向)表中的数据…...
【网络原理】深入理解HTTPS协议
本篇博客给大家带来的是网络原理的知识点, 由于时间有限, 分三天来写, 本篇为线程第三篇,也是最后一篇. 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动…...
利用Elixir中的原子特性 + 错误消息泄露 -- Atom Bomb
题目信息: This new atom bomb early warning system is quite strange… 题目使用 elixir 语言 一开始,我们会访问 /page.html <!DOCTYPE html> <!-- 设定文档语言为英语 --> <html lang"en"> <head><!-- 设定字符编码为UTF-8 --><…...
机器人--STM32
STM32启动模式 1,从主闪存存储启动器启动(默认) 2,从系统存储启动器启动 下载程序时需要使用的启动方式。 3,从内置的SRAM启动...
LVGL -文本显示 英文、中文
1 文本 在 LVGL 中,文本控件(Label)是一种基本的 UI 组件,用于显示文本信息。文本控件可以用于各种场景,如显示状态信息、提示消息、标题等。在图形用户界面(GUI)开发中,文本是传达信息和指导用户的重要组成部分。为了有效地展示文本,以下是与文本相关的几个关键方面…...
Java面试资源获取
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 **1. GitHub开源项目****2. 技术博客与社区*…...
探索 Spring AI 的 ChatClient API:构建智能对话应用的利器
探索 Spring AI 的 ChatClient API:构建智能对话应用的利器 前言 在当今人工智能蓬勃发展的时代,智能对话系统成为了众多应用的核心组成部分。无论是客服机器人、智能助手还是聊天应用,都离不开高效、灵活的对话处理能力。Spring AI 作为 S…...
Java大师成长计划之第11天:Java Memory Model与Volatile关键字
📢 友情提示: 本文由银河易创AI(https://ai.eaigx.com)平台gpt-4o-mini模型辅助创作完成,旨在提供灵感参考与技术分享,文中关键数据、代码与结论建议通过官方渠道验证。 在多线程编程中,线程的执…...
java学习之数据结构:一、数组
主要是对数组所有的东西进行总结,整理 适合小白~ 目录 1.什么是数组 1.1数组定义 1.2数组创建 1)静态创建 2)动态创建 1.3数组遍历 1)for和while遍历 2)foreach遍历 2.数组越界问题及解决 2.1数组越界问题 2…...
Oracle OCP认证考试考点详解083系列04
题记: 本系列主要讲解Oracle OCP认证考试考点(题目),适用于19C/21C,跟着学OCP考试必过。 16. 第16题: 题目 解析及答案: 关于使用恢复管理器(RMAN)恢复表,以下哪三项是…...
MARM:推荐系统中的记忆增强突破
文章目录 1. 背景1.1 模型规模与推荐系统的挑战1.2 缓存技术在推荐系统中的潜力1.3 推荐系统中的数据与计算需求1.4 复杂度对比1.5 MARM模型的创新性 2. 方法2.1 流程2.1.1 序列生成器2.1.2 外部缓存查找2.1.3 多目标注意力机制2.1.4 发结果到缓存 **2.2 MARM与SIM**2.2.1 SIM的…...
INP指标
什么是INP(Interaction to Next Paint) 参考网站:webVital-INP文档 定义与核心目标 INP 是一项稳定的 Core Web Vitals 指标,通过统计用户访问期间所有符合条件的互动约定时间,评估网页对用户操作的总体响应能力。最…...
Flink 的状态机制
在实时流处理领域,状态管理是构建复杂业务逻辑的核心能力。Apache Flink 通过统一的状态抽象和高效的容错机制,为开发者提供了从毫秒级窗口聚合到 TB 级历史数据关联的全场景支持。本文将深入剖析 Flink 状态机制的底层原理,结合实际案例展示…...