Crearea unui proces copil cu o intrare și ieșire realocată
Exemplul din această secțiune demonstrează modul de creare a unui proces copil din procesul de consolă. Aceasta demonstrează, de asemenea, tehnica utilizării canalelor de programe anonime pentru a realoca descriptorii standard ai intrării și ieșirii procesului copil.
Funcția CreatePipe utilizează structura SECURITY_ATTRIBUTES. Pentru a crea descriptori moștenitori pentru citire și scriere la capetele a două canale. Sfârșitul citirii într-unul din canale servește ca intrare standard pentru procesul copil, iar sfârșitul înregistrării în celălalt canal este ieșirea standard pentru procesul copilului. Acești descriptori de canal sunt setați în funcția SetStdHandle. ceea ce le face să fie descriptori standardi moșteniți de procesul copilului. După crearea procesului copil, SetStdHandle este folosit din nou pentru a restabili descriptorii sursă standard pentru procesul părinte.
Procesul părinte folosește celălalt capăt al canalului pentru a înregistra intrările și să citească datele de ieșire ale datelor de proces copil. Descriptorii acestor capete ale canalului sunt, de asemenea, moștenitori. Cu toate acestea, descriptorul nu trebuie moștenit. Înainte de a crea un proces copil, procesul parent trebuie să utilizeze DuplicateHandle. Pentru a crea un duplicat al variabilei globale definite de programul hChildStdinWr. care nu pot fi moștenite. Apoi îl folosește pe CloseHandle. pentru a închide mânerul mostenit. Pentru mai multe informații, consultați capitolul Canale.
Următorul este procesul părinte.
#defineBUFSIZE 4096
MANUAL hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
hInputFile, hSaveStdin, hSaveStdout;
BOOLCreateChildProcess (VOID);
VOIDReadFromPipe (VOID);
// Setați pavilionul bInheritHandle, dat fiind că descriptorii canalului sunt moșteniți.
saAttr.nLength = dimensiunea (SECURITY_ATTRIBUTES);
// Pasii pentru a reassign STDOUT la procesul copilului
// 1. Salvați STDOUT-ul curent, care va fi restaurat mai târziu.
// 2. Creați un canal anonim, care va fi STDOUT al procesului copil.
// 3. Stabiliți STDOUT-ul procesului părinte, care va,
// descriptorul înregistrării canalului prin procesul copilului moștenit.
// 4. Creați duplicatul non-moștenit al descriptorului de citire și închideți-l
// descriptor de citire moștenit.
// Salvați descriptorul STDOUT curent.
hSaveStdout = GetStdHandle (STD_OUTPUT_HANDLE);
// Creați un canal pentru STDOUT a procesului copil.
dacă (! CreatePipe (hChildStdoutRd, hChildStdoutWr, saAttr, 0))
ErrorExit ("Crearea conductei Stdout nu a reușit \ n");
// Setați descriptorul înregistrării canalului, care va fi STDOUT.
dacă (! SetStdHandle (STD_OUTPUT_HANDLE.hChildStdoutWr))
ErrorExit ("Redirecționarea STDOUT nu a reușit");
// Creați un descriptor de citire nefolosit și închideți descriptorul de citire moștenit.
fSuccess = DuplicateHandle (GetCurrentProcess (), hChildStdoutRd,
GetCurrentProcess (), hChildStdoutRdDup. 0
ErrorExit ("DuplicateHandle nu a reușit");
// Etape de reatribuire a STDIN la procesul copilului:
// 1. Salvați actualul STDIN, care va fi restaurat mai târziu.
// 2. Creați un canal anonim, care va fi STDIN al procesului copil.
// 3. Stabiliți STDIN al procesului părinte, care este descriptorul
// citiți canalul, astfel încât acesta să fie moștenit de procesul copilului.
// 4. Creați duplicatul non-mostenit al descriptorului înregistrării închideți
// Descrierea moștenită a înregistrării.
// Salvați descriptorul STDIN curent.
hSaveStdin = GetStdHandle (STD_INPUT_HANDLE);
// Creați un canal pentru procesul STDIN al copilului.
dacă (! CreatePipe ( hChildStdinRd, hChildStdinWr, saAttr, 0))
ErrorExit ("Crearea conductei Stdin a eșuat \ n");
// Setați descriptorul de citire pentru canalul care va fi STDIN.
dacă (! SetStdHandle (STD_INPUT_HANDLE.hChildStdinRd))
ErrorExit ("Redirecționarea Stdin a eșuat");
// Duplicați maneta de scriere pentru canal, deci nu a fost moștenită.
fSuccess = DuplicateHandle (GetCurrentProcess (), hChildStdinWr,
GetCurrentProcess (), hChildStdinWrDup, 0,
FALSE, // nu moșteneste
ErrorExit ("DuplicateHandle nu a reușit");
// Creați acum procesul copilului.
ErrorExit ("Procesul de creare a eșuat");
// După crearea procesului, restaurați STDIN și STDOUT salvate.
dacă (! SetStdHandle (STD_INPUT_HANDLE.hSaveStdin))
ErrorExit ("Redirecționarea Stdin nu a reușit \ n");
dacă (! SetStdHandle (STD_OUTPUT_HANDLE.hSaveStdout))
ErrorExit ("Redirecționarea Stdout nu a reușit \ n");
// Obțineți descriptorul pentru fișierul de intrare al părintelui.
hInputFile = CreateFile (argv [1], GENERIC_READ 0, NULL,
OPEN_EXISTING. FILE_ATTRIBUTE_READONLY. NULL);
dacă (hInputFile == INVALID_HANDLE_VALUE)
ErrorExit ("niciun fișier de intrare \ n");
// Scrie la canal, care este intrarea standard a datelor pentru copil
// Citiți din canal, care este ieșirea standard pentru copil