I am writing a C program which runs the following Linux command with multiple pipes:
cat myfile1.txt | egrep Computing | wc -l > myfile
My code is as follows:
int p_fd[2];
pid_t childpid, waitReturn;
int pid=1;
int status, i;
pipe(p_fd);
for( i = 1 ; i < 3 ; i++ )
if( childpid = fork() )
break;
else
pid++;
while( childpid != ( waitReturn = wait( &status ) ) )
if( ( waitReturn == -1 ) && ( errno != EINTR ) )
break;
if ( childpid > 0 && pid == 1 ){
printf("%d\n", pid);
int fd;
if ( ( fd= open("myfile", O_CREAT|O_RDWR|O_TRUNC, 00644)) == -1 )
{
printf("Error: Cannot open file in open()\n");
exit(1);
}
close(0);
dup(p_fd[0]);
close(1);
dup(fd);
close(p_fd[0]);
close(p_fd[1]);
close(fd);
execl("/bin/wc", "wc", "-l", NULL);
}else if( childpid > 0 && pid == 2 ){
printf("%d\n", pid);
close(0);
dup(p_fd[0]);
close(1);
dup(p_fd[1]);
close(p_fd[0]);
close(p_fd[1]);
execl("/bin/egrep", "egrep", "Computing", NULL);
}else if( childpid == 0 && pid == 3 ){
printf("%d\n", pid);
close(1);
dup(p_fd[1]);
close(p_fd[0]);
close(p_fd[1]);
execl("/bin/cat", "cat", "myfile1.txt", NULL);
}
return 0;
However, my program hangs when it reaches "execl("/bin/egrep", "egrep", "Computing", NULL);", which is called in the second child with a pid 2.
I do not know the reason why my program hangs there; is it about the pipe's deadlock?
Would anyone could help me to modify the above program so that it can give me the desired result?
How about something like the following pseudo code:
create_pipe_between_cat_and_egrep();
create_pipe_between_egrep_and_wc();
create_destination_file();
if (fork() == 0)
{
/* Process for cat */
setup_pipe_stdout_for_cat();
execl("cat", "cat", "arguments");
}
if (fork() == 0)
{
/* process for egrep */
setup_pipe_stdin_stdout_for_egrep();
execl("egrep", "egrep", "arguments");
}
if (fork() == 0)
{
/* process for wc */
setup_pipe_stdin_for_wc();
setup_file_stdout_for_wc();
execl("wc", "wc", "arguments");
}
wait_for_all_three_child_processes_to_finish();
It's easier to follow the flow with three distinct blocks like above, instead of a loop.
Much of the code can be put in generic functions, like setting up the stdin
/ stdout
descriptors for the child processes.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.