_pipe
Erstellt eine Pipe zum Lesen und Schreiben.
Wichtig
Diese API kann nicht in Anwendungen verwendet werden, die in Windows-Runtime ausgeführt werden. Weitere Informationen finden Sie im Artikel CRT functions not supported in Universal Windows Platform apps (In Apps für die universelle Windows-Plattform nicht unterstützte CRT-Funktionen).
Syntax
int _pipe(
int *pfds,
unsigned int psize,
int textmode
);
Parameter
pfds
Zeigen Sie auf ein Array von zwei int
Zum Lesen und Schreiben von Dateideskriptoren.
psize
Menge des zugesicherten Arbeitsspeichers.
textmode
Dateimodus.
Rückgabewert
Gibt bei Erfolg 0 zurück. Gibt -1 zurück, um einen Fehler anzugeben. Bei einem Fehler wird errno
auf einen dieser Werte festgelegt:
EMFILE
gibt an, dass keine weiteren Dateideskriptoren verfügbar sind.ENFILE
gibt einen Systemdateitabellenüberlauf an.EINVAL
gibt an, dass entweder das Arraypfds
ein NULL-Zeiger ist, oder dass ein ungültiger Wert fürtextmode
übergeben wurde.
Weitere Informationen zu diesen und anderen Rückgabecodes finden Sie unter , , _doserrno
, _sys_errlist
und _sys_nerr
.errno
Hinweise
Die _pipe
-Funktion erstellt eine neue pipe, die ein künstlicher Ein-/Ausgabekanal ist und von einem Programm verwendet wird, um Informationen an andere Programme zu übergeben. Eine Pipe ähnelt einer Datei, da sie einen Dateizeiger, einen Dateideskriptor oder beides enthält. Außerdem kann sie mithilfe der Eingabe- und Ausgabefunktionen der Standardbibliothek gelesen oder in diese geschrieben werden. Eine Pipe stellt jedoch keine bestimmte Datei oder ein bestimmtes Gerät dar. Stattdessen repräsentiert die Pipe einen temporären Speicher im Arbeitsspeicher, der vom Arbeitsspeicher des Programms unabhängig ist und vollständig über das Betriebssystem gesteuert wird.
_pipe
ähnelt _open
, öffnet jedoch die Pipe zum Lesen und Schreiben und gibt statt einem zwei Dateideskriptoren zurück. Das Programm kann beide Seiten der Pipe verwenden oder diejenige Seite schließen, die sie nicht benötigt. Zum Beispiel erstellt der Befehlsprozessor in Windows eine Pipe, wenn ein Befehl wie PROGRAM1 | PROGRAM2
ausgeführt wird.
Der Standardausgabedeskriptor von PROGRAM1
ist dem Schreibdeskriptor der Pipe angefügt. Der Standardeingabedeskriptor von PROGRAM2
ist dem Lesedeskriptor der Pipe angefügt. Diese Anlage beseitigt die Notwendigkeit, temporäre Dateien zu erstellen, um Informationen an andere Programme zu übergeben.
Die _pipe
-Funktion gibt zwei Dateideskriptoren an die Pipe im pfds
-Argument zurück. Das Element pfds
[0] enthält den Lesedeskriptor und das Element pfds
[1] enthält den Schreibdeskriptor. Pipedateideskriptoren werden auf die gleiche Weise wie andere Dateideskriptoren verwendet. (Die Eingabe- und Ausgabefunktionen _read
auf niedriger Ebene und _write
können aus einer Pipe lesen und schreiben.) Um die End-of-Pipe-Bedingung zu erkennen, suchen Sie nach einer _read
Anforderung, die 0 als Anzahl der gelesenen Bytes zurückgibt.
Das psize
-Argument gibt in Bytes den die Menge an Arbeitsspeicher an, die für die Pipe zugesichert ist. Das textmode
-Argument gibt den Übersetzungsmodus für die Pipe an. Die Manifestkonstante _O_TEXT
gibt eine ANSI-Textübersetzung an, und die Konstante _O_BINARY
gibt die binäre Übersetzung an. (Eine Beschreibung von Text- und Binärmodi finden Sie unter fopen
_wfopen
.) Wenn das textmode
Argument 0 ist, wird der Standardübersetzungsmodus verwendet, _pipe
der durch die Standardmodusvariable _fmode
angegeben wird.
In Multithreadprogrammen wird keine Sperre ausgeführt. Die zurückgegebenen Dateideskriptoren werden neu geöffnet und sollten erst nach Abschluss des _pipe
Aufrufs von einem Thread referenziert werden.
Um mit der _pipe
-Funktion zwischen einem übergeordneten Prozess und einen untergeordneten Prozess zu kommunizieren, darf jeder Prozess nur über einen Deskriptor verfügen, der auf der Pipe geöffnet ist. Die Deskriptoren müssen entgegengesetzt sein: Wenn das übergeordnete Element über einen geöffneten Lesedeskriptor verfügt, muss das untergeordnete Element über einen geöffneten Schreibdeskriptor verfügen. Es ist am einfachsten, ein bitweises "oder" (|
) auf der _O_NOINHERIT
Kennzeichnung mit textmode
zu verwenden. Anschließend erstellen Sie mit _dup
oder _dup2
eine vererbbare Kopie des Pipedeskriptors, den Sie dem untergeordneten Element übergeben möchten. Schließen Sie den ursprünglichen Deskriptor, und starten Sie dann den untergeordneten Prozess. Schließen Sie nach dem Startaufruf den doppelten Deskriptor im übergeordneten Prozess. Weitere Informationen finden Sie im zweiten Beispiel weiter unten in diesem Artikel.
Im Windows-Betriebssystem wird eine Pipe zerstört, wenn alle zugehörigen Deskriptoren geschlossen sind. (Wenn alle Lesedeskriptoren für die Rohre geschlossen wurden, verursacht das Schreiben in die Pfeife einen Fehler.) Alle Lese- und Schreibvorgänge für die Pipe warten, bis genügend Daten vorhanden sind oder genügend Pufferspeicher vorhanden ist, um die E/A-Anforderung abzuschließen.
Standardmäßig gilt der globale Zustand dieser Funktion für die Anwendung. Wie Sie dieses Verhalten ändern, erfahren Sie unter Globaler Status in der CRT.
Anforderungen
Routine | Erforderlicher Header | Optionaler Header |
---|---|---|
_pipe |
<io.h> |
<fcntl.h> ,1 <errno.h> 2 |
1 Für _O_BINARY
und _O_TEXT
Definitionen.
2 errno
Definitionen.
Weitere Informationen zur Kompatibilität finden Sie unter Kompatibilität.
Libraries
Alle Versionen der C-Laufzeitbibliotheken.
Beispiel 1
// crt_pipe.c
/* This program uses the _pipe function to pass streams of
* text to spawned processes.
*/
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include <math.h>
enum PIPES { READ, WRITE }; /* Constants 0 and 1 for READ and WRITE */
#define NUMPROBLEM 8
int main( int argc, char *argv[] )
{
int fdpipe[2];
char hstr[20];
int pid, problem, c;
int termstat;
/* If no arguments, this is the spawning process */
if( argc == 1 )
{
setvbuf( stdout, NULL, _IONBF, 0 );
/* Open a set of pipes */
if( _pipe( fdpipe, 256, O_BINARY ) == -1 )
exit( 1 );
/* Convert pipe read descriptor to string and pass as argument
* to spawned program. Program spawns itself (argv[0]).
*/
_itoa_s( fdpipe[READ], hstr, sizeof(hstr), 10 );
if( ( pid = _spawnl( P_NOWAIT, argv[0], argv[0],
hstr, NULL ) ) == -1 )
printf( "Spawn failed" );
/* Put problem in write pipe. Since spawned program is
* running simultaneously, first solutions may be done
* before last problem is given.
*/
for( problem = 1000; problem <= NUMPROBLEM * 1000; problem += 1000)
{
printf( "Son, what is the square root of %d?\n", problem );
_write( fdpipe[WRITE], (char *)&problem, sizeof( int ) );
}
/* Wait until spawned program is done processing. */
_cwait( &termstat, pid, WAIT_CHILD );
if( termstat & 0x0 )
printf( "Child failed\n" );
_close( fdpipe[READ] );
_close( fdpipe[WRITE] );
}
/* If there is an argument, this must be the spawned process. */
else
{
/* Convert passed string descriptor to integer descriptor. */
fdpipe[READ] = atoi( argv[1] );
/* Read problem from pipe and calculate solution. */
for( c = 0; c < NUMPROBLEM; c++ )
{
_read( fdpipe[READ], (char *)&problem, sizeof( int ) );
printf( "Dad, the square root of %d is %3.2f.\n",
problem, sqrt( ( double )problem ) );
}
}
}
Son, what is the square root of 1000?
Son, what is the square root of 2000?
Son, what iDad, the square root of 1000 is 31.62.
Dad, the square root of 2000 is 44.72.
s the square root of 3000?
Dad, the square root of 3000 is 54.77.
Son, what is the square root of 4000?
Dad, the square root of 4000 is 63.25.
Son, what is the square root of 5000?
Dad, the square root of 5000 is 70.71.
Son, what is the square root of 6000?
SonDad, the square root of 6000 is 77.46.
, what is the square root of 7000?
Dad, the square root of 7000 is 83.67.
Son, what is the square root of 8000?
Dad, the square root of 8000 is 89.44.
Beispiel 2
Der Beispielcode ist eine einfache Filteranwendung. Es wird die Anwendung crt_pipe_beeper
nach dem Erstellen einer Pipe erstellt, die die Spawned-Anwendung stdout
an den Filter weitergibt. Der Filter entfernt ASCII 7(Signalton)-Zeichen.
// crt_pipe_beeper.c
#include <stdio.h>
#include <string.h>
int main()
{
int i;
for(i=0;i<10;++i)
{
printf("This is speaker beep number %d...\n\7", i+1);
}
return 0;
}
Die tatsächliche Filteranwendung:
// crt_pipe_BeepFilter.C
// arguments: crt_pipe_beeper.exe
#include <windows.h>
#include <process.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#define OUT_BUFF_SIZE 512
#define READ_FD 0
#define WRITE_FD 1
#define BEEP_CHAR 7
char szBuffer[OUT_BUFF_SIZE];
int Filter(char* szBuff, ULONG nSize, int nChar)
{
char* szPos = szBuff + nSize -1;
char* szEnd = szPos;
int nRet = nSize;
while (szPos > szBuff)
{
if (*szPos == nChar)
{
memmove(szPos, szPos+1, szEnd - szPos);
--nRet;
}
--szPos;
}
return nRet;
}
int main(int argc, char** argv)
{
int nExitCode = STILL_ACTIVE;
if (argc >= 2)
{
HANDLE hProcess;
int fdStdOut;
int fdStdOutPipe[2];
// Create the pipe
if(_pipe(fdStdOutPipe, 512, O_NOINHERIT) == -1)
return 1;
// Duplicate stdout file descriptor (next line will close original)
fdStdOut = _dup(_fileno(stdout));
// Duplicate write end of pipe to stdout file descriptor
if(_dup2(fdStdOutPipe[WRITE_FD], _fileno(stdout)) != 0)
return 2;
// Close original write end of pipe
_close(fdStdOutPipe[WRITE_FD]);
// Spawn process
hProcess = (HANDLE)_spawnvp(P_NOWAIT, argv[1],
(const char* const*)&argv[1]);
// Duplicate copy of original stdout back into stdout
if(_dup2(fdStdOut, _fileno(stdout)) != 0)
return 3;
// Close duplicate copy of original stdout
_close(fdStdOut);
if(hProcess)
{
int nOutRead;
while (nExitCode == STILL_ACTIVE)
{
nOutRead = _read(fdStdOutPipe[READ_FD],
szBuffer, OUT_BUFF_SIZE);
if(nOutRead)
{
nOutRead = Filter(szBuffer, nOutRead, BEEP_CHAR);
fwrite(szBuffer, 1, nOutRead, stdout);
}
if(!GetExitCodeProcess(hProcess,(unsigned long*)&nExitCode))
return 4;
}
}
}
return nExitCode;
}
This is speaker beep number 1...
This is speaker beep number 2...
This is speaker beep number 3...
This is speaker beep number 4...
This is speaker beep number 5...
This is speaker beep number 6...
This is speaker beep number 7...
This is speaker beep number 8...
This is speaker beep number 9...
This is speaker beep number 10...