23

Фон

В прошлом году я собрал портативную систему для блогов и веб-серверов, которую можно запускать с флешки. Это здорово и прекрасно работает, особенно на XP. Проблема в том, что при запуске в Windows 7 каждая консольная программа порождает два процесса, сам процесс плюс копию conhost.exe .

проблема

В случае портативной системы блог, каждый из своих серверных компонентов mysqld.exe в MySQL, два экземпляра апача из httpd.exe два экземпляра VisualSVN в о visualsvnserver.exe и несколько экземпляров РНР php-cgi.exe нерестится экземпляр conhost.exe . В данный момент (без активных копий php-cgi.exe у меня работает пять экземпляров conhost.exe , которые используют почти без циклов ЦП, но занимают 22 МБ памяти (в дополнение к 80 МБ, которые в настоящее время выполняются фактическими процессами) с помощью).

Исследование

Поскольку Windows 7 была выпущена (и я думаю, что возможно начиная с Vista), я несколько раз пытался выяснить, для чего конкретно используются различные (новые) хост-процессы (например, conhost.exe , dllhost.exe и taskhost.exe) и действительно ли они необходимы. Я попытался убить их и обнаружил, что консольные программы продолжают работать, как для программ, которые используют окно консоли, так и для тех, которые не (например, серверы).

Я уже знаком со всем csrss.exe ⇨ Windows Vista ⇨ conhost.exe и неоднократно видел это (почти дословно) это объяснение . Проблема в том, что все просто копируют и вставляют то же самое объяснение, которое не помогает. Все это говорит о том, что в XP- консольных приложениях, которые «размещаются» или «работают под» csrss.exe , но в Windows 7 они были перемещены в conhost.exe для безопасности. Аспект безопасности имеет смысл, но он ничего не говорит о том, что означает его размещение или почему / когда это необходимо (или возможно ли избежать этого, если в этом нет необходимости). Даже в дискуссии Раймонда Чена по этому вопросу скрывается, почему консольные приложения вообще размещаются по-разному.

Наиболее подробное техническое объяснение, которое я могу найти, - это сообщение в блоге Microsoft, которое, кажется, подтверждает идею о том, что речь идет только о графическом интерфейсе и окне консольного приложения. Это заставляет меня задуматься о том, нужен ли conhost.exe для таких программ без окон, как эти серверы. Если окна вообще нет, то зачем мне тратить ресурсы и загромождать пространство процессов ненужными процессами? Почему Windows не может определить, когда это не нужно, и избежать этого? Ответ SecurityMatt также был немного полезен в отношении технического объяснения, но, опять же, недостаточно информации, которую я ищу.

Я не единственный, кто пытался найти способ остановить ненужные случаи с conhost . Этот человек спросил о его отключении, и ему просто сказали «это невозможно» без каких-либо дополнительных усилий или мыслей об этом. Хью Д. и «Едва ли это особенность» указали на проблему с многочисленными избыточными экземплярами conhost (по крайней мере, с csrss , была запущена только одна копия), включая использование ресурсов и длительные экземпляры после завершения их дочерних процессов. Я Лауфер усомнился, / когда это даже необходимо.

Наблюдения и попытки решения

Если они на самом деле не нужны во все времена (опять же, я не видел каких-либо побочных эффектов от их убийства), то я полагаю, что мог бы (очень раздражающе) обойти проблему, заменив серверы пакетными файлами, которые запускают серверы , подождите, а затем убейте копию conhost которую они вызывают для запуска. Конечно, это требует быстрого и простого способа определить, какой это. FallenGameR спросил, как получить экземпляр conhost.exe связанного с консольной программой с заданным PID, но не получил ответа. Я бы подумал, что простое получение PID родительского процесса должно помочь (нет, ProcessExplorer не является опцией, требуется автоматическое / скриптовое решение), но не только это потребует создания какой-то структуры для получения PID дочерний процесс (вместо того, чтобы просто запустить его и выполнить задачу), но это также означало бы найти способ сделать его совместимым с XP (например, проверить имя-изображения родительского процесса). Этот пост в блоге дает один способ, но он требует PowerShell и вряд ли идеален, не говоря уже о том, что он ничего не говорит о последствиях запуска скрипта.

Вопросы)

Возможно, Microsoft считает, что никто больше не использует командные подсказки (* кашель * Windows 8 * кашель *), и поэтому предположил, что не стоит их обременять, но есть определенные сценарии, когда несколько консольных приложений работают и имеют каждое из них. порождать дополнительный, требующий памяти процесс, использующий PID, ужасно, и пытаться обойти его, в лучшем случае, ужасно неудобно.

