我正在阅读Windows Internals (7th Edition),他们在第1章:
进程
[...]Windows进程包括以下内容:
- [...]
*至少有一个执行线程尽管“空”进程是可能的,但它(大多数情况下)没有用。
在这个上下文中,“大多数”是什么意思?没有线程的进程能做什么?这有什么用?
编辑:还有,在a 2015 talk中,Mark Russinovich说一个进程“至少有一个线程”(19:12)。这是一个概括吗?Disclaimer: I work for Microsoft.
1条答案
按热度按时间nlejzf6q1#
我想答案已经在评论中出来了。似乎至少有两种场景,无线程进程会很有用。
场景1:捕获进程快照
正如RbMm所评论的,可以使用
PSS_CAPTURE_VA_CLONE
选项调用PssCaptureSnapshot
来创建一个无线程(或“空”)进程(使用ZwCreateProcessEx
,大概是duplicate the target process's memory in kernel mode)。这里的主要用途是调试,如果开发人员希望在某个时间点检查进程的内存。
值得注意的是,Eryk Sun指出,空进程对于检查句柄不是必需的(即使空进程同时拥有自己的内存空间 * 和 * 句柄),因为已经有一种方法可以检查进程的句柄,而无需创建新进程或复制内存。
场景2:安全地派生具有特定继承句柄的进程
Raymond Chen解释了无线程进程的另一个用途:安全地创建具有继承句柄的新的“真实的”进程。
当线程想要创建一个新进程(
CreateProcess
)时,有几种方法可以将句柄传递给新进程:CreateProcess
设置为bInheritHandles = true
。PROC_THREAD_ATTRIBUTE_LIST
,并将该列表传递给CreateProcess
调用。然而,它们提供了相互冲突的保证,当调用者希望同时创建两个 * 具有不同句柄 * 的线程时,可能会导致问题。
为了继承一个句柄,你不仅要把它放在
PROC_THREAD_ATTRIBUTE_LIST
中,而且你还必须使这个句柄是可继承的。这意味着如果另一个线程没有使用PROC_THREAD_ATTRIBUTE_LIST
技巧,而是直接使用bInheritHandles = true
执行CreateProcess
,它会无意中继承你的句柄。您可以使用无线程进程来缓解这种情况。
1.创建无线程进程。
DuplicateHandle
要捕获到这个新的无线程进程中的所有句柄。CreateProcess
使用PROC_THREAD_ATTRIBUTE_LIST
创建新的真实的的分叉进程,但将此进程的名义父进程设置为无线程进程(使用PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
)。您现在可以并发地执行
CreateProcess
,而不用担心其他调用方,并且您现在可以关闭重复的句柄和空进程。