_pipe
Tworzy potok do odczytu i zapisu.
Ważne
Tego interfejsu API nie można używać w aplikacjach wykonywanych w środowisko wykonawcze systemu Windows. Aby uzyskać więcej informacji, zobacz Funkcje CRT nieobsługiwane w aplikacjach platforma uniwersalna systemu Windows.
Składnia
int _pipe(
int *pfds,
unsigned int psize,
int textmode
);
Parametry
pfds
Wskaźnik do tablicy dwóch int
do przechowywania deskryptorów plików odczytu i zapisu.
psize
Ilość pamięci do zarezerwowania.
textmode
Tryb pliku.
Wartość zwracana
Zwraca wartość 0 w przypadku powodzenia. Zwraca wartość -1, aby wskazać błąd. W przypadku błędu errno
ustawiono jedną z następujących wartości:
EMFILE
, co wskazuje, że nie są dostępne żadne deskryptory plików.ENFILE
, który wskazuje przepełnienie tabeli system-file-table.EINVAL
, który wskazuje, że tablicapfds
jest wskaźnikiem o wartości null lub że przekazano nieprawidłową wartośćtextmode
.
Aby uzyskać więcej informacji na temat tych i innych kodów powrotnych, zobacz errno
, _doserrno
, _sys_errlist
i _sys_nerr
.
Uwagi
Funkcja _pipe
tworzy potok, który jest sztucznym kanałem we/wy używanym przez program do przekazywania informacji do innych programów. Potok przypomina plik, ponieważ zawiera wskaźnik pliku, deskryptor plików lub oba te elementy. Można go odczytywać lub zapisywać przy użyciu funkcji wejściowych i wyjściowych biblioteki standardowej. Potok nie reprezentuje jednak określonego pliku ani urządzenia. Zamiast tego reprezentuje magazyn tymczasowy w pamięci, który jest niezależny od własnej pamięci programu i jest kontrolowany całkowicie przez system operacyjny.
_pipe
_open
przypomina, ale otwiera potok do odczytu i zapisu i zwraca dwa deskryptory plików zamiast jednego. Program może używać obu stron rury lub zamknąć ten, którego nie potrzebuje. Na przykład procesor poleceń w systemie Windows tworzy potok podczas wykonywania polecenia takiego jak PROGRAM1 | PROGRAM2
.
Standardowy deskryptor danych wyjściowych PROGRAM1
jest dołączony do deskryptora zapisu potoku. Standardowy deskryptor PROGRAM2
wejściowy elementu jest dołączony do deskryptora odczytu potoku. Ten załącznik eliminuje konieczność tworzenia plików tymczasowych w celu przekazania informacji do innych programów.
Funkcja _pipe
zwraca dwa deskryptory plików do potoku w argumencie pfds
. Element pfds
[0] zawiera deskryptor odczytu, a element pfds
[1] zawiera deskryptor zapisu. Deskryptory plików potokowych są używane w taki sam sposób jak inne deskryptory plików. (Funkcje wejściowe i wyjściowe _read
niskiego poziomu oraz _write
mogą odczytywać i zapisywać w potoku). Aby wykryć warunek końca potoku, sprawdź _read
żądanie zwracające wartość 0 jako liczbę odczytanych bajtów.
Argument psize
określa ilość pamięci w bajtach do zarezerwowania dla potoku. Argument textmode
określa tryb tłumaczenia potoku. Stała _O_TEXT
manifestu określa tłumaczenie tekstu ANSI, a stała _O_BINARY
określa tłumaczenie binarne. (Zobacz fopen
, _wfopen
aby uzyskać opis trybów tekstowych i binarnych). textmode
Jeśli argument ma wartość 0, _pipe
używa domyślnego trybu tłumaczenia określonego przez zmienną trybu _fmode
domyślnego .
W programach wielowątkowych nie jest wykonywane blokowanie. Deskryptory plików, które są zwracane, są nowo otwarte i nie powinny być przywoływane przez żaden wątek do momentu _pipe
zakończenia wywołania.
Aby używać _pipe
funkcji do komunikowania się między procesem nadrzędnym a procesem podrzędnym, każdy proces musi mieć tylko jeden deskryptor otwarty w potoku. Deskryptory muszą być przeciwieństwami: jeśli element nadrzędny ma otwarty deskryptor odczytu, wówczas element podrzędny musi mieć otwarty deskryptor zapisu. Najłatwiej jest użyć bitowego znaku "lub" (|
) na flagi _O_NOINHERIT
z textmode
. Następnie użyj polecenia _dup
lub _dup2
, aby utworzyć dziedziczoną kopię deskryptora potoku, którą chcesz przekazać do elementu podrzędnego. Zamknij oryginalny deskryptor, a następnie zduplikuj proces podrzędny. Po powrocie z wywołania spawn zamknij zduplikowany deskryptor w procesie nadrzędnym. Aby uzyskać więcej informacji, zobacz przykład 2 w dalszej części tego artykułu.
W systemie operacyjnym Windows potok jest niszczony, gdy wszystkie deskryptory zostały zamknięte. (Jeśli wszystkie deskryptory odczytu w potoku zostały zamknięte, zapis w potoku powoduje błąd). Wszystkie operacje odczytu i zapisu w potoku czekają na wystarczającą ilość danych lub wystarczającą ilość miejsca buforu do ukończenia żądania we/wy.
Domyślnie stan globalny tej funkcji jest zakresem aplikacji. Aby zmienić to zachowanie, zobacz Stan globalny w CRT.
Wymagania
Procedura | Wymagany nagłówek | Opcjonalny nagłówek |
---|---|---|
_pipe |
<io.h> |
<fcntl.h> ,1 <errno.h> 2 |
1 Dla _O_BINARY
definicji i _O_TEXT
.
2 errno
definicje.
Aby uzyskać więcej informacji o zgodności, zobacz Zgodność.
Biblioteki
Wszystkie wersje bibliotek czasu wykonywania języka C.
Przykład 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.
Przykład 2
Przykładowy kod to podstawowa aplikacja filtru. Spowoduje to zduplikowane przez aplikację crt_pipe_beeper
po utworzeniu potoku, który kieruje zduplikowaną aplikację stdout
do filtru. Filtr usuwa znaki ASCII 7 (sygnał dźwiękowy).
// 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;
}
Rzeczywista aplikacja filtru:
// 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...