4.2.2. Los cambios del entorno que configura un proceso
Texto íntegro de la conversión. Las figuras y la disposición de las notas se pueden consultar en el PDF.
4.2.2. Los cambios del entorno que configura un proceso
El siguiente ejemplo muestra cómo se puede crear un proceso en Windows y cómo se puede realizar la redirección de las entradas y las salidas por medio de los manejadores (handles). Mostramos sólo algunos trozos que ilustran cómo se puede realizar la redirección. El ejemplo usa pipes. Aunque estudiaremos con detalle las pipes en el último módulo del curso, hemos visto ya su funcio-
Página 38
namiento básico al hablar del intérprete de comandos y la creación de filtros conectando la salida de unos comandos con la entrada de otros comandos. El ejemplo completo se puede encontrar en la web de ayuda a los desarrolladores de Microsoft bajo el concepto "Creating a Child Process with Redirected Input and Output".
El código del padre contiene:
... HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL; HANDLE g_hChildStd_OUT_Rd = NULL; HANDLE g_hChildStd_OUT_Wr = NULL;
... int _tmain(int argc, TCHAR *argv[]) {
SECURITY_ATTRIBUTES saAttr;
printf("\n->Start of parent execution.\n");
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDOUT. ¡if (! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
ErrorExit(TEXT("StdoutRd CreatePipe"));
// Ensure the read handle to the pipe for STDOUT is not inherited. ¡if (! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) ErrorExit(TEXT("Stdout SetHandleInformation"));
// Create a pipe for the child process's STDIN. ¡if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
ErrorExit(TEXT("Stdin CreatePipe"));
// Ensure the write handle to the pipe for STDIN is not inherited.
¡if (! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) ErrorExit(TEXT("Stdin SetHandleInformation"));
// Create the child process. CreateChildProcess();
... }
Página 39
void CreateChildProcess()
// Create a child process that uses the previously created pipes for STDIN and STDOUT. { TCHAR szCmdline[]=TEXT("child");
PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; BOOL bSuccess = FALSE;
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION));
// Set up members of the STARTUPINFO structure.
// This structure specifies the STDIN and STDOUT handles for redirection. ZeroMemory( &siStartInfo, sizeof(STARTUPINFO)); siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr; siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
bSuccess = CreateProcess(NULL, szCmdline // 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
// If an error occurs, exit the application. ¡if (! bSuccess) ErrorExit(TEXT("CreateProcess"));
else { // Close handles to the child process and its primary thread.
CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); }
}
El código del hijo es:
#include <windows.h>
Página 40
#include <stdio.h>
#define BUFSIZE 4096
int main(void)
{ CHAR chBuf[BUFSIZE]; DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout; BOOL bSuccess;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE); hStdin = GetStdHandle(STD_INPUT_HANDLE);
if ( (hStdout == INVALID_HANDLE_VALUE) || (hStdin == INVALID_HANDLE_VALUE)
) ExitProcess(1);
// Send something to this process's stdout using printf. printf("\n ** This is en message from the child process. ** \n");
// This simple algorithm uses the existence of the pipes to control execution. // It relies on the pipe buffers to ensure that no data is lost. // Larger applications would use more advanced process control.
for (;;) {
// Read from standard input and stop on error or no data. bSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
¡if (! bSuccess || dwRead == 0) break;
// Write to standard output and stop on error. bSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);
¡if (! bSuccess) break;
} return 0; }
Página 41
Ver fragmento extraído sin normalizar
4.2.2. Los cambios del entorno que configura un proceso
El siguiente ejemplo muestra cómo se puede crear un proceso en Windows y
cómo se puede realizar la redirección de las entradas y las salidas por medio de
los manejadores (handles). Mostramos sólo algunos trozos que ilustran cómo
se puede realizar la redirección. El ejemplo usa pipes. Aunque estudiaremos
con detalle las pipes en el último módulo del curso, hemos visto ya su funcio-
## Página 38
<!-- source-page: 38 -->
GNUFDL • PID_00214802 38 La gestión de procesos
namiento básico al hablar del intérprete de comandos y la creación de filtros
conectando la salida de unos comandos con la entrada de otros comandos. El
ejemplo completo se puede encontrar en la web de ayuda a los desarrolladores
de Microsoft bajo el concepto "Creating a Child Process with Redirected Input
and Output".
El código del padre contiene:
...
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
...
int _tmain(int argc, TCHAR *argv[])
{
SECURITY_ATTRIBUTES saAttr;
printf("\n->Start of parent execution.\n");
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDOUT.
¡if (! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
ErrorExit(TEXT("StdoutRd CreatePipe"));
// Ensure the read handle to the pipe for STDOUT is not inherited.
¡if (! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
ErrorExit(TEXT("Stdout SetHandleInformation"));
// Create a pipe for the child process's STDIN.
¡if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
ErrorExit(TEXT("Stdin CreatePipe"));
// Ensure the write handle to the pipe for STDIN is not inherited.
¡if (! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
ErrorExit(TEXT("Stdin SetHandleInformation"));
// Create the child process.
CreateChildProcess();
...
}
## Página 39
<!-- source-page: 39 -->
GNUFDL • PID_00214802 39 La gestión de procesos
void CreateChildProcess()
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
{
TCHAR szCmdline[]=TEXT("child");
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bSuccess = FALSE;
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION));
// Set up members of the STARTUPINFO structure.
// This structure specifies the STDIN and STDOUT handles for redirection.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
bSuccess = CreateProcess(NULL,
szCmdline // 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
// If an error occurs, exit the application.
¡if (! bSuccess)
ErrorExit(TEXT("CreateProcess"));
else
{
// Close handles to the child process and its primary thread.
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
}
}
El código del hijo es:
#include <windows.h>
## Página 40
<!-- source-page: 40 -->
GNUFDL • PID_00214802 40 La gestión de procesos
#include <stdio.h>
#define BUFSIZE 4096
int main(void)
{
CHAR chBuf[BUFSIZE];
DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout;
BOOL bSuccess;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hStdin = GetStdHandle(STD_INPUT_HANDLE);
if (
(hStdout == INVALID_HANDLE_VALUE) ||
(hStdin == INVALID_HANDLE_VALUE)
)
ExitProcess(1);
// Send something to this process's stdout using printf.
printf("\n ** This is en message from the child process. ** \n");
// This simple algorithm uses the existence of the pipes to control execution.
// It relies on the pipe buffers to ensure that no data is lost.
// Larger applications would use more advanced process control.
for (;;)
{
// Read from standard input and stop on error or no data.
bSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
¡if (! bSuccess || dwRead == 0)
break;
// Write to standard output and stop on error.
bSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);
¡if (! bSuccess)
break;
}
return 0;
}
## Página 41
<!-- source-page: 41 -->
GNUFDL • PID_00214802 41 La gestión de procesos