38. 【C语言】时间、信号与程序控制

2021-BUPT计组课设硬布线控制器 目录 题目分析 4 实验目的 4 实验任务 4 任务分析 4 实验环境与设备 5 团队分工 6 原理详解 6 硬连线控制器 VS 微程序控制器 6 硬连线控制器的基本原理 6 模型计算机时序信号 7 TEC-8 模型计算机组成模块 & 数据通路 7 执行一条机器指令的节拍电位数 8 流水 VS 非流水 9 由非流水变为流水,指令的变化 10 设计详解 11 指令系统 11 机器指令周期流程图设计 12 EPM7128 器件的引脚 14 本实验控制信号详解 16 流水设计 18 ST0的设计 19 阅读详情

一个健壮的程序,不仅要能算得对,还要能应对时间与外部世界的干预:知道现在几点、计算一段代码跑了多久;当用户按下 Ctrl+C 时优雅退出而不是直接暴毙;在极端错误时从嵌套的函数深处直接跳回安全地带。

今天这三样本领,对应的就是 C 语言中的时间处理、信号处理和非局部跳转。它们是程序控制领域的“软技能”——不直接产出算法结果,却决定了程序的鲁棒性和用户体验。


一、时间的两种面貌:日历时间与程序计时

C 语言处理时间分为两类需求:

  • 日历时间:现在几点?今天的日期?格式化输出时间戳。
  • 程序计时:这段代码跑了多久?精确到微秒或纳秒。

1. 日历时间:time() 与 ctime()

最基础的时间函数是 time(),返回自 1970-01-01 00:00:00 UTC 至今的秒数(称为 Unix 时间戳)。定义在 <time.h>。

#include <stdio.h>
#include <time.h>

int main(void) {
    time_t now = time(NULL);   // 获取当前时间戳
    if (now == (time_t)-1) {
        perror("time 失败");
        return 1;
    }
    printf("时间戳: %ld\n", (long)now);

    // 转换为可读字符串
    char *str = ctime(&now);
    printf("当前时间: %s", str);  // 自带换行符

    return 0;
}

输出类似:

时间戳: 1753152000
当前时间: Mon Jul 21 14:30:00 2025

ctime 直接返回一个静态分配的字符串(不需要手动 free,但下次调用会覆盖)。time_t 通常是 long 的别名。

2. 分解时间:localtime() 与 strftime()

ctime 格式固定,不够灵活。需要自定义格式时,先用 localtime 把 time_t 分解成 struct tm,再用 strftime 格式化。

#include <stdio.h>
#include <time.h>

int main(void) {
    time_t now = time(NULL);
    struct tm *local = localtime(&now);

    printf("年: %d\n", local->tm_year + 1900);  // 从 1900 起算
    printf("月: %d\n", local->tm_mon + 1);      // 0~11
    printf("日: %d\n", local->tm_mday);
    printf("星期: %d (0=周日)\n", local->tm_wday);
    printf("时: %d\n", local->tm_hour);
    printf("分: %d\n", local->tm_min);
    printf("秒: %d\n", local->tm_sec);

    // 自定义格式化
    char buf[100];
    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", local);
    printf("格式化: %s\n", buf);  // 2025-07-21 14:30:00

    return 0;
}

strftime 的格式符非常丰富,%Y 四位年份,%m 两位月份,%d 两位日期,%H 24小时制小时,%M 分,%S 秒。更多格式符请查手册。

注意:localtime 返回指向静态内存的指针,非线程安全。在多线程程序中使用 localtime_r(POSIX)替代。

3. 程序计时:clock() 与高精度替代

clock() 我们在第三十四篇用过,它测量的是 CPU 时间,精度通常为毫秒级。适合对比算法效率。

如果需要更高精度(微秒甚至纳秒),POSIX 提供 gettimeofday 或 clock_gettime:

#include <stdio.h>
#include <time.h>    // clock_gettime

int main(void) {
    struct timespec start, end;
    clock_gettime(CLOCK_MONOTONIC, &start);

    // 模拟耗时操作
    for (volatile long i = 0; i < 100000000; i++) { }

    clock_gettime(CLOCK_MONOTONIC, &end);

    double elapsed = (end.tv_sec - start.tv_sec) 
                   + (end.tv_nsec - start.tv_nsec) / 1e9;
    printf("耗时: %.6f 秒\n", elapsed);
    return 0;
}

