_pipe_pipe

创建用于读取和写入的管道。Creates a pipe for reading and writing.

重要

此 API 不能用于在 Windows 运行时中执行的应用程序。This API cannot be used in applications that execute in the Windows Runtime. 有关详细信息,请参阅通用 Windows 平台应用中不支持的 CRT 函数For more information, see CRT functions not supported in Universal Windows Platform apps.

语法Syntax

int _pipe(
   int *pfds,
   unsigned int psize,
   int textmode
);

参数Parameters

pfdpfds
指向数组的两个指针int来保留读取和写入文件描述符。Pointer to an array of two int to hold read and write file descriptors.

psizepsize
要保留的内存量。Amount of memory to reserve.

textmodetextmode
文件模式。File mode.

返回值Return Value

如果成功,则返回 0。Returns 0 if successful. 将返回-1 以指示错误。Returns -1 to indicate an error. 错误时, errno设置为下列值之一:On error, errno is set to one of these values:

  • EMFILE,这指示没有其他文件说明符可用。EMFILE, which indicates that no more file descriptors are available.

  • ENFILE,指示系统文件表溢出。ENFILE, which indicates a system-file-table overflow.

  • EINVAL,表示其中一个数组pfd是 null 指针或值无效textmode中传递。EINVAL, which indicates that either the array pfds is a null pointer or that an invalid value for textmode was passed in.

有关这些代码及其他返回代码的详细信息,请参阅 errno、_doserrno、_sys_errlist 和 _sys_nerrFor more information about these and other return codes, see errno, _doserrno, _sys_errlist, and _sys_nerr.

备注Remarks

_Pipe函数创建管道,即程序用于将信息传递给其他程序人工 I/O 通道。The _pipe function creates a pipe, which is an artificial I/O channel that a program uses to pass information to other programs. 管道类似于文件,因为它具有文件指针或文件描述符,或者两者兼具,并且可以通过使用标准库输入和输出函数读取或写入。A pipe resembles a file because it has a file pointer, a file descriptor, or both, and it can be read from or written to by using the Standard Library input and output functions. 但是,管道不表示特定的文件或设备。However, a pipe does not represent a specific file or device. 相反,它表示存储器中独立于程序自身内存的临时存储,并且完全由操作系统控制。Instead, it represents temporary storage in memory that is independent of the program's own memory and is controlled entirely by the operating system.

_pipe类似于 _open但打开用于读取和写入管道并返回两个文件而不是一个描述符。_pipe resembles _open but opens the pipe for reading and writing and returns two file descriptors instead of one. 程序可以使用管道的两端或关闭它不需要的一端。The program can use both sides of the pipe or close the one that it doesn't need. 例如,在 Windows 命令处理器创建的管道,如执行命令时PROGRAM1 | PROGRAM2For example, the command processor in Windows creates a pipe when it executes a command such as PROGRAM1 | PROGRAM2.

标准输出的描述符PROGRAM1附加到管道的写入描述符。The standard output descriptor of PROGRAM1 is attached to the pipe's write descriptor. 标准输入的描述符PROGRAM2附加到管道的读取描述符。The standard input descriptor of PROGRAM2 is attached to the pipe's read descriptor. 这消除了创建临时文件以将信息传递给其他程序的需要。This eliminates the need to create temporary files to pass information to other programs.

_Pipe函数返回到管道中的两个文件描述符pfd自变量。The _pipe function returns two file descriptors to the pipe in the pfds argument. 元素pfd[0] 包含的元素和读取的描述符, pfd[1] 包含写入描述符。The element pfds[0] contains the read descriptor, and the element pfds[1] contains the write descriptor. 管道文件描述符的使用方式与其他文件描述符相同。Pipe file descriptors are used in the same way as other file descriptors. (低级别的输入和输出函数阅读 (_r)_write可以读取和写入到管道。)要检测的最终的管道条件,请检查阅读 (_r) 返回读取的字节数为 0 的请求。(The low-level input and output functions _read and _write can read from and write to a pipe.) To detect the end-of-pipe condition, check for a _read request that returns 0 as the number of bytes read.

