有没有更好的方法来修改一个被多个线程不断调用的函数?

问题描述 投票:0回答:1

我想钩住一个函数,这个函数通常被多个线程调用,中间没有任何空闲时间。我想知道有什么最安全的方法来钩住这个函数,防止其他线程(不属于我自己)在我钩住函数的时候不执行代码。

我最初的想法是暂停其他线程,但这在我的情况下并不理想。我决定使用原子操作。这是我想出的一些伪代码来测试我的想法。

#include <thread>
#include <cstdio>
#include <Windows.h>

void hook()
{
    puts("Function hooked");
}

void func()
{
    puts("Actual function");
}

void __declspec(noreturn) thread()
{
    while (true)
        func(); //Hammer the function
}

int main()
{
    DWORD old;
    VirtualProtect(func, 0x5, PAGE_EXECUTE_READWRITE, &old); //change memory protections so we can write

    //create the threads and release the handle (we don't own them)
    std::thread t{thread};
    t.detach();

    std::thread s{thread};
    s.detach();

    std::thread z{thread};
    z.detach();

    //sleep 1 second to allow `threads t, s, z` to run
    Sleep(1000);

    //Hook the function
    _InterlockedExchange8(reinterpret_cast<char*>(func), 0xe9);
    const auto diff = static_cast<ULONG>(reinterpret_cast<ULONG>(hook) - reinterpret_cast<ULONG>(func)) - 5;
    _InterlockedExchange(reinterpret_cast<unsigned long*>(reinterpret_cast<PUCHAR>(func) + 1), diff);

    //Halt the current thread until program is terminated
    WaitForSingleObject(GetCurrentProcess(), INFINITE);
}

这能用,但安全吗? 还是说,它的工作只是因为调用 puts 并返回?有没有更好的方法?

谢谢,我想钩住一个通常被多个线程调用的函数,中间没有任何空闲时间。

c++ windows synchronization hook atomic
1个回答
0
投票

这取决于很多因素,有很多可能的解决方案。

  1. 能否把函数写成可重入的?也就是说,能不能把函数写成多个线程同时使用都无所谓?缺少静态变量(静态常量也可以),缺少对非重入例程的调用,就会使得它本身是非重入的。在这种情况下,不需要同步。
  2. 看起来你是在自己写函数的代码。为什么不在函数中放一个静态的mutex,并在你执行违反重入标准的代码时锁定它呢?关键部分可能是整个函数中很小的一部分,线程暂停简写。
  3. 看起来你是在为其他线程写代码。你可以共享一个全局的mutex,每个线程调用函数时都会锁定它。
  4. 如果其他线程是在单独的进程中,你应该研究一下这个函数的 进程间同步 的功能。这将允许你产生一个 系统互换对象 并将其交给所有进程使用,以允许同步访问该函数。

请注意,解决方案2、3和4会暂停线程,所以在你的情况下可能无法接受。

另外,请注意,你分离了线程,但函数是你代码的一部分。在你的代码退出后,这些线程会继续运行吗?那些分离出来的线程就会调用删除的代码。

© www.soinside.com 2019 - 2024. All rights reserved.