CLOCK_MONOTONIC 是单调时钟,不受系统时间调整影响,适合测量时间间隔。CLOCK_REALTIME 是系统实时时钟,可能被用户或 NTP 调整。


二、信号处理:与外部世界对话

信号是操作系统向进程发送的异步通知。比如你按 Ctrl+C,内核向当前前台进程发送 SIGINT 信号;程序访问了非法内存,内核发送 SIGSEGV。程序可以注册信号处理函数来响应这些信号,而不是让默认行为(通常是终止程序)直接发生。

1. 常见信号

信号值默认行为触发场景
SIGINT2终止键盘 Ctrl+C
SIGTERM15终止kill 命令默认发送
SIGKILL9终止(无法捕获或忽略)kill -9
SIGSTOP19暂停(无法捕获或忽略)Ctrl+Z
SIGSEGV11终止并 core dump非法内存访问
SIGABRT6终止并 core dumpabort() 调用
SIGALRM14终止alarm() 定时器到期
SIGUSR110终止用户自定义
SIGUSR212终止用户自定义

信号定义在 <signal.h>。

2. signal():注册信号处理函数

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
  • signum:信号编号。
  • handler:信号处理函数(接收信号编号),或 SIG_IGN(忽略),或 SIG_DFL(恢复默认)。
  • 返回值:之前的处理函数指针,出错返回 SIG_ERR。

示例:优雅地响应 Ctrl+C

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// 全局标志(注意:必须是 volatile sig_atomic_t 类型!)
volatile sig_atomic_t keep_running = 1;

void handle_sigint(int sig) {
    const char msg[] = "\n收到 SIGINT,正在优雅退出...\n";
    write(STDERR_FILENO, msg, sizeof(msg) - 1);
    keep_running = 0;
}

int main(void) {
    // 注册 SIGINT 的处理函数
    if (signal(SIGINT, handle_sigint) == SIG_ERR) {
        perror("signal 注册失败");
        return 1;
    }

    printf("程序运行中,按 Ctrl+C 退出\n");
    while (keep_running) {
        printf("工作中...\n");
        sleep(1);
    }

    printf("程序已退出。\n");
    return 0;
}

运行后按 Ctrl+C,程序不会直接终止,而是打印提示并将 keep_running 设为 0,循环自然结束。

关键细节:

  • 信号处理函数必须使用 volatile sig_atomic_t 类型的全局变量与主程序通信。这个类型保证读写是原子性的(不会被信号中断打断一半),volatile 防止编译器缓存其值。
  • 信号处理函数中尽量只做简单操作(设置标志)。不要在信号处理函数中调用 printf(它不是“异步信号安全”的),虽然很多实现中它可以工作,但标准不保证。若要安全输出,使用 write()。

3. 实用信号场景

定时器:用 alarm(seconds) 或 setitimer 设置定时,到期发送 SIGALRM。可用于实现超时机制。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

volatile sig_atomic_t timeout = 0;

void handle_alarm(int sig) {
    timeout = 1;
}

int main(void) {
    signal(SIGALRM, handle_alarm);
    printf("5 秒倒计时...\n");
    alarm(5);  // 5 秒后发送 SIGALRM

    while (!timeout) {
        // 模拟工作
        usleep(100000);
    }
    printf("时间到!\n");
    return 0;
}

忽略信号:

signal(SIGPIPE, SIG_IGN);  // 忽略管道破裂信号

服务器程序中经常忽略 SIGPIPE,因为向关闭的 socket 写数据会触发该信号,而程序想自己处理写入错误而不是被信号杀死。


三、setjmp 与 longjmp:跨越函数栈的跳转

C 语言没有异常处理机制(不像 C++ 的 try/catch)。但有时你需要在深层函数中遇到不可恢复的错误时,直接跳回最外层,而不是一层层 return 错误码。setjmp/longjmp 就是干这个的。

1. 基本原理

setjmp 在当前位置保存“执行环境”(寄存器、栈指针、程序计数器等),返回 0。之后任何地方调用 longjmp,程序状态会回到 setjmp 那一刻,而且 setjmp 会返回非 0 值(longjmp 的第二个参数),从而区分“首次执行”还是“跳转回来”。

