2015-04-24 2 views
1

Я в настоящее время погружаюсь в API Win32 и пишу сам класс-оболочку для CreateProcess и CreatePipe. Мне просто интересно, что произойдет, если процесс, который я открыл, создает слишком большой вывод для хранения буфера. Будет ли процесс ждать, пока я не прочитаю с другого конца трубы? Замечание функции CreatePipe предполагает, таким образом:Будет ли процесс записываться в блок трубы, если труба заполнена?

Когда процесс использует WriteFile для записи анонимной трубы, операция записи не завершена, пока все байты не будут записаны. Если буфер буфера заполнен до того, как все байты будут записаны, WriteFile не вернется, пока другой процесс или поток не использует ReadFile, чтобы сделать больше доступного пространства для буфера.

https://msdn.microsoft.com/en-us/library/windows/desktop/aa365152%28v=vs.85%29.aspx

Давайте предположим, что я открываю процесс с CreateProcess, а затем использовать WaitForSingleObject подождать, пока процесс не завершит работу. Будет ли процесс когда-либо выходить, если он превышает размер буфера его стандартного выходного канала?

+1

Если в официальной ссылке указано, что функция «WriteFile» не возвращается до ... », это то же самое, что и ее блокировка. Итак, ответ заключается в том, что да, запись в полный канал будет заблокирована. Кстати, это стандартное поведение, например. POSIX (например, Linux или OSX). –

+1

В системах POSIX это действительно то, что происходит: производитель блокируется, пока не будет места для записи. Например, когда вы делаете 'ls -R/| less', 'less' будет читать некоторые экраны текста, а затем блокировать' ls', пока пользователь не прокрутится вниз. Если пользователь убивает процесс чтения (например, выйдя из «меньше»), исходный процесс будет убит. Это может сэкономить массу бесполезных вычислений. – anol

+1

«Не возвращает» == блок. Если вы не читаете перенаправленный вывод, то да, этот процесс, скорее всего, заторможен. Довольно стандартная ошибка - это дренаж stdout, но не stderr. Вам понадобится WaitForMultipleObjects() для всех трех ручек. –

ответ

3

WaitForSingleObject Процесс с перенаправленным выходом действительно является взаимоблокировкой. Вам необходимо убрать выходную трубку, чтобы позволить дочернему процессу завершить работу.

Как правило, вы бы использовать перекрывается ввода/вывода на трубе, а затем WaitForMultipleObjects на ручке пары (дескриптор процесса, труба чтения ручки события) в цикле, пока процесс не дескриптор становится сигнальным.

Raymond Chen писал о сценарии, когда вход также поступает:


Как отметил Ханс, может быть больше, чем один выходной поток. stdout, stderr являются типичными, еще больше возможны через наследование рукоятки. Слейте все трубы, выходящие из процесса.

+0

Спасибо за ваш информативный ответ. У меня есть еще один вопрос: когда я вызываю «CloseHandle» на всех созданных для этого процесса трубах, может ли возникнуть тупик или я могу назвать «WaitForSingleObject»?Я хочу добавить метод 'Wait()', который просто опускает любой результат, созданный процессом, но блокирует его до тех пор, пока он не завершится. –

+0

Вы спрашиваете о том, что CloseHandle является родительским или дочерним процессом? Это предотвратит тупик, но на другом конце трубы будут возникать ошибки при попытке записи или чтения нулевого байта. –

+0

В родительском процессе. С «ручками в дочернем процессе» вы ссылаетесь на ручки, указанные мной в структуре «STARTUPINFO»? Предполагая, что дочерний процесс читается со стандартного ввода, и я закрываю его из родительского процесса, будет ли дочерний процесс запущен в ошибке или он просто ничего не прочитает (или что останется) в стандартном входном канале? –

Смежные вопросы