Pipe: How do I ensure if I successfully write into the pipe? - c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#define SIZE 50
struct record {
int freq;
char word[SIZE];
};
int main(){
int number_process = 3;
int pipes[number_process][2];
struct record r1;
r1.freq = 10;
strcpy(r1.word, "Cat");
struct record r2;
r2.freq = 20;
strcpy(r2.word, "Elephant");
struct record r3;
r3.freq = 30;
strcpy(r3.word, "Dragon");
struct record records_array[3] = {r1, r2, r3};
for (int i = 0; i < number_process; i++){
if (pipe(pipes[i]) == -1){
perror("pipe");
exit(1);
}
// Create children.
pid_t fork_result = fork();
if (fork_result == -1){
perror("Parent fork");
exit(1);
} else if (fork_result == 0){
if (close(pipes[i][0]) == -1){
perror("Child closes reading port");
exit(1);
}
// Later children is going to close all reading port from pipe that parent creates.
for (int child_no = 0; child_no < i; child_no++) {
if (close(pipes[child_no][0]) == -1) {
perror("close reading ends of previously forked children");
exit(1);
}
}
// Now, I am trying to write each strct record member from the above array into the pipe
// when I run the program, it won't allow me to do so because of bad file descriptor exception.
for (int j = 0; j < number_process; i++){
if (write(pipes[i][1], &(records_array[j]), sizeof(struct record)) == -1){
perror("write from child to pipe");
exit(1);
}
}
// Finishing writing, close the writing end in pipe.
if (close(pipes[i][1]) == -1){
perror("Child closes writing port");
exit(1);
}
// Terminate the process.
exit(0);
} else {
// Parent is closing all the writing ends in pipe.
if (close(pipes[i][1]) == -1){
perror("Parent close writing");
exit(1);
}
}
}
struct record buffer;
for (int i = 0; i < number_process; i++){
// Parent reads from the pipe.
if (read(pipes[i][0], &buffer, sizeof(struct record)) == -1){
perror("parent read");
exit(1);
}
printf("buffer.freq = %d\n", buffer.freq);
printf("buffer.word = %s\n", buffer.word);
}
return 0;
}
I am new to system programming, the following code is some practice I implement to see the pipe functionality. I have a few questions to my code:
1) Is there any system call or library call that will help me to ensure the content that I want to write into the pipe has actually been successfully written into the pipe? In other words, is there any methods available for me to check the content/data I wrote into the pipe?
2) I feel my parent reading part is not implemented correct, when I run this code, my parent reading part reads consecutive 3 same things, although it should be different things each time it read.
3) I have confronted the bad addresses issue when I try to read something from the pipe in my parent process, what is the reason that this error occurs?
Can someone please help me understand this stuff? Really appreciated.

You've got a simple cut-n-paste error. for (int j = 0; j < number_process; i++){
You need to increment j.

Related

Pipe: Bad file descriptors

I know this kind of posts have been asked previously, but their level are clearly higher than mind, I still don't get it after reading their post, so I decide to post this question again from here.
I am learning multi-processes communication using pipe, I have confronted to this error called Bad file descriptors, I don't understand why I am having this error in my code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#define SIZE 50
struct record {
int freq;
char word[SIZE];
};
int main(){
int number_process = 3;
int pipes[number_process][2];
struct record r1;
r1.freq = 10;
strcpy(r1.word, "Cat");
struct record r2;
r2.freq = 20;
strcpy(r2.word, "Elephant");
struct record r3;
r3.freq = 30;
strcpy(r3.word, "Dragon");
struct record records_array[3] = {r1, r2, r3};
for (int i = 0; i < number_process; i++){
if (pipe(pipes[i]) == -1){
perror("pipe");
exit(1);
}
// Create children.
pid_t fork_result = fork();
if (fork_result == -1){
perror("Parent fork");
exit(1);
} else if (fork_result == 0){
if (close(pipes[i][0]) == -1){
perror("Child closes reading port");
exit(1);
}
// Later children is going to close all reading port from pipe that parent creates.
for (int child_no = 0; child_no < i; child_no++) {
if (close(pipes[child_no][0]) == -1) {
perror("close reading ends of previously forked children");
exit(1);
}
}
// Now, I am trying to write each strct record member from the above array into the pipe
// when I run the program, it won't allow me to do so because of bad file descriptor exception.
for (int j = 0; j < number_process; i++){
if (write(pipes[i][1], &(records_array[j]), sizeof(struct record)) == -1){
perror("write from child to pipe");
exit(1);
}
}
// Finishing writing, close the writing end in pipe.
if (close(pipes[i][1]) == -1){
perror("Child closes writing port");
exit(1);
}
// Terminate the process.
exit(0);
} else {
// Parent is closing all the writing ends in pipe.
if (close(pipes[i][1]) == -1){
perror("Parent close writing");
exit(1);
}
}
}
return 0;
}
When I finish compiling and run the executable, it just tells me bad file descriptors occurs. I tried to use gdb to take a closer look at where this error might occur, and I notice that gdb reports this error even before I call write().
I feel completely lost in this write and pipe concept, can someone kindly please explain to me what I did wrong somewhere in the process?
Your issue has nothing to do with any of the system calls you're using. It is more mundane. for (int j = 0; j < number_process; i++) is a bug. You are using i to access your array of file descriptors and incrementing it incorrectly. You meant to increment j.