Psize参数指定的内存量,以字节为单位,来保留用于管道。The psize argument specifies the amount of memory, in bytes, to reserve for the pipe. Textmode参数指定管道的转换模式。The textmode argument specifies the translation mode for the pipe. 清单常量 _O_TEXT指定文本进行转换时和常量 _O_BINARY指定二进制平移。The manifest constant _O_TEXT specifies a text translation, and the constant _O_BINARY specifies binary translation. (有关文本和二进制模式的说明,请参阅 fopen、_wfopen。)如果textmode自变量为 0, _pipe使用由默认模式变量指定的默认转换模式_fmode(See fopen, _wfopen for a description of text and binary modes.) If the textmode argument is 0, _pipe uses the default translation mode that's specified by the default-mode variable _fmode.

在多线程程序中,未执行任何锁定。In multithreaded programs, no locking is performed. 返回的文件描述符新打开,并且不应由后任何线程之前引用 _pipe调用已完成。The file descriptors that are returned are newly opened and should not be referenced by any thread until after the _pipe call is complete.

若要使用 _pipe函数父进程和子进程之间进行通信,每个进程必须具有只有一个描述符管道上打开。To use the _pipe function to communicate between a parent process and a child process, each process must have only one descriptor open on the pipe. 描述符必须是相对的:如果父级打开了一个读取描述符,那么子级必须打开一个写入描述符。The descriptors must be opposites: if the parent has a read descriptor open, then the child must have a write descriptor open. 若要这样做最简单方法是为按位或 (|) _O_NOINHERIT标志与textmodeThe easiest way to do this is to bitwise or (|) the _O_NOINHERIT flag with textmode. 然后,使用 _dup_dup2若要创建要将传递给子的管道描述符的可继承副本。Then, use _dup or _dup2 to create an inheritable copy of the pipe descriptor that you want to pass to the child. 关闭原始描述符,然后生成子进程。Close the original descriptor, and then spawn the child process. 从生成调用返回时,关闭父进程中的重复描述符。On returning from the spawn call, close the duplicate descriptor in the parent process. 有关详细信息,请参见本文后续部分的示例 2。For more information, see example 2 later in this article.

在 Windows 操作系统中,关闭管道的所有描述符时,该管道也就被损坏了。In the Windows operating system, a pipe is destroyed when all of its descriptors have been closed. (如果管道上的所有读取描述符都已关闭,则写入该管道操作将导致错误。)管道上的所有读取和写入操作都需要等待,直到有足够的数据或足够的缓冲区空间来完成 I/O 请求。(If all read descriptors on the pipe have been closed, then writing to the pipe causes an error.) All read and write operations on the pipe wait until there is enough data or enough buffer space to complete the I/O request.

要求Requirements

例程Routine 必需的标头Required header 可选标头Optional header
_pipe_pipe <io.h><io.h> <fcntl.h>,1 <errno.h>2<fcntl.h>,1 <errno.h>2

1 有关 _O_BINARY_O_TEXT定义。1 For _O_BINARY and _O_TEXT definitions.

2 errno定义。2 errno definitions.

有关更多兼容性信息,请参阅 兼容性For more compatibility information, see Compatibility.

Libraries

C 运行时库的所有版本。All versions of the C run-time libraries.

示例 1Example 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.

示例 2Example 2

这是一个基本的筛选器应用程序。This is a basic filter application. 它在创建了一个将生成的应用程序的 stdout 指向筛选器的管道后,会生成应用程序 crt_pipe_beeper。It spawns the application crt_pipe_beeper after it creates a pipe that directs the spawned application's stdout to the filter. 筛选器删除 ASCII 7(蜂鸣)字符。The filter removes ASCII 7 (beep) characters.

// 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;
}

实际的筛选器应用程序:The actual filter application:

// 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...

请参阅See also

进程和环境控制Process and Environment Control
_open、_wopen_open, _wopen