#include <stdio.h>
#include <setjmp.h>

jmp_buf env;

void inner(void) {
    printf("inner: 发现错误,准备跳回!\n");
    longjmp(env, 1);   // 跳回 setjmp,并使它返回 1
    printf("这行不会执行\n");
}

int main(void) {
    if (setjmp(env) == 0) {
        // 首次执行
        printf("首次进入,调用 inner...\n");
        inner();
        printf("这行也不会执行\n");
    } else {
        // longjmp 跳回这里
        printf("从 inner 跳回,执行清理工作\n");
    }
    return 0;
}

输出:

首次进入,调用 inner...
inner: 发现错误,准备跳回!
从 inner 跳回,执行清理工作

2. 典型用途:深层错误恢复

想象一个解析器,在递归下降的深处遇到语法错误。一种处理方式是每层函数都返回错误码,逐层向上传递。用 setjmp/longjmp 则可以“一步到位”:

#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>

jmp_buf parser_env;

void parse_expression(void) {
    // 模拟深层错误
    printf("解析表达式... 错误!\n");
    longjmp(parser_env, 1);
}

void parse_statement(void) {
    parse_expression();
}

void parse_program(void) {
    parse_statement();
}

int main(void) {
    if (setjmp(parser_env) == 0) {
        parse_program();
    } else {
        printf("解析失败,已恢复。请检查输入。\n");
    }
    return 0;
}

3. 陷阱与限制

setjmp/longjmp 功能强大,但有几条必须遵守的规则:

限制 1:不能跳回已结束的函数

void bad(void) {
    jmp_buf env;
    if (setjmp(env) == 0) {
        return;   // bad 返回后,env 所在的栈帧已失效
    }
}
// 其他地方 longjmp(env, 1) → 未定义行为!

jmp_buf 必须定义在调用 setjmp 后仍存活的函数中(通常是 main 或顶层调用者)。

限制 2:局部变量的值不确定

longjmp 跳回后,setjmp 所在函数中的非 volatile 局部变量,如果在 setjmp 和 longjmp 之间被修改过,其值是不确定的(C 标准这么说)。如果需要在跳回后读取这些变量,用 volatile 修饰。

#include <stdio.h>
#include <setjmp.h>

jmp_buf env;

int main(void) {
    int x = 1;
    volatile int y = 1;   // volatile 保证值正确

    if (setjmp(env) == 0) {
        x = 100;
        y = 100;
        longjmp(env, 1);
    } else {
        printf("x = %d (不确定), y = %d (确定是 100)\n", x, y);
    }
    return 0;
}

限制 3:资源泄漏

longjmp 会跳过局部变量的析构……等等,C 没有析构函数。但它会跳过 free() 调用!如果中间有 malloc 但没有在跳回后释放,就会内存泄漏。

void *buffer = malloc(1024);
// ... 处理 ...
longjmp(env, 1);   // 跳过 free(buffer)!
free(buffer);

所以在 setjmp 的“恢复分支”中,必须能清理之前分配的资源(通常通过全局指针记录)。


四、实战:带超时的网络连接模拟

把时间、信号、跳转结合起来,模拟一个带超时的操作:

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <unistd.h>

jmp_buf timeout_env;

void handle_alarm(int sig) {
    longjmp(timeout_env, 1);  // 超时直接跳回
}

int main(void) {
    signal(SIGALRM, handle_alarm);

    printf("尝试连接(3 秒超时)...\n");

    if (setjmp(timeout_env) == 0) {
        alarm(3);  // 设置 3 秒超时
        // 模拟耗时操作(如果超过 3 秒,alarm 触发跳转)
        sleep(5);  // 模拟超时情况
        alarm(0);  // 取消闹钟
        printf("连接成功!\n");
    } else {
        printf("操作超时!\n");
    }

    return 0;
}

运行结果:sleep(5) 未完成就被 SIGALRM 中断,longjmp 跳回打印“操作超时”。

如果 sleep(2)(小于 3 秒),则会先取消闹钟,输出“连接成功”。

Windows环境下:

#include <stdio.h>
#include <windows.h>

// 模拟耗时操作的线程函数
DWORD WINAPI connect_thread(LPVOID arg) {
    Sleep(5000);  // 模拟 5 秒连接耗时
    return 42;    // 返回结果
}