C - dup2() not executing

This is my first question so I apologize if I'm omitting anything important. So I've been working on an assignment that handles piping via forking. My code is pretty messy, littered with printf statements so I see what's going on.
I've looked around online and I think I get the idea of how to handle piping, but the problem I'm having is that my code skips dup2() on any file descriptor except inFD and outFD.
Here's the code for my function. Also, from what I understand, my teacher made a macro called CHK which checks for errors. If there is an error (such as dup2 returning -1), it'll terminate with a print to stderr.
My includes, global variables and myhandler() for signal
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <strings.h>
#include <math.h>
#include <signal.h>
// Function calls
void parse(char *w, char **ptrArray, char *inArray, char *outArray, int *pipeArray);
int flagHandler(char **ptrArray, char *inArray, char *outArray);
int pipeHandler(char **ptrArray, char *inArray, char *outArray, int *pipeArray);
// Global Variables
const int STORAGE = 254;
const int MAXITEM = 100;
int inFD; // file descriptor for <
int outFD; // file descriptor for >
int complete = 0; // for sighandler
int readDes = 0;
int writeDes = 1;
int numPipes = 0;
int status;
int forCounter = 0;
int fildes[4];
int pipeIndex = 0;
// MetaChar flags
int lessthanSign = 0; // < flag
int greaterthanSign = 0; // > flag
int firstChildFlag = 0;
int lastChildFlag = 0;
void myhandler(int signum)
{
complete = 1;
}
My main function
int main()
{
char s[STORAGE]; // array of words
char *newargv[MAXITEM];
char inArray[STORAGE]; // for <
char outArray[STORAGE]; // for >
int firstCheck;
int pidBackground; // holds value from fork(), used for background calls
struct stat st; // for stat(), checks if file exists
// dynamic array based on numPipes
// first child doesn't use this array, as it uses newargv[0] and newargv
// only the middle children and last child use this array, hence 10
int *pipeArray = malloc(10 * sizeof(int));
int numLoops = 0;
int i = 0;
signal(SIGTERM, myhandler);
for(;;)
{
// Reset flags here
lessthanSign = 0;
greaterthanSign = 0;
pipeSign = 0;
firstChildFlag = 0;
lastChildFlag = 0;
pipeIndex = 0;
parse(s, newargv, inArray, outArray, pipeArray);
pipeHandler(newargv, inArray, outArray, pipeArray);
wait(NULL);
fflush(NULL);
} // end for
printf("Entering killpg; numLoops = %d\n", numLoops);
killpg(getpid(), SIGTERM);
printf("p2 terminated.\n");
exit(0);
} // end main
Main calls parse which fills in newargv[]. It also fills in inArray[] and outArray[] with the string immediately after a < and > respectively. When detecting a pipe sign, it puts a null on newargv[], as well as putting a value in pipeArray[] for indexing the executable's name in newargv. I omitted the parse() and flagHandler() calls to keep it minimal.
My parseHandler() function
int pipeHandler(char **ptrArray, char *inArray, char *outArray, int *pipeArray)
{
pid_t firstChild;
pid_t firstChildBackground;
pid_t middleChild;
pid_t lastChild;
pid_t lastChildBackground;
int i = 0; // plain integer for for loops
printf("Initializing pipes\n");
//pipe(fildes);
//pipe(fildes + 2);
for (i = 0; i < (2*numPipes); i+=2)
{
printf("pipe initializing; i is %d\n", i);
if (pipe(fildes + i) < 0)
{
perror("pipe initialization failed");
exit(EXIT_FAILURE);
}
}
fflush(stdout);
if ((firstChild = fork()) < 0)
{
perror("First child's fork failed!");
exit(EXIT_FAILURE);
}
printf("firstChild pid = %d\n", getpid());
if (firstChild == 0)
{
if (firstChildFlag == 1)
{
printf("inFD = open...\n");
inFD = open(inArray, O_RDONLY);
printf("Doing dup2 inFD\n");
if (dup2(inFD, STDIN_FILENO) < 0)
{
perror("First child's < dup2 failed");
exit(EXIT_FAILURE);
}
}
printf("doing dup2 fildes[writeDes]\n");
if (dup2(fildes[writeDes], STDOUT_FILENO) < 0)
{
perror("First child's dup2 failed");
exit(EXIT_FAILURE);
}
printf("*****doing dup2 fildes[writeDes] was a success!\n");
for (i = 0; i < 4; i++)
{
if (close(fildes[i]) < 0)
{
perror("close failed");
exit(EXIT_FAILURE);
}
}
if (firstChildFlag == 1)
{
lessthanSign = 0;
firstChildFlag = 0;
if (close(inFD) < 0)
{
perror("close inFD failed");
exit(EXIT_FAILURE);
}
}
writeDes += 2;
printf("About to execvp first child\n");
if (execvp(ptrArray[0], ptrArray) < 0)
{
perror("execvp failed");
exit(EXIT_FAILURE);
}
}
else
{
fflush(stdout);
if ((middleChild = fork() < 0))
{
perror("Middle child's fork failed");
exit(EXIT_FAILURE);
}
printf("middleChild pid = %d\n", getpid());
if (middleChild == 0)
{
if (dup2(fildes[readDes], STDIN_FILENO) < 0)
{
perror("Middle child's dup2 on reading failed");
exit(EXIT_FAILURE);
}
if (dup2(fildes[writeDes], STDOUT_FILENO) < 0)
{
perror("Middle child's dup2 on writing failed");
exit(EXIT_FAILURE);
}
for (i = 0; i < 4; i++)
{
if (close(fildes[i]) < 0)
{
perror("close failed");
exit(EXIT_FAILURE);
}
}
readDes += 2;
writeDes += 2;
if (execvp(ptrArray[pipeArray[0]], ptrArray + pipeArray[0]) < 0)
{
perror("Middle child's execvp failed");
exit(EXIT_FAILURE);
}
}
else
{
fflush(stdout);
if ((lastChild = fork() < 0))
{
perror("Last child's fork failed");
exit(EXIT_FAILURE);
}
printf("lastChild pid = %d\n", getpid());
if (lastChild == 0)
{
if (dup2(fildes[readDes], STDOUT_FILENO) < 0)
{
perror("Last child's dup2 on reading failed");
exit(EXIT_FAILURE);
}
if (lastChildFlag == 1)
{
outFD = open(outArray, O_CREAT | O_RDWR, 0400 | 0200);
if (dup2(outFD, STDOUT_FILENO) < 0)
{
perror("Last child's > dup2 failed");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < 4; i++)
{
if (close(fildes[i]) < 0)
{
perror("close failed");
exit(EXIT_FAILURE);
}
}
if (lastChildFlag == 1)
{
greaterthanSign = 0;
lastChildFlag = 0;
if (close(outFD) < 0)
{
perror("close on outFD failed");
exit(EXIT_FAILURE);
}
}
printf("Execvp last child\n");
if (execvp(ptrArray[pipeArray[1]], ptrArray + pipeArray[1]) < 0)
{
perror("Last child's execvp failed");
exit(EXIT_FAILURE);
}
printf("Last child execvp finished\n");
}
}
}
// Only the parent gets here
printf("Only the parent should be here\n");
printf("My pid is %d\n", getpid());
for (i = 0; i < 4; i++)
{
if (close(fildes[i]) < 0)
{
perror("close failed");
exit(EXIT_FAILURE);
}
}
for (;;)
{
pid_t pid;
if (pid = wait(NULL) < 0)
{
perror("wait failed");
exit(EXIT_FAILURE);
}
if (pid == lastChild)
{
printf("Parent is waiting for lastChild\n");
break;
}
}
printf("Parent finished waiting. Returning...\n");
return 0;
}
I did pipe(fildes) before any fork, so that all children and a parent have their copy. Therefore, I must close all file descriptors in each child (after dup2 but before execvp) and the parent. The parent will then wait until it gets the pid of lastChild.
With a lot of printf statements, I have found that no child does the dup2() command (except for dup2(inFD...) and dup2(outFD...) when the flags are appropriate). There is also no error printed.
I printed out my (char) newargv[] and my (int) pipeArray[] and they contain the correct values. It seems to be just the dup2 problem, and I have absolutely no idea what's going wrong with it.
I made a simple text file called test2 containing
ls | sort | cat someString
Where someString is just a file with some text. With all the print statements in the pipeHandler() function my output is:
EDIT: I fixed a couple typos I had. I forgot to lace an extra set of parenthesis on 3 ifs, if ((firstChild = fork()0 < 0)
I now have an infinite loop as the parent is waiting for the lastChild's pid. Here's the output:
Initializing pipes
numpipes = 2
pipe initializing; i is 0
pipe initializing; i is 2
firstChild pid = 20521
firstChild pid = 20522
doing dup2 fildes[writeDes]
middleChild pid = 20521
middleChild pid = 20523
lastChild pid = 20521
Only the parent should be here
My pid is 20521
lastChild pid = 20524
<infinite loop>
I'm still clueless though as to what's going on or what's potentially stopping the child.
#MarkPlotnick you're right! It's not that dup2 isn't executing or anything. Because I did dup2(fildes[1], STDOUT_FILENO), all print statements will be piped.
I fixed the typo mentioned as well. I tried my teacher's test file
< input1 cat|>your.outputc tr a-z A-Z | tr \ q
Which should result with a file called your.outputc. It does, and the contents are input1 with the effects of tr. However, I also have the printf statements at the top of this file.
I assumed the dup2 wasn't working because no printf statement followed, unlike it did in dup2(inFD, STDIN_FILENO), but that's probably because it was STDIN.

C Using pipes to transfer data to write to file using shared memory

I am trying to use pipes in C. I have two create two pipes between parent and child process.I have to read a file in chunks of 4096 bytes (or smaller if there is less) and I have to send through the pipes the amount of data that was read and how many times there have been readings. For example, to copy a 6KB
file, the parent writes the first 4KB data of the file to the shared memory and send two integers, 1 and 4096, to the child via the pipe. The child receives these two numbers, copies 4096 bytes from the shared memory to the output file, and sends back 1 to the parent via the other pipe. After receiving 1,
the parent copies the left 2KB data to the shared memory and send 2 and 2048 to the child. The child receives them from the pipe, copies 2048 bytes to the output file, and replies with 2 to the parent. The parent then send 0, 0 to the child. The child receives 0 and replies with a 0 and then exit. The parent
receives 0 and exits too.
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define SIZE 4096
#define NUM_OF_PIPES 2
#define P_READ 0
#define P_WRITE 1
#define C_READ 2
#define C_WRITE 3
int main(int argv, char *argc[]) {
/*Check if program is called correctly*/
if(argv != 3) {
printf("Please call program appropriately\n");
exit(EXIT_FAILURE);
}
FILE *r, *w, *check;
void *sharedMem;
int pipes[4];
int shm;
char userInput[5];
char *name = "dm11ad_cop4610";
int inChild = 0;
int inParent = 0;
r = fopen(argc[1], "rb");
check = fopen(argc[2], "rb");
/*Check if read file can open*/
if(r == NULL) {
perror("Error opening read file");
exit(EXIT_FAILURE);
}
/*Check if write file can open*/
if(check == NULL) {
perror("Error with write file");
exit(EXIT_FAILURE);
}
else {
fseek(check, 0, SEEK_END);
int writeLen = ftell(check);
if(writeLen > 0) {
rewind(check);
printf("Would you like to overwrite file (yes/no): ");
scanf("%s", userInput);
if(!strcmp(userInput, "yes")) {
printf("Overwriting file...\n");
w = fopen(argc[2], "wb");
}
else if(!strcmp(userInput, "no")) {
printf("Will not overwrite\n");
exit(EXIT_FAILURE);
}
else {
printf("User input not accepted\n");
exit(EXIT_FAILURE);
}
}
}
for (int i = 0; i < NUM_OF_PIPES; i++) {
if (pipe(pipes+(i*2)) < 0) {
perror("Pipe");
exit(EXIT_FAILURE);
}
}
/*Check if forking process is successful*/
pid_t pid = fork();
if(pid < 0) {
perror("Fork");
exit(EXIT_FAILURE);
}
shm = shm_open(name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if(shm == -1) {
perror("Shared memory");
exit(EXIT_FAILURE);
}
if(ftruncate(shm, SIZE) == -1) {
perror("Shared Memory");
exit(EXIT_FAILURE);
}
sharedMem = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if(sharedMem == MAP_FAILED) {
perror("Mapping shared memory");
exit(EXIT_FAILURE);
}
if(pid == 0) {
while(inParent);
inChild = 1;
printf("I am in child\n");
close(pipes[P_READ]);
close(pipes[P_WRITE]);
printf("Closed P pipes\n");
int cBytes, len;
printf("Im stuck\n");
len = read(pipes[C_READ], &cBytes, sizeof(cBytes));
printf("There are %i bytes\n", len);
if(len < 0) {
perror("Failed to read from pipe");
exit(EXIT_FAILURE);
}
else if(len == 0) {
printf("End of fle reached\n");
}
else {
printf("Writing to file\n");
fwrite(sharedMem, 1, sizeof(sharedMem), w);
}
printf("Closing C pipes\n");
close(pipes[C_READ]);
close(pipes[C_WRITE]);
printf("Exiting Child\n");
inChild = 0;
}
else {
while(inChild);
inParent = 1;
close(pipes[C_READ]);
close(pipes[C_WRITE]);
int pBytes;
int P2SHM = fread(sharedMem, 1, SIZE, r);
if(P2SHM < 0) {
perror("Could not store to shared memory");
exit(EXIT_FAILURE);
}
if(write(pipes[P_WRITE], &P2SHM, sizeof(int)) < 0) {
perror("Failed to write to pipe");
exit(EXIT_FAILURE);
}
int C2P = read(pipes[P_READ], &pBytes, sizeof(int));
if(C2P < 0) {
perror("Failed to read value from pipe");
exit(EXIT_FAILURE);
}
else if(C2P == 0) {
printf("End of file reached\n");
}
else {
printf("Received succesfully\n");
}
close(pipes[P_READ]);
close(pipes[P_WRITE]);
inParent = 0;
printf("Waiting for child\n");
wait(NULL);
}
return 0;
}
The printfs are there to help me see where the program is during execution. It gets stuck in child process, it seems during
len = read(pipes[C_READ], &cBytes, sizeof(cBytes));
This is an assignment, so please do not post code as an answer but rather please hep me understand what I am doing wrong. Thanks
Synchronization mechanism between child and parent looks suspicious:
while(inParent);
inChild = 1;
and
while(inChild);
inParent = 1;
Initial values for inChild and inParent is 0. After child process created each process has it's own copy of variable values. When you change inChild = 1 and inParent = 1, it's changed inside the current process only. Other process doesn't see new values and cannot wait for the input/output.
To fix it you should use better synchronization algorithm, e.g. processes semaphores. Read "5.2 Processes Semaphores" to get details.
It gets stuck in child process, it seems during
len = read(pipes[C_READ], &cBytes, sizeof(cBytes));
Well yes, I imagine it does.
You've been a bit too clever, I think, in setting up a single 4-element array for the pipe-end file descriptors. That's not inherently wrong, but it tends to obscure what's going on a bit.
Consider what the pipes are supposed to do for you: one process writes to the write end of a pipe, and the other reads what was written from the read end of that same pipe. Look carefully at which file descriptors each process is reading from and writing to.

daemonize of a process?

I'm learning apue and I try to daemonize a process according to the code sample in apue. The code is as follows:
#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/resource.h>
int damonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
umask(0);
if(getrlimit(RLIMIT_NOFILE, &rl) < 0)
{
return 1;
}
if((pid = fork()) < 0)
{
return 2;
}
else if(pid != 0)
{
exit(0);
}
setsid();
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if(sigaction(SIGHUP, &sa, NULL) < 0)
{
return 3;
}
if((pid = fork()) < 0)
{
return 4;
}
else if(pid > 0)
{
exit(0);
}
if(chdir("/") < 0)
{
return 5;
}
if(rl.rlim_max == RLIM_INFINITY)
{
rl.rlim_max = 1024;
}
for(i = 0; i < rl.rlim_max; i++)
{
close(i);
}
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
openlog(cmd, LOG_CONS, LOG_DAEMON);
if(fd0 != 0 || fd1 != 1 || fd2 != 2)
{
syslog(LOG_ERR, "unexpected file descriptors %d %d %d\n", fd0, fd1, fd2);
return 6;
}
}
int main(void)
{
FILE *fp;
int id;
fp = fopen("test.txt", "w+");
id = damonize("ls");
fprintf(fp, "%d", id);
fclose(fp);
exit(0);
}
I run the above program and use ps -axj, but there's no daemon process created by the program, and threre's no output in the file test.txt. My question is
What's wrong in my code? What causes the above two problems?
You won't see the daemonized process because it doesn't stick around. After it tries writing to the file, it exits.
But it won't write to the file, because your daemonize routine closes every file handle (and that's what fopen() uses under the hood). Try opening the file in main() after daemonize(), or in the loop closing all file descriptors, exclude the one associated with the file using fileno().
I am afraid that your program is oversophisticated (if such a word exists in English). You are spawning one child process, exit parents, then the child spawns another child and exits. The child of the child is then closing all possible (even not opened) file descriptors, then it opens "/dev/null" and redirect standard input, output and error there. The "daemonisation" is finished and your program tries to write some number into a file "fp" in the main function. However, this fp have been closed long time ago in daemonize.
In other words, the main problem is that your daemonize function is closing all possible file descriptors in the loop:
for(i = 0; i < rl.rlim_max; i++) close(i);
However, if you want to daemonize a process why not to start with a simple solution and once it works you can add features while keeping it working. For example if you start with:
int daemonize() {
pid_t pid;
pid = fork();
if (pid > 0) exit(EXIT_SUCCESS);
if (pid < 0) printf("Can't fork\n");
return(pid);
}
Then you can add code for closing standard input close(STDIN_FILENO); before return, and so on. After each modification test if it is still working.

duplicate file descriptor to point to pipe

My program will pick a random number and have the use guess what it is. I am almost done with it, except I need to duplicate the file descriptors to point to a pipe, and I'm not entirely sure how to do that. I think i'd have to use dup2, but I'm not entirely sure how to implement it. Anything helps. Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int pid;
int n;
char buf[101];
int pfdA[2];
int pfdB[2];
// CREATE FIRST PIPE
if (pipe(pfdA) == -1)
{
perror("pipe failed");
exit(-1);
}
// CREATE SECOND PIPE
if (pipe(pfdB) == -1)
{
perror("pipe failed");
exit(-1);
}
// FORK()
if ((pid == fork()) < 0)
{
perror("fork failed");
exit(-2);
}
if (pid == 0)
{
// duplicate file descriptor 0 to point to FIRST pipe
// CLOSE ends of FIRST pipe you don't need anymore
close(pfdA[0]);
close(pdfA[1]);
// duplicate file descriptor 1 to point to SECOND pipe
// CLOSE ends of SECOND pipe you don't need anymore
close(pfdB[0]);
close(pfdB[1]);
execlp("./A5_CHILD", "./A5_CHILD", (char *) 0);
perror("execlp");
exit(-3);
}
else
{
while (1)
{
char NUM[100];
close(pfdA[0]);
close(pfdB[1]);
int r = 0;
printf("Enter a Number: ");
fflush(stdout);
scanf("%s", NUM);
// SEND NUM to Child process
write(pdfA[1], NUM, strlen(NUM));
// READ FROM CHILD THE RESPONSE into the variable buf and
// store the return value from read() into the variable r
r = read(pfdB[0], buf, 100);
if (r > 0)
{
buf[r] = '\0';
printf("%s\n", buf);
fflush(stdout);
}
else
{
printf("[PARENT] Reading from child: read() returned %d\n", r);
break;
}
}
}
return (0);
}
I think i'd have to use dup2, but I'm not entirely sure how to
implement it.
You are right.
// duplicate file descriptor 0 to point to FIRST pipe
dup2(pfdA[0], 0);
...
// duplicate file descriptor 1 to point to SECOND pipe
dup2(pfdB[1], 1);

Resources