Reputation: 11
I´m having troubles to understand how pipes and fork work together for a online course. Firstly, I want to type two strings below a printf and the when all read/write end cat both string into one. I´m stuck in the read/write for both childs, the problems is that it didn´t match what I want because first print the strings and then open the channel to type. Maybe this is a small matter but I am starting using C for a online course. read and write function are compulsory.
String 1:
sdfsdfsdf
String 2:
Sdfsdfdsfsdfsd
String cat:
sdfsdfsdfSdfsdfdsfsdfsd
here is my code so far.
int main()
{
int fd1[2],fd2[2];
int status, pid;
pipe(fd1);
printf("String 1: \n");
pid = fork();
if(pid == 0) /* child 1*/
{
close(fd1[0]);
char cad1[100];
read(0,&cad1,100);
write(fd1[1],&cad1, 100);
close(fd1[1]);
exit(0);
}
else /* father*/
{
close(fd1[1]);
printf("String 2: \n");
pipe(fd2);
pid = fork();
if(pid == 0) /* child 2 */
{
close(fd2[0]);
close(fd1[0]);
char cad2[100];
read(0,&cad2,100);
write(fd2[1],&cad2, 100);
close(fd2[1]);
exit(0);
}
}
close(fd2[0]);
/* wait every child */
wait(&status);
wait(&status);
return 0;
}
My output is like this:
String 1:
String 2:
cvbcvbcvbcvb
cvbcvbcvbcvb
To cat my code (not implemented in the code I think to call both pipe into to char [] variable before cat.
Any suggestion to improve my code. Thanks in advance.
Upvotes: 0
Views: 698
Reputation: 754900
Here's my code, based loosely on yours. As I said in a comment, the parent code needs to read from the two pipes to collect the data from the children, and then concatenate them. You need to pay attention to how many bytes are read so that you don't write more bytes than were read. The second child should close both fd1[0]
and fd1[1]
as it will use neither of them. You'll need to worry about newlines and null bytes — the information returned by read()
is not a string and will include the newline.
I opted to use fgets()
to read from standard input since it does return a string and zapped the newlines. I wrote some information to standard output, too. The concatenated string is created using snprintf()
.
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static inline void syserr_exit(const char *fmt, ...)
{
va_list args;
int errnum = errno;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
int main(void)
{
int fd1[2], fd2[2];
int pid1, pid2;
if (pipe(fd1) < 0 || pipe(fd2) < 0)
syserr_exit("Failed to create two pipes: ");
else if ((pid1 = fork()) < 0)
syserr_exit("Failed to fork() child 1: ");
else if (pid1 == 0)
{
/* Child 1*/
close(fd1[0]);
close(fd2[0]);
close(fd2[1]);
char cad1[100];
printf("String 1: \n");
fflush(stdout);
if (fgets(cad1, sizeof(cad1), stdin) == NULL)
syserr_exit("child 1 - failed to read from standard input: ");
cad1[strcspn(cad1, "\r\n")] = '\0';
write(fd1[1], cad1, strlen(cad1));
/* Should error check the write! */
printf("child 1 wrote [%s] to the parent process\n", cad1);
close(fd1[1]);
exit(0);
}
else if ((pid2 = fork()) < 0)
syserr_exit("Failed to fork child 2: ");
else if (pid2 == 0)
{
/* Child 1*/
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
printf("String 2: \n");
fflush(stdout);
char cad2[100];
if (fgets(cad2, sizeof(cad2), stdin) == NULL)
syserr_exit("child 2 - failed to read from standard input: ");
cad2[strcspn(cad2, "\r\n")] = '\0';
write(fd2[1], cad2, strlen(cad2));
/* Should error check the write! */
printf("child 2 wrote [%s] to the parent process\n", cad2);
close(fd2[1]);
exit(0);
}
else
{
/* Parent */
char buffer1[100];
char buffer2[100];
close(fd2[1]);
close(fd1[1]);
ssize_t sz1 = read(fd1[0], buffer1, sizeof(buffer1));
buffer1[sz1] = '\0';
close(fd1[0]);
ssize_t sz2 = read(fd2[0], buffer2, sizeof(buffer2));
buffer2[sz2] = '\0';
close(fd2[0]);
size_t tlen = sz1 + sz2 + sizeof("[]+[]");
char concat[tlen];
snprintf(concat, sizeof(concat), "[%s]+[%s]", buffer1, buffer2);
/* wait for both children */
int s1, s2;
int c1 = wait(&s1);
int c2 = wait(&s2);
printf("The one child (%d) exited with status 0x%.4X\n", c1, s1);
printf("T'other child (%d) exited with status 0x%.4X\n", c2, s2);
printf("Received from %d (%zu bytes) [[%s]]\n", pid1, sz1, buffer1);
printf("Received from %d (%zu bytes) [[%s]]\n", pid2, sz2, buffer2);
printf("Concatenated data: <<%s>>\n", concat);
}
return 0;
}
One sample run yielded:
$ ./pipe43
String 1:
String 2:
Vultures keep the world clean.
child 2 wrote [Vultures keep the world clean.] to the parent process
Hypersonic transport planes are as ubiquitous as pink elephants
child 1 wrote [Hypersonic transport planes are as ubiquitous as pink elephants] to the parent process
The one child (69005) exited with status 0x0000
T'other child (69004) exited with status 0x0000
Received from 69004 (63 bytes) [[Hypersonic transport planes are as ubiquitous as pink elephants]]
Received from 69005 (30 bytes) [[Vultures keep the world clean.]]
Concatenated data: <<[Hypersonic transport planes are as ubiquitous as pink elephants]+[Vultures keep the world clean.]>>
$
Upvotes: 1