int main(void) {
    printf("尝试连接(3 秒超时)...\n");

    HANDLE hThread = CreateThread(NULL, 0, connect_thread, NULL, 0, NULL);
    if (hThread == NULL) {
        fprintf(stderr, "创建线程失败\n");
        return 1;
    }

    // 等待线程完成,最多等 3 秒
    DWORD result = WaitForSingleObject(hThread, 3000);

    if (result == WAIT_TIMEOUT) {
        printf("操作超时!\n");
        TerminateThread(hThread, 0);  // 强制终止
    } else if (result == WAIT_OBJECT_0) {
        DWORD exitCode;
        GetExitCodeThread(hThread, &exitCode);
        printf("连接成功!线程返回值: %lu\n", exitCode);
    } else {
        printf("等待失败\n");
    }

    CloseHandle(hThread);
    return 0;
}

五、小结

今天你学会了三项“程序控制”的高级技能:

  • 时间处理:time() 获取时间戳,localtime + strftime 灵活格式化;clock_gettime 做高精度计时。
  • 信号处理:signal 捕获 SIGINT、SIGALRM 等,用 volatile sig_atomic_t 标志安全退出,alarm 做简单超时。
  • 非局部跳转:setjmp/longjmp 在深层错误时一步跳回,但注意变量 volatile 和资源清理问题。

这些技术让程序从“按部就班执行”升级为“能感知时间、能响应外部信号、能从错误中恢复”的健壮系统。信号处理在守护进程和服务器中至关重要;setjmp/longjmp 是 C 语言实现简易异常处理或协程的核心机制。

至此,系统编程的各个模块——文件 I/O、库制作、多线程、信号、时间——已经覆盖完毕。下一篇,我们将迎来一个综合实战:打造一个迷你 HTTP 服务器。把前面学到的 socket 原理(通过系统调用铺垫)、多线程、文件 I/O、字符串处理、信号处理全部串联起来,写出一个真正能用的网络服务。这是对整个 C 语言知识体系的一次大阅兵。


课后小练习

  1. 写一个程序,获取当前时间并以“YYYY-MM-DD HH:MM:SS”格式输出。再计算距离 2030 年 1 月 1 日还有多少秒,并输出倒计时。
  2. 实现一个“安全重启”程序:主循环执行某些工作,捕获 SIGHUP 信号(kill -1 发送)后重新加载配置(打印一条模拟消息即可),捕获 SIGTERM 后优雅退出。
  3. 用 setjmp/longjmp 实现一个简易的“重试”机制:定义一个宏 TRY 和 CATCH,让用户可以在操作失败时跳回恢复点。
  4. (小挑战)结合 SIGALRM 和 setjmp/longjmp,实现一个通用的 timeout_execute 函数:传入一个函数指针和超时秒数,在该时间内执行函数;若超时则返回错误码。

我们下期见!

💡获取本系列示例代码请访问 GitCode 仓库。

DSP56800数字信号控制器:融合DSP算力与MCU控制的高性能嵌入式架构解析 在嵌入式系统开发中,数字信号处理器和微控制器常面临算力与控制能力的权衡。数字信号控制器通过哈佛架构、独立程序与数据总线,实现了指令与数据的并行存取,突破了冯·诺依曼瓶颈。其技术价值在于将DSP的高效乘加运算能力与MCU的丰富外设深度集成,显著提升了实时信号处理效率。这种架构特别适用于电机控制、工业自动化等对实时性要求严苛的场景。本文以飞思卡尔DSP56800系列为例,深入剖析其如何通过并行执行引擎、集成存储和面向控制的外设,为复杂算法如无感FOC和矢量控制提供硬件支持,实现高性能嵌入式控制系统的简化设计。 阅读详情

相关推荐

Portapack应用开发教程(七)nrf24l01解调

前段时间我在做低功耗蓝牙的时候看到了这个网页 https://wiki.bitcraze.io/misc:hacks:hackrf 但是我当时没有成功解调nrf24l01,反而成功搞定蓝牙了。 后来我用了我自己新买的小四轴也没解调成功,所以我打算老老实实地重现那个网页上的步骤。 正好我以前买过crazyflie的产品(小四轴和crazyradio模块),我就找出了这个crazyradio模...

