将标准输出放入管道
Put stdout in a pipe
我想知道一个词在不同文件中重复的次数,
为此,我需要使用 fork() 函数并为每个文件创建一个子文件,它将找到这个数字并将不同的结果添加到父文件中。
我成功找到了出现次数,但无法将此信息传达给家长。
我知道我需要使用 pipe 和 dup2。我以前都用过,但分开用过,我不能说我对它们很满意。
正如您在变量 'temp' 中看到的那样,管道是空的。一开始我以为是同步问题,但好像不是这样。我的理解是 dup2(tube[1],1)
将 stdout 放入管道,但我开始怀疑了。
我错过了什么?
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是writer端。所以,你需要关闭子路径中的第一个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 日的编辑:从中间代码版本中删除了一些剩余的内容。阐明了从换行符终止到零终止字符串的转换。
我想知道一个词在不同文件中重复的次数, 为此,我需要使用 fork() 函数并为每个文件创建一个子文件,它将找到这个数字并将不同的结果添加到父文件中。
我成功找到了出现次数,但无法将此信息传达给家长。
我知道我需要使用 pipe 和 dup2。我以前都用过,但分开用过,我不能说我对它们很满意。
正如您在变量 'temp' 中看到的那样,管道是空的。一开始我以为是同步问题,但好像不是这样。我的理解是 dup2(tube[1],1)
将 stdout 放入管道,但我开始怀疑了。
我错过了什么?
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是writer端。所以,你需要关闭子路径中的第一个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 日的编辑:从中间代码版本中删除了一些剩余的内容。阐明了从换行符终止到零终止字符串的转换。