У кого-нибудь есть точная, авторитетная информация по этому вопросу? Опять же, я уже прочитал общее объяснение; Мне интересно:

  1. Почему консольные приложения должны (все еще) обрабатываться по-другому вообще
  2. При каких конкретных обстоятельствах они должны иметь conhost
  3. Каковы последствия убийства conhost
  4. Есть ли какой-нибудь способ остановить / предотвратить / отключить / заблокировать его или хотя бы простой способ быстро справиться с ним назад?

3 ответа3

18
  1. Консольные приложения должны обрабатываться по-разному, поскольку в ядре NT (которое лежит в основе всех 2000, XP, Vista, Windows 7 и Windows 8) они являются гражданами второго сорта. В архитектуре системы Unix каждый процесс во время создания имеет стандартные потоки ввода, вывода и ошибок, связанные с ним; Терминальный ввод-вывод реализован в терминах этих потоков (stdin, поступающий с клавиатуры, и stdout/stderr, идущий к терминалу), и требуются дополнительные усилия со стороны процесса, который не желает использовать эти потоки или имеет их файловые дескрипторы открыты.

    В архитектуре Windows NT, которая, хотя и не является прямым потомком VMS, была разработана более или менее одной и той же командой, верно и обратное; вновь порожденный процесс по умолчанию не имеет подключенных к нему потоков ввода-вывода, и такого понятия, как "терминал", не существует. Программы, которые хотят вести себя немного более Unixy-способом, могут запросить (путем объявления времени компиляции), что система создаст для них окно консоли и подключенные к нему потоки ввода / вывода; система сделает это, но поскольку Windows, в отличие от Unix, не предоставляет вам терминалы бесплатно, для их создания требуется значительное количество дополнительных усилий, то есть, прежде всего, csrss.exe , а теперь и conhost.exe .

    Что касается разницы между ними, ваша ссылка "Вряд ли особенность" объясняет это вполне адекватно; короче говоря, он существует для обхода уязвимости безопасности в предыдущей итерации высокосекундного консольного API-интерфейса Windows, который допускал повышение привилегий в версиях NT, более старых, чем Windows 7. (Vista, к вашему сведению, не имеет conhost.exe , что соответствует его статусу Windows Millennium семейства NT.)

  2. Любая программа, которая хочет получить эквивалент Unix stdin / stdout/stderr, нуждается в консоли, а следовательно, в экземпляре conhost.exe . Иммигранты из Unix-land, такие как Apache, PHP и др., Захотят получить эти потоки, поэтому для них будет автоматически создан экземпляр conhost.exe , независимо от того, отображают ли они окно или нет. Теоретически, было бы возможно изменить исходный код, например, для Apache, так, чтобы он не требовал терминала, и скомпилировать его как приложение с графическим интерфейсом Windows вместо консольного приложения, чтобы система не чувствовала необходимости порождать его как conhost.exe . Предполагая, что это также возможно на практике, похоже, никто не заботился об этом. Возможно, ты будешь первым.

  3. Уничтожение данного conhost.exe почти наверняка отключит консольный ввод-вывод для любого процесса, запущенного под этим экземпляром. Возможно, вас это не волнует, потому что вы имеете дело с серверными процессами, которые в любом случае не делают ничего интересного в консольных потоках ввода-вывода, поэтому, вероятно, нет причин не убивать их conhost.exe . Если есть сомнения, убейте их и посмотрите, не сломается ли что-нибудь.

  4. Нет способа предотвратить создание экземпляра conhost.exe Windows при запуске программы, которая запрашивает консольный ввод-вывод; единственный способ сделать это - перекомпилировать его, чтобы Windows не считала его консольным приложением. Однако, если предположить, что уничтожение родительского conhost.exe данного серверного процесса никоим образом не повлияет на его функциональность, вы сможете убить их всех сразу, taskkill /f /im conhost.exe в приглашении "Выполнить". или окно консоли - предпочтительно первое, так как последнее, вероятно, умрет и почти наверняка перестанет работать, как только его родительский экземпляр conhost.exe будет уничтожен. Опять же, если сомневаетесь, убейте их и посмотрите, не сломается ли что-нибудь.

6

Консольное приложение, запущенное с флагом DETACHED_PROCESS не получает ни консольный, ни дочерний процесс conhost. Проблема в том, что флаг не применяется к внукам, поэтому он будет работать только с процессами, которые вы запускаете напрямую (если вы даже можете найти утилиту, которая позволяет вам указать этот флаг).

Другой вариант, который может сработать, - это если консольный процесс вызывает FreeConsole() . Некоторые серверные приложения поддерживают параметр -d или -detach, но это, вероятно, чаще встречается в системах * nix ...

1

Быстрое решение, которое может работать на вас. При связывании вашего приложения добавьте /SUBSYSTEM:WINDOWS к параметрам. Вы также можете использовать editbin.exe для изменения существующего исполняемого файла.

Это предотвращает появление Windows conhost.exe для вашего приложения.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .