在Windows上,控制台窗口所有权如何工作?

在Windows上,控制台窗口所有权如何工作?,windows,winapi,console,console-application,Windows,Winapi,Console,Console Application,从另一个控制台应用程序启动控制台应用程序时,控制台所有权如何工作 我认为有四种可能性: 第二个应用程序在其生命周期内从第一个应用程序继承控制台,控制台在退出时返回到原始所有者 每个应用程序都有自己的控制台。Windows然后以某种方式将两者的内容合并到用户可见的“控制台”中 第二个应用程序获得属于第一个应用程序的控制台句柄 控制台被放置在共享内存中,两个应用程序具有相同的“所有权” 很可能我遗漏了什么,这四个选项中没有一个能充分描述Windows对其控制台的功能 如果答案接近选项4。我的后续问题

从另一个控制台应用程序启动控制台应用程序时,控制台所有权如何工作

我认为有四种可能性:

  • 第二个应用程序在其生命周期内从第一个应用程序继承控制台,控制台在退出时返回到原始所有者
  • 每个应用程序都有自己的控制台。Windows然后以某种方式将两者的内容合并到用户可见的“控制台”中
  • 第二个应用程序获得属于第一个应用程序的控制台句柄
  • 控制台被放置在共享内存中,两个应用程序具有相同的“所有权”
  • 很可能我遗漏了什么,这四个选项中没有一个能充分描述Windows对其控制台的功能

    如果答案接近选项4。我的后续问题是,这两个进程中的哪一个负责管理窗口?(在需要刷新/重画屏幕时处理图形更新等)


    一个具体的例子:runcmd。然后,使用CMD运行[控制台应用程序]。[控制台应用程序]将写入CMD使用的控制台窗口。

    每个应用程序将在其自己的AppDomain中运行。每个AppDomain都应该运行自己的控制台


    啊,你说得对。我在考虑在一个进程内运行可执行文件,但忘记了它们启动自己的进程-我没有深入到足够远的地方。

    我猜大概在3到4之间。控制台是一个独立的对象,具有标准的输入、输出和错误流。这些流连接到使用控制台的第一个进程。如果没有重定向,后续进程也可以继承这些流(例如,运行带有重定向到文件的命令)

    通常不存在争用,因为父进程通常等待其子进程完成,而异步进程通常启动自己的控制台(例如,在命令提示符下尝试“start cmd”)或重定向标准输出


    但是,没有什么可以阻止两个进程同时写入输出流——流是共享的。这在使用某些运行时库时可能是一个问题,因为对标准输出/错误的写入可能不会立即刷新,从而导致混合的乱码输出。一般来说,必须让进程主动写入同一输出流通常不是一个好主意,除非您采取措施通过互斥体、事件等并发原语来协调它们的输出。

    CMD“拥有”控制台。为应用程序创建进程时,该应用程序会将句柄继承到控制台。它可以读写这些。当流程结束时,CMD继续拥有所有权


    注意:我不完全确定“所有权”这个词在这里是否正确。当CMD退出时,Windows将关闭控制台,但这可能是一个简单的设置。

    SDK谈论它的方式非常类似于1。它是CreateProcess的一个选项,描述如下:

    创建新的控制台
    新进程有一个新控制台,而不是继承其父进程的控制台(默认)。有关更多信息,请参阅创建控制台

    然而,输出是通过句柄进行的,您可以通过GetStdHandle()获得一个。传递STD_OUTPUT_HANDLE返回控制台句柄,假设输出未重定向。实际输出是通过WriteFile()或WriteConsole/output()完成的。如果两个进程都将输出写入句柄,那么它们的输出将随机混合。这与两个程序写入同一个文件句柄时发生的情况是无法区分的


    从逻辑上讲,有一个屏幕缓冲区与控制台关联。您可以使用SetConsoleScreenBufferXxx()对其进行修补。从这个角度来看,你可以称之为共享内存。实际的实现是不可发现的,就像任何Win32 API一样,将它们抽象掉。使用新的conhost.exe进程,Vista中的情况肯定发生了很大的变化。

    我认为它在中的表述相当清楚。

    您的四种可能性中没有一种是实际情况,对于您的后续问题,“两个进程中的哪一个负责管理窗口?”,答案是这两个进程都不负责。TUI程序根本不需要了解任何关于windows的知识,而且,在幕后,甚至不必深入到GUI

    控制台是对象,通过句柄访问,就像文件、目录、管道、进程和线程一样。单个进程不会通过其句柄“拥有”控制台,就像一个进程“拥有”其具有打开句柄的任何文件一样。控制台的句柄由子进程从其父进程继承,继承方式与所有其他(可继承)句柄相同。由CMD生成的TUI应用程序只继承了CMD在调用
    CreateProcess()
    -时说它应该继承的标准句柄,这些句柄通常是CMD的标准输入、输出和错误(除非命令行告诉CMD使用一些其他句柄作为子级的标准输入、输出和错误)

    控制台不依赖于CMD。只要(a)控制台的输入或输出缓冲区有任何打开的句柄,或者(b)以其他方式“连接”到控制台的任何进程,它们就存在。因此,在您的示例中,您可以杀死CMD,但只有在终止子进程时,控制台才会被实际销毁


    在6.1版之前的windows NT中,负责显示控制台所在GUI窗口的过程是CSRSS,即客户机-服务器运行时子系统。窗口处理代码位于WINSRV.DLL中,其中包含“控制台服务器”,在幕后执行控制台I/O的Win32程序会对其进行LPC调用。在Windows NT 6.1中,由于种种原因,此功能从CSRSS移到了CSRSS产生的权限较低的进程中。

    控制台是Windows的概念,它是每个进程的