在 pipie() 之后,返回的第一个文件描述符(FD)是管道的 reader 端,第二个 FD 是 writer 端。因此,您需要关闭子路径中的第一个 FD,以及 pogram 的父路径中的第二个 DF。
您不得关闭父路径中的第一个 FD,因为您希望父路径读取客户端写入的内容。而且您不得关闭子路径中的第二个 FD;否则如何写入管道。
请记住,stdout 被认为是为用户输出的,即 text。因此,您的代码需要接收一个字符串(匹配行数),然后,测试一个有效数字,并将其转换为一个int( long int, long long int),可以总结一下。
此外,在父进程从管道读取数据之前,可能有多个子进程已写入其结果,即一次读取可能会读取多个换行符终止的字符串。
最后,你需要在每个子进程上wait(),否则他们会变成僵尸。
这个问题让我很好奇,所以我试着想出一些工作代码。
//------------------------------------------------------------------------------
//
// The purpose of this program is to find the total number of lines containing
// the specified grep pattern in all the files specified.
//
// Parameters:
// pattern file [ file [ ... ] ]
//
// pattern -> search pattern to be passed to grep
// file -> file(s) to be scanned for "pattern" occurences.
//
//------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main( int argc, char* argv[] ) {
int pipefd[2];
int totalCount = 0;
//----------------------------------------
// Open a pipe to receive the result from
// running "grep" in the child processes.
//----------------------------------------
pipe(pipefd);
//---------------------------------------------------------
// Start a child process for each file given as parameter.
// First file is passed as argument #2.
//---------------------------------------------------------
for ( int ii = 2; ii < argc; ii++ ) {
//------------------------
// This is the child code
//------------------------
if ( fork() == 0 ) {
//-----------------------------
// Redirect stdout to the pipe
//-----------------------------
dup2( pipefd[1], 1 );
//------------------------------------
// Close the reader side of the pipe.
//------------------------------------
close( pipefd[0] );
execlp( "grep", "grep", "-c", argv[1], argv[ii], NULL );
}
}
//-----------------------------------------------------------------------
// This is the parent code.
//
// There possibly is more than one child process writing to the pipe.
// Writes and reads are atomic, however, more than one child may be able
// to write to the pipe before the parent can read.
//-----------------------------------------------------------------------
for ( int ii = 2; ii < argc; ii++ ) {
char result[1024];
int bytesRead;
int ss, pp;
//---------------------------
// Close writer side of pipe
//---------------------------
close( pipefd[1] );
//----------------------------------------------------------
// Read the data that one or more child process has written
//----------------------------------------------------------
bytesRead = read( pipefd[0], &result, sizeof( result ) );
if ( bytesRead > 0 ) {
//---------------------------------------------------------
// One or more *newline terminated* string has been read
// from the pipe, representing the result from one or
// more grep command that has finised.
//
// Each newline terminated string is converted to a zero
// terminated C-sytle string, so that it can be passed to
// atoi().
//---------------------------------------------------------
ss = 0;
for ( pp = 0; pp < bytesRead; pp++ ) {
if ( result[pp] == '\n' ) {
result[pp] = 0x0;
totalCount += atoi( &result[ss] );
ss = pp + 1;
}
}
}
wait( NULL );
}
//-----------------------------------
// Print the final result and return
//-----------------------------------
printf("Total number of matches: %d\n\n", totalCount );
return 0;
}
从 4 月 19 日开始编辑:从中间代码版本中删除了一些剩余部分。阐明了从换行符终止到零终止字符串的转换。