【问题标题】:On Windows, how does console window ownership work?在 Windows 上,控制台窗口所有权如何工作?
【发布时间】:2011-02-17 22:27:33
【问题描述】:

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

我看到了四种可能性:

  1. 第二个应用程序在其生命周期内从第一个应用程序继承控制台,控制台在退出时返回给原始所有者。
  2. 每个应用程序都有自己的控制台。然后 Windows 以某种方式将两者的内容合并到用户可见的“控制台”中
  3. 第二个应用程序获取属于第一个应用程序的控制台句柄。
  4. 控制台放置在共享内存中,两个应用程序具有相同的“所有权”

很可能我错过了一些东西,这四个选项都不能充分描述 Windows 对其控制台的作用。

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

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

【问题讨论】:

    标签: windows winapi console console-application


    【解决方案1】:

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

    啊,你是对的。我正在考虑在进程中运行可执行文件,但忘记了它们启动自己的进程 - 我没有深入了解。

    【讨论】:

    • 控制台是一个 Windows 概念,它是每个进程而不是 AppDomain
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      CMD“拥有”控制台。当它为应用程序创建进程时,该应用程序会继承控制台的句柄。它可以读取和写入这些。当进程消失时,CMD 继续拥有所有权。

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

      【讨论】:

        【解决方案4】:

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

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

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

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

        【讨论】:

          【解决方案5】:

          我认为documentation 中的拼写相当好。

          【讨论】:

            【解决方案6】:

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

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

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-11-12
              • 2014-04-11
              • 1970-01-01
              • 2017-04-22
              • 2011-01-20
              • 2010-09-16
              • 1970-01-01
              相关资源
              最近更新 更多