|
| БЕСПЛАТНАЯ ежедневная online лотерея! Выигрывай каждый день БЕСПЛАТНО! |
|
|
Creating a Child Process with Redirected Input and Output
The example in this topic demonstrates how to create a child process from a console process. It also demonstrates a technique for using anonymous pipes to redirect the child process's standard input and output handles.
The CreatePipe function uses the SECURITY_ATTRIBUTES structure to create inheritable handles to the read and write ends of two pipes. The read end of one pipe serves as standard input for the child process, and the write end of the other pipe is the standard output for the child process. These pipe handles are specified in the SetStdHandle function, which makes them the standard handles inherited by the child process. After the child process is created, SetStdHandle is used again to restore the original standard handles for the parent process.
The parent process uses the other ends of the pipes to write to the child process's input and read the child process's output. The handles to these ends of the pipe are also inheritable. However, the handle must not be inherited. Before creating the child process, the parent process must use DuplicateHandle to create a duplicate of the application-defined hChildStdinWr global variable that cannot be inherited. It then uses CloseHandle to close the inheritable handle. For more information, see Pipes.
The following is the parent process.
#include #include #define BUFSIZE 4096 HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, hInputFile, hSaveStdin, hSaveStdout; BOOL CreateChildProcess(VOID); VOID WriteToPipe(VOID); VOID ReadFromPipe(VOID); VOID ErrorExit(LPTSTR); VOID ErrMsg(LPTSTR, BOOL); DWORD main(int argc, char *argv[]) { SECURITY_ATTRIBUTES saAttr; BOOL fSuccess; // Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // The steps for redirecting child process's STDOUT: // 1. Save current STDOUT, to be restored later. // 2. Create anonymous pipe to be STDOUT for child process. // 3. Set STDOUT of the parent process to be write handle of // the pipe, so it is inherited by the child process. // 4. Create a noninheritable duplicate of the read handle and
// close the inheritable read handle. // Save the handle to the current STDOUT. hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); // Create a pipe for the child process's STDOUT. if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) ErrorExit("Stdout pipe creation failed\n"); // Set a write handle to the pipe to be STDOUT. if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) ErrorExit("Redirecting STDOUT failed");
// Create noninheritable read handle and close the inheritable read // handle.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup , 0, FALSE, DUPLICATE_SAME_ACCESS); if( !fSuccess ) ErrorExit("DuplicateHandle failed"); CloseHandle(hChildStdoutRd);
// The steps for redirecting child process's STDIN: // 1. Save current STDIN, to be restored later.
// 2. Create anonymous pipe to be STDIN for child process. // 3. Set STDIN of the parent to be the read handle of the // pipe, so it is inherited by the child process. // 4. Create a noninheritable duplicate of the write handle, // and close the inheritable write handle. // Save the handle to the current STDIN. hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); // Create a pipe for the child process's STDIN.
if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) ErrorExit("Stdin pipe creation failed\n"); // Set a read handle to the pipe to be STDIN. if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) ErrorExit("Redirecting Stdin failed"); // Duplicate the write handle to the pipe so it is not inherited. fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, // not inherited
DUPLICATE_SAME_ACCESS); if (! fSuccess) ErrorExit("DuplicateHandle failed"); CloseHandle(hChildStdinWr); // Now create the child process. if (! CreateChildProcess()) ErrorExit("Create process failed"); // After process creation, restore the saved STDIN and STDOUT. if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) ErrorExit("Re-redirecting Stdin failed\n"); if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
ErrorExit("Re-redirecting Stdout failed\n"); // Get a handle to the parent's input file. if (argc > 1) hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); else hInputFile = hSaveStdin; if (hInputFile == INVALID_HANDLE_VALUE) ErrorExit("no input file\n"); // Write to pipe that is the standard input for a child process. WriteToPipe(); // Read from pipe that is the standard output for child process.
ReadFromPipe(); return 0; } BOOL CreateChildProcess() { PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; // Set up members of STARTUPINFO structure. ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); siStartInfo.cb = sizeof(STARTUPINFO); // Create the child process. return CreateProcess(NULL, "child", // command line NULL, // process security attributes NULL, // primary thread security attributes
TRUE, // handles are inherited 0, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &siStartInfo, // STARTUPINFO pointer &piProcInfo); // receives PROCESS_INFORMATION } VOID WriteToPipe(VOID) { DWORD dwRead, dwWritten; CHAR chBuf[BUFSIZE]; // Read from a file and write its contents to a pipe. for (;;) { if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ||
dwRead == 0) break; if (! WriteFile(hChildStdinWrDup, chBuf, dwRead, &dwWritten, NULL)) break; } // Close the pipe handle so the child process stops reading. if (! CloseHandle(hChildStdinWrDup)) ErrorExit("Close pipe failed\n"); } VOID ReadFromPipe(VOID) { DWORD dwRead, dwWritten; CHAR chBuf[BUFSIZE]; HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Close the write end of the pipe before reading from the
// read end of the pipe. if (!CloseHandle(hChildStdoutWr)) ErrorExit("Closing handle failed"); // Read output from the child process, and write to parent's STDOUT. for (;;) { if( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0) break; if (! WriteFile(hSaveStdout, chBuf, dwRead, &dwWritten, NULL)) break; } } VOID ErrorExit (LPTSTR lpszMessage) { fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0); } // The code for the child process.
#include #define BUFSIZE 4096 VOID main(VOID) { CHAR chBuf[BUFSIZE]; DWORD dwRead, dwWritten; HANDLE hStdin, hStdout; BOOL fSuccess; hStdout = GetStdHandle(STD_OUTPUT_HANDLE); hStdin = GetStdHandle(STD_INPUT_HANDLE); if ((hStdout == INVALID_HANDLE_VALUE) || (hStdin == INVALID_HANDLE_VALUE)) ExitProcess(1); for (;;) { // Read from standard input.
fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL); if (! fSuccess || dwRead == 0) break; // Write to standard output. fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL); if (! fSuccess) break; } }
| Пригласи друзей и счет твоего мобильника всегда будет положительным! |
| Пригласи друзей и счет твоего мобильника всегда будет положительным! |
Создание Процесса Ребенка с Переназначенным Вкладом и Выходом
Пример в этой теме демонстрирует как, чтобы создавать процесс ребенка из консольного процесса. Это также демонстрирует технику для использования анонимных труб, чтобы переназначать процесс ребенка стандартные входные и выходные ручки.
Функция CreatePipe использует структуру SECURITY_ATTRIBUTES, чтобы создавать inheritable ручкам на чтение и концы записи двух труб. Конец чтения одной трубы служит в качестве стандартного вклада для процесса ребенка, и писать конец другой трубы является стандартным выходом для процесса ребенка. Эти ручки трубы определены в функции SetStdHandle, которая делает их стандартными ручками наследовался процессом ребенка. После того, как процесс ребенка будет создан, SetStdHandle используется снова, чтобы восстанавливать оригинальные стандартные ручки для родительского процесса.
Родительский процесс использует другие концы труб, чтобы писаться во вклад процесса ребенка и читать выход процесса ребенка. Ручки в эти концы трубы - также inheritable. Тем не менее, ручка не должна наследована. Перед созданием процесса ребенка, родительский процесс должен использовать DuplicateHandle, чтобы создавать дубликат определенной глобальной переменной приложения hChildStdinWr, которое не может быть унаследовано. Это затем использует CloseHandle, чтобы закрывать ручку inheritable. Более подробно, смотри Трубы.
Следующее является родительским процессом.
#include #include #define BUFSIZE 4096 ПРООПЕРИРУЙТЕ hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, hInputFile, hSaveStdin, hSaveStdout; BOOL CreateChildProcess(ПУСТОТА); НЕДЕЙСТВИТЕЛЬНАЯ WriteToPipe(ПУСТОТА); НЕДЕЙСТВИТЕЛЬНАЯ ReadFromPipe(ПУСТОТА); АННУЛИРУЙТЕ ErrorExit(LPTSTR); АННУЛИРУЙТЕ ErrMsg(LPTSTR, BOOL); ОСНОВА DWORD(int argc, символ *argv[]) { SECURITY_ATTRIBUTES saAttr; BOOL fSuccess; // Установившее флаг bInheritHandle, так что ручки трубы унаследованы.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = ИСТИНА; saAttr.lpSecurityDescriptor = НЕДЕЙСТВИТЕЛЬНЫЙ; // Шаги чтобы переназначать процесс ребенка STDOUT: // 1. Сохраняемое течение STDOUT, чтобы быть восстановленн позже. // 2. Создайте анонимную трубу, чтобы быть STDOUT для процесса ребенка. // 3. Установите STDOUT родительский процесс, чтобы быть ручкой записи // труба, так что унаследовано процессом ребенка. // 4. Создайте noninheritable дубликат ручки чтения и
// закрытие inheritable было прочитано ручка. // Сохраните ручку в течение STDOUT. hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); // Создайте трубу для процесса ребенка STDOUT. если (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) ErrorExit(СОЗДАНИЕ трубы "Stdout failed\n"); // Установленный записывать ручка в трубу, чтобы быть STDOUT. если (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) ErrorExit("Redirecting STDOUT ПОТЕРПЕВШИЙ неудачу");
// Создайте прочитанный noninheritable оперировать и закрывай inheritable прочитавшее // ручку.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup , 0, ЛОЖЬ, DUPLICATE_SAME_ACCESS); если( !fSuccess ) ErrorExit("DuplicateHandle ПОТЕРПЕВШИЙ неудачу"); CloseHandle(hChildStdoutRd);
// Шаги чтобы переназначать процесс ребенка STDIN: // 1. Сохраняемое течение STDIN, чтобы быть восстановленн позже.
// 2. Создайте анонимную трубу, чтобы быть STDIN для процесса ребенка. // 3. Установите STDIN родитель, чтобы быть ручкой чтения // трубы, так что унаследовано процессом ребенка. // 4. Создайте noninheritable дубликат записывать ручки, // и закрывать записывать ручку inheritable. // Сохраните ручку в течение STDIN. hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); // Создайте трубу для процесса ребенка STDIN.
если (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) ErrorExit(СОЗДАНИЕ трубы "Stdin failed\n"); // Установленный ручка чтения в трубу, чтобы быть STDIN. если (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) ErrorExit("Redirecting Stdin ПОТЕРПЕВШИЙ неудачу"); // Дубликат записывать ручка в трубу, так что это не унаследовано. fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, ЛОЖЬ, // не унаследованное
DUPLICATE_SAME_ACCESS); если (! fSuccess) ErrorExit("DuplicateHandle Потерпевший неудачу"); CloseHandle(hChildStdinWr); // Теперь создайте процесс ребенка. если (! CreateChildProcess()) ErrorExit(ПРОЦЕСС "Create терпел неудачу"); // После создания процесса, восстановите сохраненный STDIN и STDOUT. если (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) ErrorExit(ПЕРЕНАЗНАЧАТЬ "Re-Stdin failed\n"); если (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
ErrorExit(ПЕРЕНАЗНАЧАТЬ "Re-Stdout failed\n"); // Получите ручку в родительский входной файл. если (argc > 1) hInputFile = CreateFile(argv[1], GENERIC_READ, 0, НЕДЕЙСТВИТЕЛЬНЫЙ, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, НЕДЕЙСТВИТЕЛЬНЫЙ); еще hInputFile = hSaveStdin; если (hInputFile == INVALID_HANDLE_VALUE) ErrorExit("no ввод file\n"); // Запись в трубу, которая - стандартный ввод для процесса ребенка. WriteToPipe(); // Прочитанное из трубы, которая - стандартный выход для процесса ребенка.
ReadFromPipe(); возврат 0; } BOOL CreateChildProcess() { PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; // Установленные участники структуры STARTUPINFO. ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); siStartInfo.cb = sizeof(STARTUPINFO); // Создайте процесс ребенка. возврат CreateProcess(НЕДЕЙСТВИТЕЛЬНЫЙ, "ребенок", // командная строка НЕДЕЙСТВИТЕЛЬНАЯ, // атрибуты безопасности процесса НЕДЕЙСТВИТЕЛЬНЫЕ, // атрибуты безопасности первичной резьбы
ИСТИНА, // ручки унаследованы 0, // флаги создания НЕДЕЙСТВИТЕЛЬНАЯ, // родительская среда использования НЕДЕЙСТВИТЕЛЬНЫЙ, // родительский текущий директорий использования &siStartInfo, // указателя STARTUPINFO &piProcInfo); // приемники PROCESS_INFORMATION } ПУСТОТА WriteToPipe(ПУСТОТА) { DWORD dwRead, dwWritten; СИМВОЛ chBuf[BUFSIZE]; // Прочитанное из файла и записывать свое содержание в трубу. для (;;) { если (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, НЕДЕЙСТВИТЕЛЬНОЕ) ||
dwRead == 0) Прерывание; если (! WriteFile ПРЕРЫВАНИЯ(hChildStdinWrDup, chBuf, dwRead, &dwWritten, НЕДЕЙСТВИТЕЛЬНОЕ)); } // Закрытие ручка трубы так чтение стоп процесса ребенка. если (! CloseHandle(hChildStdinWrDup)) ErrorExit(ТРУБА "Close failed\n"); } ПУСТОТА ReadFromPipe(ПУСТОТА) { DWORD dwRead, dwWritten; СИМВОЛ chBuf[BUFSIZE]; ПРООПЕРИРУЙТЕ hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Закрытие записывать конец трубы перед чтением из the
// прочитанный конец трубы. если (!CloseHandle(hChildStdoutWr)) ErrorExit(РУЧКА "Closing терпела неудачу"); // Прочитанный выход от процесса ребенка, и записи до родительского STDOUT. для (;;) { если прерывание( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, НЕДЕЙСТВИТЕЛЬНОЕ) || dwRead == 0); если (! WriteFile ПРЕРЫВАНИЯ(hSaveStdout, chBuf, dwRead, &dwWritten, НЕДЕЙСТВИТЕЛЬНОЕ)); } } ПУСТОТА ErrorExit (lpszMessage LPTSTR) { fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0); } // Код для процесса ребенка.
#include <окно.h> #define BUFSIZE 4096 НЕДЕЙСТВИТЕЛЬНАЯ основа(ПУСТОТА) { СИМВОЛ chBuf[BUFSIZE]; DWORD dwRead, dwWritten; ПРООПЕРИРУЙТЕ hStdin, hStdout; BOOL fSuccess; hStdout = GetStdHandle(STD_OUTPUT_HANDLE); hStdin = GetStdHandle(STD_INPUT_HANDLE); если ((hStdout == INVALID_HANDLE_VALUE) || (hStdin == INVALID_HANDLE_VALUE)) ExitProcess(1); для (;;) { // Прочитанное со стандартного ввода.
fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, НЕДЕЙСТВИТЕЛЬНОЕ); если (! fSuccess || dwRead == 0) Прерывание; // Запись на стандартный выход. fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, НЕДЕЙСТВИТЕЛЬНОЕ); если (! fSuccess) Прерывание; } }
|
|
|
|
| |