老邵的开源世界 4077

【C语言初级课程详解】第38课时-C语言标准库

以下是 C 标准库头文件及其功能简介的详细列表:C 语言是一种通用的、面向过程式的计算机程序设计语言。1972 年,为了移植与开发 UNIX 操作系统,丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言。C 语言是一种广泛使用的计算机语言,它与 Java 编程语言一样普及,二者在现代软件程序员之间都得到广泛使用。C 标准库(C Standard Library)包含了一组头文件,这些头文件提供了许多函数和宏,用于处理输入输出、字符串操作、数学计算、内存管理等常见编程任务。。

xzs51job的专栏 809

汇编期末复习

第一章、 概述1、 什么是时钟周期、总线周期和指令周期?为什么要了解CPU的时序? 时钟周期是CPU工作的时间基准,由计算机主频决定;  总线周期是CPU完成一次访问存储器或IO端口操作所需要的时间。  执行一条指令所需要的时间成为指令周期。一条指令的执行需要若干个总线周期才能完成。而一个总线周期又由若干个时钟周期组成。第二章、 IA-32处理器1、 IA-32、I

晨阳再升的博客 2073

c语言编程基础

变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。type表示变量的数据类型,可以是整型、浮点型、字符型、指针等,也可以是用户自定义的对象。可以由一个或多个变量的名称组成,多个变量之间用逗号,分隔,变量由字母、数字和下划线组成,且以字母或下划线开头。int age;char grade;int *ptr;使用 const 关键字。使用 #define 预处理器。在 C 语言中,函数由一个函数头和一个函数主体组成。返回类型:一个函数可以返回一个值。是函数返回的值的数据类型。

Beforthing的博客 242

光码保险箱:基于红外通信与嵌入式系统的非接触式物理安全方案

嵌入式系统与物联网技术正不断革新物理安全领域,其中非接触式认证因其便捷性与隐蔽性成为重要发展方向。其核心原理在于利用特定信号媒介(如光、射频)进行身份验证,替代传统的机械或生物识别方式。在技术实现上,红外通信协议(如NEC协议)因其抗干扰性强、硬件成本低,常被用于构建可靠的光信号传输链路。结合微控制器(如ESP32)进行信号解码与逻辑控制,可构建高安全性的认证系统。这种技术方案在需要物理隔绝、电磁静默或高隐蔽性的场景(如特种设备存取、隐私物品保管)中具有独特价值。本文以光码保险箱为例,深入解析了如何利用红外

weixin_33859231的博客 498

西门子S7-200 SMART PLC基本指令全解析:从能流原理到实战编程框架

在工业自动化领域,可编程逻辑控制器(PLC)是实现设备控制的核心。其编程基础在于处理开关量信号的逻辑运算,核心原理是“能流”概念——一种虚拟的电流,在梯形图中从左至右流动,经过触点、线圈等指令构成的路径,决定输出状态。理解这一原理是掌握PLC编程的关键技术价值,它使得工程师能够将复杂的现场物理逻辑转化为稳定可靠的程序。在实际应用场景中,从简单的电机启停、自锁电路,到复杂的流水线控制、顺序流程,都离不开对基本指令的灵活运用。本文聚焦西门子S7-200 SMART PLC,深入剖析其位逻辑、定时器、计数器等基本

weixin_34295316的博客 361

Awesome C 完整导览:纯 C 开源生态资源清单的定位、目录结构与实战选型指南

