Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么Win32控制台应用程序启动时会出现三个意外的工作线程?_C++_Multithreading_Winapi - Fatal编程技术网

C++ 为什么Win32控制台应用程序启动时会出现三个意外的工作线程?

C++ 为什么Win32控制台应用程序启动时会出现三个意外的工作线程?,c++,multithreading,winapi,C++,Multithreading,Winapi,这是情况的截图 我用VS2010创建了Visual C++ Win32控制台应用程序。当我启动应用程序时,我发现有四个线程:一个“主线程”和三个工作线程(我没有编写任何代码) 我不知道这三个工作线程来自哪里。 我想知道这三个线程的作用 提前谢谢 Windows 10实现了一种加载DLL的新方法—多个工作线程并行加载(LdrpWorkCallback)。所有Windows 10进程现在都有几个这样的线程 在Win10之前,系统(ntdll.dll)总是在单个线程中加载dll,但从Win10开始,

这是情况的截图

<>我用VS2010创建了Visual C++ Win32控制台应用程序。当我启动应用程序时,我发现有四个线程:一个“主线程”和三个工作线程(我没有编写任何代码)

我不知道这三个工作线程来自哪里。
我想知道这三个线程的作用


提前谢谢

Windows 10实现了一种加载DLL的新方法—多个工作线程并行加载(
LdrpWorkCallback
)。所有Windows 10进程现在都有几个这样的线程

在Win10之前,系统(
ntdll.dll
)总是在单个线程中加载dll,但从Win10开始,此行为发生了变化。现在,
ntdll
中存在一个“并行加载程序”。现在可以在工作线程中执行加载任务(
NTSTATUS LdrpSnapModule(LDRP\u LOAD\u CONTEXT*LoadContext)
)。几乎每个DLL都有导入(依赖DLL),因此当加载DLL时,它的依赖DLL也会加载,并且这个过程是递归的(依赖DLL有自己的依赖项)

函数
void LdrpMapAndSnapDependency(LDRP\u LOAD\u CONTEXT*LoadContext)
通过调用
LdrpLoadDependentModule()
(内部调用
LdrpMapAndSnapDependency())遍历当前加载的DLL导入表并加载其直接(第一级)依赖的DLL
用于新加载的DLL-因此此过程是递归的)。最后,
ldrpmapandsnappendency()
需要调用
NTSTATUS LdrpSnapModule(LDRP\u LOAD\u CONTEXT*LoadContext)
将导入绑定到已加载的DLL
LdrpSnapModule()
在顶级DLL加载过程中对许多DLL执行,并且该过程对每个DLL都是独立的,因此这是一个并行化的好地方
LdrpSnapModule()
在大多数情况下,不会加载新的DLL,而只会将导入绑定到已加载DLL的导出。但是,如果导入解析为转发导出(这种情况很少发生),则会加载新的转发DLL


目前的一些实施细节:

  • 首先,让我们看看
    struct\u RTL\u USER\u PROCESS\u参数
    new字段-
    ULONG LoaderThreads
    。此
    LoaderThreads
    (如果设置为非零)在新进程中启用或禁用“并行加载程序”。当我们创建一个新流程时,第9个参数是
    PRTL\u用户\u流程\u参数ProcessParameters
    。但是如果我们使用
    CreateProcess[Internal]W()
    ,我们不能直接传递
    PRTL\u USER\u PROCESS\u参数
    ,只能传递
    STARTUPINFO
    RTL\u USER\u PROCESS\u PARAMETERS
    是从
    STARTUPINFO
    部分初始化的,但是我们不控制
    ULONG LoaderThreads
    ,它将始终为零(如果我们不调用
    ZwCreateUserProcess()
    或设置此例程的挂钩)

  • 在新的进程初始化阶段,调用了
    LdrpInitializeExecutionOptions()
    (从
    LdrpInitializeProcess()
    )。此例程检查
    HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\
    中的几个值(如果
    子项存在-通常不存在),包括
    MaxLoaderThreads
    REG\u DWORD
    )-如果存在
    MaxLoaderThreads
    ,则其值将覆盖
    RTL\u用户\u进程\u参数。LoaderThreads

  • 调用了LdrpCreateLoaderEvents()。此例程必须创建2个全局事件:
    HANDLE LdrpWorkCompleteEvent、LdrpLoadCompleteEvent,用于同步

    NTSTATUS LdrpCreateLoaderEvents()
    {
    NTSTATUS status=ZwCreateEvent(&LdrpWorkCompleteEvent,EVENT\u ALL\u ACCESS,0,SynchronizationEvent,TRUE);
    如果(0低!=pps->低| ppv->高!=pps->高)
    {
    if(LdrpDebugFlags&5)
    {
    DbgPrint(!!!检测到迂回,禁用并行加载\n”);
    LdrpDetourExist=TRUE;
    返回;
    }
    }
    }而(pps++,ppv++,--n);
    布尔动态政治;
    如果(0个加载线程)

    NTSTATUS LdrpEnableParallelLoading(ULONG LoaderThreads)
    {
    ldrpdetectedtour();
    if(LoaderThreads)
    {
    LoaderThreads=min(LoaderThreads,16);//不允许超过16个线程
    if(LoaderThreads Size=sizeof(TP\u CALLBACK\u ENVIRON);
    CallbackEnviron->Pool=LdrpThreadPool;
    CallbackEnviron->Version=3;
    状态=TpAllocWork(&LdrpMapAndSnapWork,LdrpWorkCallback,0,&CallbackEnviron);//CreateThreadpoolWork
    }
    返回状态;
    }
    
    创建一个特殊的加载程序线程池-
    LdrpThreadPool
    ,其中
    LoaderThreads-1
    最大线程数。空闲超时设置为30秒(之后线程退出),并分配
    PTP_WORK ldrpmap和snapwork
    ,然后在
    void LdrpQueueWork(LDRP_LOAD_CONTEXT*LoadContext)
    中使用

  • 并行加载程序使用的全局变量:

    处理LdrpWorkCompleteEvent,LdrpLoadCompleteEvent;
    临界段LdrpWorkQueueLock;
    列表\u条目LdrpWorkQueue={&LdrpWorkQueue,&LdrpWorkQueue};
    乌龙LdrpWorkInProgress;
    布尔LdrpDetourExist;
    PTP_池LDRPThread池;
    PTP_工作LDRPMAP和Snapwork;
    枚举排出任务{
    WaitLoadComplete,WaitWorkComplete
    };
    结构LDRP\u加载\u上下文
    {
    UNICODE_基于字符串的名称;
    pvoidsomestruct;
    ULONG Flags;//一些未知的标志
    NTSTATUS*pstatus;//加载的最终状态
    _LDR_数据_表_ENTRY*ParentEntry;//的'parent'加载dll
    _LDR\u DATA\u TABLE\u ENTRY*ENTRY;//this==ENTRY->LoadContext
    列表\u条目WorkQueueListEntry;
    _LDR_数据_表_条目*替换项;
    _LDR_数据_表_项**pvImports;//与图像_导入_描述符piid中的ordef相同
    ULONG ImportDllCount;//pvImports的计数