Re: Process Synchronization using Pipes



On Mar 25, 8:45 pm, Barry Margolin <bar...@xxxxxxxxxxxx> wrote:
In article <1174862813.738202.285...@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>,



"Arturo" <arturo.roto...@xxxxxxxxx> wrote:
Hey,

I need to have 4 processes: Producer, Filter1, Filter2 and Consumer.
Producer needs to read data from an input file line by line and pass
each line via a pipe to Filter1 who will replace all " " w/ "*". Once
Filter1 is done it will pass the newly modified line to Filter2.
Filter2 converts all lowercase letters to uppercases. Once Filter2 is
done it will pass the newly modified line to Consumer who simply
writes the line to an output file. This is repeated until the input
file is completely scanned.

I can get this to work w/ one line (no loops), so the first line of
text is completely converted but how do I get a while() loop to work
with this pipe synchronization so that the entire input file is
scanned?

I'd appreciate it if someone can help.

I'm not sure what the problem is. As long as all the processes read
their input line by line until EOF, you should be able to do:

Producer | Filter1 | Filter2 | Consumer

Are you saying that some of these processes only process one line and
then exit? You can change that process to:

{ while read line; do echo "$line" | <process>; done; }

--
Barry Margolin, bar...@xxxxxxxxxxxx
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***


I should have mentioned I'm using C/C++ not shell script. OK so I'll
post the code so you can see how I'm approaching this. I'm a beginner
at this, the code may look a little ugly, but it's just a simple chain
where Producer forks to Filter1 whom forks to Filter2 whom forks to
Consumer.

The problem is ... The while loop seems to only execute once. I don't
understand why, I think it may have to do with close() cause I've
reading about how it deallocates the file descriptor. If this is the
case then how can I solve this?

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
#include <string.h>
#include <ctype.h>
using namespace std;

int main ( int argc , char* argv[] )
{
/* status variables are used with _exit() and wait(), allowing parent
processes
to wait() for its child process to signal it; using "_exit()", when
the
child process is done. There are three status variables one for each
child process */

int status1 , status2 , status3;

/* pipe() creates a pair of file descriptors, pointing to a pipe
inode,
and places them in the array pointed to by fd arrays. fd[0] is for
reading, fd[1] is for writing. */

int fd1[2] , fd2[2] , fd3[2];

/* data from text will be read and written to/from pipelines and
files
using the following char pointers, and the maximum number of
characters is set to 500 */

const int maxChar = 500;
char buffer1[maxChar];
char buffer2[maxChar];

/* The four processes used to synchronize the file manipulation
process */

pid_t Filter1;
pid_t Filter2;
pid_t Consumer;

/* Producer opens an input file */

FILE* filePtr = fopen( "test.txt" , "r" );
if( filePtr == NULL ) perror( "Error opening file");

/* create pipe used for Producer | Filter1 data transfer */

if( pipe( fd1 ) ) perror( "Error creating pipeline" );

while( !feof( filePtr ) )
{
/* Producer forks to Filter1 */

switch( Filter1 = vfork() )
{
/* Parent Process: Producer */

case -1 :

cout << "ERROR FORKING" << endl;
exit( -1 );

/* Child Process: Filter1 */

case 0 :

/* receive data sent by Producer */

close( fd1[1] );
read( fd1[0], buffer2, maxChar );

/* replace all " " w/ "*" */

for( int i = 0 ; i < strlen( buffer2 ) ; i++ ){
if( buffer2[i] == ' ' )
buffer2[i] = '*';}

/* create pipe used for Filter1 | Filter2 data transfer */

if( pipe( fd2 ) ) perror( "Error creating pipeline" );

/* Filter1 forks to Filter2 */

switch( Filter2 = vfork() )
{
/* Parent Process: Filter1 */

case -1 :

cout << "ERROR FORKING" << endl;
exit( -1 );

/* Child Process: Filter2 */

case 0 :

/* receive data sent by Filter1 */

close( fd2[1] );
read( fd2[0], buffer1 , maxChar );

/* convert all lowercases to uppercases */

for( int i = 0 ; i < strlen( buffer1 ) ; i++ ){
if( isalpha( buffer1[i] ) ){
if( islower( buffer1[i] ) )
buffer1[i] = toupper( buffer1[i] );}}

/* create pipe used for Filter2 | Consumer data transfer */

if( pipe( fd3 ) ) perror( "Error creating pipeline" );

/* Filter2 forks to Consumer */

switch( Consumer = vfork() )
{
/* Parent Process: Filter2 */

case -1 :

cout << "ERROR FORKING" << endl;
exit( -1 );

/* Child Process: Consumer */

case 0 :

/* receive data sent by Filter2 */
close( fd3[1] );
read( fd3[0], buffer2 , maxChar );

/* store data received data into an output file */
FILE *outputFile = fopen( "modifiedTest.txt" , "a" );
fputs( buffer2 , outputFile );
fclose( outputFile );
_exit( status3 );

/* Parent Process: Filter2 */

default :

/* send data to Consumer via fd3 */

close( fd3[0] );
write( fd3[1] , buffer1 , strlen( buffer1 ) + 1 );

/* wait for Consumer */

wait( &status3 );
}

_exit( status2 );

/* Parent Process: Filter1 */

default :

/* send data to Filter2 */

close( fd2[0] );
write( fd2[1] , buffer2 , strlen( buffer2 ) + 1 );

/* wait for Filter2 */

wait( &status2 );
}

_exit( status1 );

/* Parent Process: Producer */

default :

/* send data to Filter1 */

close( fd1[0] );
fgets( buffer1 , maxChar , filePtr );
write( fd1[1] , buffer1 , strlen( buffer1 ) + 1 );

/* wait for Filter1 */

wait( &status1 );
}

fclose( filePtr );

}

return 0;

}




.



Relevant Pages

  • Re: Process Synchronization using Pipes
    ... Producer needs to read data from an input file line by line and pass ... Filter1 is done it will pass the newly modified line to Filter2. ... where Producer forks to Filter1 whom forks to Filter2 whom forks to ...
    (comp.unix.programmer)
  • Re: Process Synchronization using Pipes
    ... Producer needs to read data from an input file line by line and pass ... Filter1 is done it will pass the newly modified line to Filter2. ... where Producer forks to Filter1 whom forks to Filter2 whom forks to ...
    (comp.unix.programmer)
  • Re: Process Synchronization using Pipes
    ... I need to have 4 processes: Producer, Filter1, Filter2 and Consumer. ... Producer needs to read data from an input file line by line and pass ...
    (comp.unix.programmer)
  • Process Synchronization using Pipes
    ... I need to have 4 processes: Producer, Filter1, Filter2 and Consumer. ... Producer needs to read data from an input file line by line and pass ...
    (comp.unix.programmer)