本篇技术指南以开源仓库 [awesome-c](https://link.gitcode.com/i/3b9c01fec41dd6cd5d799fe0911e32f4) 的 README 清单为核心,系统讲解这份"纯 C 精选资源清单"的定位与收录准则、目录结构与条目格式,并逐分类完整梳理 AI、构建系统、编译器、压缩、并发、加密、数据库、数据结构、调试、游戏、图形、GUI、网络、数值计算、序列化

gitblog_00342的博客 372

【信息科学与工程学】【运营科学】第二篇 C4信息与通信网络运营 (C4) ——数据中心网络运营04

典型值:λ1​∈[−0.02,−0.01], λ2​∈[−0.01,0], η1​,η3​∈[0.1,0.3], η2​,η4​∈[0.05,0.15]参数:δ1​∈[−0.8,−0.3], δ2​∈[−0.5,−0.2], δ3​∈[−0.4,−0.1], δ4​∈[−0.6,−0.2]参数:φ1​∈[0.1,0.3], φ2​∈[−0.2,−0.05], φ3​∈[−0.1,0.1], φ4​∈[−0.3,−0.1]参数:α∈[0.3,0.6], β∈[0.2,0.4], γ∈[0.01,0.03]

weixin_49199313的博客 1203

哈理工自动化C语言考试,自动化考试试题(含答案).doc

自动化考试试题(含答案)第一类:填空题一.填空题1.自动化控制系统按被控量的时间特性分为(连续量)和(离散量)。2.PLC 全称为( 可编程序逻辑控制器 ),DCS全称为( 集散控制系统 )。3.输入输出单元是( PLC )与工业过程控制现场之间的连接部件。4.PLC的工作方式是( 周期扫描方式 )。5. 冗余设计可采用( 热备份 )或( 冷备份 )。6.MPI 接口一般的默认传输速率( 187....

weixin_39541844的博客 438

【信息科学与工程学】【物理/化学科学和工程技术】知识体系081 磁学02

由 τ = 1/f_0 * exp(E_b/(k_B T_B)), 解得 T_B = E_b / (k_B ln(f_0 τ)) = 5e-21 / (1.38e-23 * ln(1e9 * 3600)) ≈ 363 K / (ln(3.6e12)) ≈ 363 K / 28.8 ≈ 580 K (307°C)。若 N_s=100, A=1e-6 m², l=0.01 m, 则 k ≈ 8 * 1e4 * 100 * 1e-6 * 4πe-7 * 1e5/0.01 ≈ 10 V/T。即 10 μV/nT。

weixin_49199313的博客 281

基于51单片机与Proteus的心率血氧检测系统仿真设计与实现

在嵌入式系统与生物医学工程领域,信号采集与处理是连接物理世界与数字系统的核心技术。其基本原理是通过传感器将生理信号(如光、电、压力)转换为模拟电信号,再经模数转换(ADC)变为数字序列,供微控制器进行算法处理。这项技术的核心价值在于能够非侵入、实时地监测人体关键生命体征,对于健康监护、疾病预警具有重要意义。典型的应用场景包括便携式健康设备、穿戴式监测装置以及临床辅助诊断系统。本文聚焦于利用经典的51单片机平台和Proteus仿真软件,构建一个指夹式光电心率血氧检测系统的数字核心仿真模型。该模型深入演示了如何

weixin_34393428的博客 413

基于单片机的全自动洗衣机控制器的设计与实现

摘要:本文设计了一种基于STC89C52单片机的全自动洗衣机控制器,通过传感器实时检测衣物重量、水位和温度,自动完成洗涤全流程。系统采用模块化设计,包含核心控制、传感检测、执行驱动等模块,实现精准水位匹配(误差±1cm)和5种智能洗涤程序。测试表明,该系统较传统洗衣机节水28%、节能22%,洗涤效率提升37.5%,成本仅85元,具有显著实用价值和推广前景。

2401_86331863的博客 1010

AD9026芯片开发实战指南:从硬件配置到射频校准

本文为AD9026芯片开发实战指南,详细解析了从硬件设计、电源时钟配置、SPI初始化到多芯片同步与JESD204高速链路建立的完整流程。重点探讨了射频校准技术,包括初始化校准与跟踪校准,以保障5G、MIMO等现代通信系统所需的射频性能。旨在帮助开发者系统掌握这颗高性能射频收发器的应用,规避常见设计陷阱。

tomato的博客 851

Nios-II入门实践

NIos入门实践

qq_52548731的博客 474

从CCD数据上报看wxHOOK的封号风险与规避

本文深入分析了微信CCD数据上报机制对wxHOOK的检测逻辑与封号风险,揭示了调试器路径暴露、非白名单DLL加载和内存校验失败等关键风险点。通过实战案例和规避方案,帮助开发者理解如何安全使用wxHOOK技术,避免封号风险,包括内存镜像欺骗、内核级隐蔽和硬件辅助方案等高级技巧。

weixin_27875131的博客 625

帆软js--获取控件和单元格

参数面板: 获取面板控件 ,name为控件名称:_g().parameterEl.getWidgetByName("name") 取值:_g().parameterEl.getWidgetByName("tt3").getValue()2323 赋值:_g().parameterEl.getWidgetByName("tt2").setValue("987") 调用对应的事件比...

江湖行骗老中医 7197

基于三菱FX系列PLC的花式音乐喷泉控制系统

本文研究了基于PLC控制的花式音乐喷泉系统设计。主要内容包括:1)概述了课题背景与意义,指出喷泉可改善环境质量;2)设计了三种喷水花样系统,通过PLC编程实现喷水高度、灯光效果的可控变化;3)完成了硬件系统设计,选用三菱FX系列PLC、变频器及接近传感器等设备;4)采用梯形图编程语言,利用SWOPC-FXGP/WIN-C软件实现控制程序设计。该系统具有经济实用、运行稳定、控制灵活等特点,提升了喷泉的艺术表现力。

