问题描述
我想知道一个单词在不同文件中重复的次数, 为此,我需要使用 fork() 函数并为每个文件创建一个子文件,该子文件将找到此数字并将不同的结果添加到父文件中。
我成功找到了出现次数,但无法将此信息传达给父级。
我知道我需要使用管道和 dup2。我之前都使用过它们,但分开使用,我不能说我对它们感到满意。
正如您在变量 'temp' 中看到的那样,管道是空的。起初我以为是同步问题,但似乎并非如此。我的理解是 dup2(tube[1],1)
将标准输出放入管道中,但我开始怀疑。
我想念什么?
int main(int argc,char const *argv[])
{
int tube[2];pipe(tube);int temp;
int s=0;
for (int i = 2; i < argc; i++)
{
if (fork()==0)
{
dup2(tube[1],1);
close(tube[1]);
close(tube[0]);
execlp("grep","grep","-c",argv[1],argv[i],NULL);
}
}
wait(NULL);
for (int i = 2; i < argc; i++) {
{
close(tube[1]);
close(tube[0]);
read(tube[0],&temp,sizeof(int));
printf("temp=%d\n",temp);
s+=temp;
}
}
printf("s=%d",s);
return 0;
}
解决方法
pipie() 之后,返回的第一个文件描述符 (FD) 是管道的reader 端,第二个 FD 是写入端。因此,您需要关闭子路径中的第一个 FD,以及程序的父路径中的第二个 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 日起编辑:从中间代码版本中删除了一些剩余内容。阐明了从换行符终止到零终止字符串的转换。