You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

逆向工程中旧POSIX信号代码的现代C++跨平台适配咨询

问题描述

逆向工程中遇到一段基于旧版POSIX线程的Linux核心代码,需要适配为现代C++代码并支持Windows平台。原代码逻辑如下:

while ( GameRunning() )
  {
    sigblock(512);
    for ( i = SigUsr1Counter; !SigUsr1Counter && !SigAlarmCounter; i = SigUsr1Counter )
      __sigpause(0, 0);
    if ( i > 0 )
    {
      SigUsr1Counter = 0;
      ReceiveData();
    }
    v2 = SigAlarmCounter;
    if ( SigAlarmCounter > 0 )
    {
      SigAlarmCounter = 0;
      AdvanceGame(Beat * v2);
    }
  }

原代码通过sigblock和__sigpause实现等待信号的逻辑。曾考虑过conditional_variable但不确定适用性,尝试过轮询方式但存疑:

int signalCount = 0;
while (signalCount == 0) {
   sleep(50);
}
适配思路与解决方案

核心逻辑拆解

原代码本质是阻塞等待两个事件触发(SigUsr1/SigAlarm):

  1. 挂起线程,直到任一事件计数器不为0
  2. 处理触发的事件,重置计数器后回到循环

你尝试的轮询方式存在明显问题:

  • 会占用不必要的CPU资源,即使sleep也会有无效唤醒
  • 事件响应延迟不可控(最多50ms的滞后)

std::condition_variable完全适配这个场景,它能实现无轮询的阻塞等待,支持多条件触发,且是C++标准特性,天然跨平台兼容Linux和Windows。

现代C++跨平台实现

结合std::mutex和std::condition_variable,用线程安全的原子变量替代原全局计数器:

#include <condition_variable>
#include <mutex>
#include <atomic>

// 线程安全的计数器,替代原全局变量
std::atomic<int> SigUsr1Counter{0};
std::atomic<int> SigAlarmCounter{0};
std::mutex cv_mutex;
std::condition_variable cv;

void GameLoop() {
    while (GameRunning()) {
        std::unique_lock<std::mutex> lock(cv_mutex);
        // 等待直到任一计数器不为0,自动处理虚假唤醒
        cv.wait(lock, []{ return SigUsr1Counter > 0 || SigAlarmCounter > 0; });

        // 处理SigUsr1事件,原子操作重置计数器
        int usr1_count = SigUsr1Counter.exchange(0);
        if (usr1_count > 0) {
            ReceiveData();
        }

        // 处理SigAlarm事件,原子操作重置计数器
        int alarm_count = SigAlarmCounter.exchange(0);
        if (alarm_count > 0) {
            AdvanceGame(reinterpret_cast<Beat*>(alarm_count)); // 保留原代码的Beat*参数逻辑
        }
    }
}

// 模拟原SigUsr1信号触发逻辑
void TriggerSigUsr1() {
    SigUsr1Counter++;
    cv.notify_one();
}

// 模拟原SigAlarm信号触发逻辑
void TriggerSigAlarm() {
    SigAlarmCounter++;
    cv.notify_one();
}

关键细节说明

  • 线程安全:用std::atomic存储计数器,避免多线程竞争;std::unique_lock保证等待与修改流程的互斥性
  • 无虚假唤醒:cv.wait的谓词参数确保只有当条件真满足时才退出等待
  • 跨平台兼容:所有API都是C++11及以上的标准库特性,无需依赖POSIX或Windows专属接口
  • 逻辑一致性:完全复刻原代码"等待事件→处理事件→重置计数器"的核心流程,未改变业务逻辑

备选方案(特殊场景下)

如果因项目限制无法使用标准库condition_variable,可以针对不同平台做原生实现:

Windows平台

用系统事件对象实现等待逻辑:

#include <Windows.h>

HANDLE hSigUsr1Event = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE hSigAlarmEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE events[2] = {hSigUsr1Event, hSigAlarmEvent};

void GameLoop() {
    while (GameRunning()) {
        // 等待任一事件触发
        DWORD result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
        if (result == WAIT_OBJECT_0) {
            ReceiveData();
            ResetEvent(hSigUsr1Event);
        } else if (result == WAIT_OBJECT_0 + 1) {
            int count = 1; // 若需要计数逻辑可扩展为原子变量
            AdvanceGame(reinterpret_cast<Beat*>(count));
            ResetEvent(hSigAlarmEvent);
        }
    }
}

// 触发事件
void TriggerSigUsr1() {
    SetEvent(hSigUsr1Event);
}

内容的提问来源于stack exchange,提问作者Alejandro Mujica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:54:56