毕业作品网站 4441

大学物理第二章 质点动力学详解

大学物理第二章 质点动力学概念详解

weixin_63026364的博客 1万+

可用软硬件技术来检测与消除计算机病毒,重庆计算机一模级拟试题.doc

重庆计算机一模级拟试题一( × )1.计算机被称为电脑,它完全可以代替人进行工作。( √)2.如果将计算机系统视为“硬件”,用户学习计算机的各种操作视为“软件”,那么,要使计算机发挥作用,二者缺一不可。( √)3.计算机与其它计算工具的本质区别是它能够存储和控制程序。( √)4.任何文件和数据只有读入计算机内存后才能被CPU使用。( √)5.机器语言是用计算机的二进制指令代码编写的程序设计语言。(...

weixin_29706315的博客 695

如何实现chrome谷歌浏览器多开(独立环境 独立cookie)

由于各种各样的原因,你可能需要在一个电脑登录某个平台,比如一个电脑登录3个公众号,或者3个知乎等等。最简单的方案是,直接安装3个不同的浏览器,比如一个谷歌浏览器,一个火狐浏览器,一个 Edge 浏览器。这个方案也能解决,但如果想多开10个呢?安装10个不同的浏览器也能解决,但感觉这样比较复杂,另外一方面安装太多的应用,会导致电脑卡顿。这里给大家介绍,我在 Win 和 Mac 系统下的躲开解决方案。Win 系统下的解决方案最为简单,原理就是给不同的谷歌浏览器,指向不同的用户存储路径即可。

lzqial1987的专栏 1万+

深交所 vs 上交所:Level-2实时数据推送规则详解与策略适配指南

本文深度解析沪深Level-2实时数据推送规则的关键差异,包括逐笔成交、逐笔委托和10档行情接口的处理逻辑。针对高频交易策略,详细对比上交所与深交所在数据推送机制、时间戳处理及委托队列解析等方面的差异,并提供具体的策略适配方案和性能优化建议,帮助量化投资者提升跨市场交易稳定性。

weixin_27310417的博客 1162

WT588F02-8S-C语音芯片在电动车仪表中的三语播报与硬件仲裁设计

语音播报系统是智能电动车人机交互的关键环节,其本质是嵌入式实时音频处理与多源事件调度的融合技术。核心在于语音芯片如何实现低延迟解码、抗干扰存储访问及多优先级信号仲裁——这直接决定告警响应是否及时、语音是否清晰可懂、多语言切换是否无缝。以WT588F02-8S-C为例,其片内SPI NOR Flash架构支持XIP随机读取,配合硬件状态机实现速度/电量/故障三路信号的毫秒级优先级调度,同时通过REG_LANG寄存器直连Flash分区,达成微秒级三语切换。该方案显著提升车载语音系统的可靠性与安全性,广泛适用于B

weixin_34095889的博客 256

Qt视频播放器项目(打开文件,视频的播放与停止,进度条与视频进度绑定,调整音量,设置按钮图标,将槽函数与按钮绑定等功能)完整代码地址在末尾

【代码】Qt视频播放器项目。

分享计算机视觉,C++,网络摄像头研发,音视频开发,嵌入式等知识。 754
上一篇: 37. 【C语言】并发世界的钥匙:线程编程初步
下一篇: 39. 【C语言】经典 C 项目实战:迷你 HTTP 服务器
gugucoding
博客等级 码龄140天 7粉丝 102原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值