В Windows, как владение консоли работает?

Когда консольное приложение запускается с другого консольного приложения, как консольное владение работает?

Я вижу четыре возможности:

  1. Второе приложение наследовало консоль от первого приложения в течение его времени жизни с консолью, возвращающейся к первоначальному владельцу на выходе.
  2. Каждое приложение имеет свою собственную консоль. Windows затем так или иначе объединяет содержание двух в какой "консоль", видимая пользователю
  3. Второе приложение получает дескриптор к консоли, которая принадлежит первому приложению.
  4. Консоль помещается в общую память, и оба приложения имеют равное "владение"

Довольно возможно, что я пропустил что-то, и ни одна из этих четырех опций соответственно не описывает то, что Windows делает с его консолями.

Если ответ близко к опции 4. Мой последующий вопрос - какой из двух процессов ответственен за управление окном? (Обработка графических обновлений, когда экран должен быть обновлен / перерисованный, и т.д.),

Конкретный пример: Выполните CMD. Затем с помощью CMD, выполненного [консольное приложение]. [Консольное приложение] запишет в то, что, кажется, та же консоль, которую использовал CMD.

5
задан shroudednight 11 May 2010 в 00:17
поделиться

6 ответов

Ни одна из ваших четырех возможностей на самом деле не соответствует действительности, и ответ на ваш последующий вопрос: «Какой из двух процессов отвечает за управление окном? ? ", это то, что ни один процесс не несет ответственности. Программы TUI вообще ничего не должны знать об окнах , и, по сути, не обязательно даже подключены к графическому интерфейсу.

Консоли - это объекты, к которым осуществляется доступ через дескрипторы, как и к файлам, каталогам, каналам, процессам и потокам. Отдельный процесс не «владеет» консолью через свой дескриптор, как и процесс «владеет» любым файлом, для которого у него есть открытый дескриптор. Дескрипторы консолей наследуются дочерними процессами от своих родителей так же, как и все другие (наследуемые) дескрипторы. Ваше приложение TUI, порожденное CMD, просто наследует стандартные дескрипторы, которые CMD сказал, что он должен наследовать, когда он вызвал CreateProcess () - которые обычно будут стандартным вводом, выводом и ошибкой CMD (если только командная строка сказала CMD использовать некоторые другие дескрипторы в качестве стандартных входных данных, выходных данных и ошибок дочернего элемента).

Консоли не зависят от CMD. Они существуют до тех пор, пока есть (а) любые открытые дескрипторы буферов ввода или вывода консоли или (б) любые процессы, иным образом «прикрепленные» к консоли. Итак, в вашем примере вы можете убить CMD, но только когда вы завершите дочерний процесс, консоль будет фактически уничтожена.

Процесс, отвечающий за отображение окон графического интерфейса пользователя, в которых представлены консоли, в Windows NT до версии 6.1 представляет собой CSRSS, подсистему времени выполнения клиент-сервер. Код обработки окна находится в WINSRV.DLL, который содержит «консольный сервер», на который - под покровом - программы Win32, выполняющие консольный ввод-вывод, обращаются к LPC-вызовам. В Windows NT 6.1 эта функциональность по причинам , описанным Раймондом Ченом , была перенесена из CSRSS в менее привилегированный процесс, порождаемый CSRSS.

6
ответ дан 14 December 2019 в 08:45
поделиться

Мое предположение - где-то между 3 и 4. Консоль - это самостоятельный объект, который имеет стандартные потоки ввода, вывода и ошибок. Эти потоки присоединяются к первому процессу, который использует консоль. Последующие процессы также могут наследовать эти потоки, если они не перенаправлены (например, выполнение команды с перенаправлением в файл).

Обычно не происходит никаких конфликтов, поскольку родительские процессы обычно ждут завершения дочернего процесса, а асинхронные процессы обычно запускают свою собственную консоль (например, попробуйте "start cmd" в командной строке) или перенаправляют стандартный вывод.

Однако ничто не мешает обоим процессам писать в выходной поток одновременно - потоки являются общими. Это может стать проблемой при использовании некоторых библиотек времени выполнения, поскольку запись в стандартный вывод/ошибку может быть не сразу удалена, что приведет к смешанному беспорядочному выводу. В общем, наличие процессов, активно пишущих в один и тот же поток вывода, обычно не является хорошей идеей, если только вы не приняли меры для координации их вывода с помощью примитивов параллелизма, таких как мьютексы, события и тому подобное.

1
ответ дан 14 December 2019 в 08:45
поделиться

То, как SDK говорит об этом, очень похоже на 1. Это вариант с CreateProcess, описанный следующим образом:

CREATE_NEW_CONSOLE
Новый процесс имеет новую консоль вместо наследования родительской консоли (по умолчанию). Для получения дополнительной информации см. Создание консоли.

Вывод, однако, осуществляется через дескрипторы, вы бы получили их с помощью GetStdHandle (). Передача STD_OUTPUT_HANDLE возвращает дескриптор консоли, если вывод не перенаправляется. Фактический вывод осуществляется через WriteFile () или WriteConsole / Output (). Если оба процесса продолжают записывать выходные данные в дескриптор, их выходные данные будут случайным образом перемешаны. В остальном это неотличимо от того, что произошло бы, когда две программы записывают в один и тот же дескриптор файла.

Логично, что с консолью связан экранный буфер. Вы можете повозиться с этим с помощью SetConsoleScreenBufferXxx (). С этой точки зрения вы могли бы назвать это общей памятью. Фактическая реализация не обнаруживается, абстрагируются от них, как и в любом Win32 API. Несомненно, он значительно изменился в Vista с появлением нового процесса conhost.exe.

1
ответ дан 14 December 2019 в 08:45
поделиться

CMD "владеет" консолью. Когда он создает процесс для приложения, это приложение наследует дескрипторы консоли. Он может их читать и писать. Когда процесс завершается, CMD продолжает владение.

Примечание: я не совсем уверен, что «владение» здесь правильное слово. Windows закроет консоль при выходе из CMD, но это может быть простая настройка.

0
ответ дан 14 December 2019 в 08:45
поделиться

Я думаю, что это довольно хорошо изложено в документации .

0
ответ дан 14 December 2019 в 08:45
поделиться

Каждое приложение будет запускаться в собственном AppDomain. В каждом AppDomain должна быть запущена своя консоль.

А, вы правы. Я думал о запуске исполняемых файлов внутри процесса и забыл, что они запускают свой собственный процесс - я недостаточно глубоко вник.

-1
ответ дан 14 December 2019 в 08:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: