【问题标题】:Restart Windows process inplace preserving process ID and handles重新启动 Windows 进程就地保留进程 ID 和句柄
【发布时间】:2017-08-10 08:10:38
【问题描述】:

我创建了一个 Windows 可执行文件,用作某些嵌入式设备的模拟器(所有业务逻辑都与原始设备上的完全相同,只有与硬件相关的东西被存根)。

此模拟需要不时重置,在“正常”用例中,它会执行以下操作:

//some global environment
...

int main(int argc, char* argv[])
{
    __debugbreak();

    //... do some stuff 

    //if( restart needed ){
        printf("before _execv");
        _execv(argv[0], argv); //"reset" simulated device
    //}

    //... do some other testing stuff
    return 0;
}

注意:上面的代码只是为了说明主要思想,在实际应用中execv调用实际上位于HW_Reset()存根中,即在原始代码中从多个位置调用。

问题是 Windows 上的 _execv 的行为与 Linux 上的 execv 不完全相同: 当我在 Visual Studio 中调试此应用程序时,_execv 不会将当前进程映像替换为“重新启动”映像。相反,它只是创建一个具有新 ID 的新进程并终止当前进程,导致它与 Visual Studio 分离,因此,为了保留所有断点,我需要一次又一次地重新附加到该新进程(单个调试会话中有数十次重新启动)。

目前我使用 __debugbreak() 作为解决方法。 其他选项是通过重新初始化全局环境并使用 setjmp/longjmp 的某种组合来重置模拟 - 但全局环境和相应的初始化程序分布在成千上万的原始文件中,并且其中大部分是静态的,因此无法手动处理此类重置(我也不允许编辑原始文件)。

所以问题是: 是否有一些 Windows API / 通用解决方法通过重置所有全局(和静态)变量来“就地”重新启动当前进程,以防万一在相同的地址空间内重新加载相同的进程映像,保留外部可观察的进程 ID、进程句柄和与 Visual Studio 调试器的连接?

【问题讨论】:

  • 不,Windows 中几乎没有任何东西

标签: c visual-studio winapi exec win32-process


【解决方案1】:

恐怕简单的答案是 Windows 上不存在这样的功能。

【讨论】:

    【解决方案2】:

    Windows 不支持您的要求。您将不得不重组 main() 代码以在循环中运行,例如:

    //some global environment
    ...
    
    int main(int argc, char* argv[])
    {
        __debugbreak();
    
        do
        {
            //... (re)initialize simulated device
            //... do some stuff
        }
        while (restart needed);
    
        //... do some other testing stuff
        return 0;
    }
    

    【讨论】:

    • 在这种情况下“(重新)初始化模拟设备”操作必须手动完成,包括(重新)初始化散布在“数千个原始文件”中的静态数据
    • @Chajnik-U:最好摆脱全局和静态,将它们包装在对象中,然后重新初始化可以简单地销毁旧对象并创建新对象。
    猜你喜欢
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    相关资源
    最近更新 更多