0

I have the following hw problem:

Read the man page of pipe system call. 2 partially completed programs have been provided to help teach you pipes.

For this lab you are to create an output identical to that of lab 5(x-5, x/5, etc.). This time you are using pipes though. Since pipes have a built in mechanism for process control, you only need to use 2 processes, each which loop 5 times (instead of creating a new process every time you loop). Wait then won’t work for this lab. If you need help controlling process order, try using the system call sleep(). Following is a sample output that will be printed to the screen/terminal.

Below is a sample output:

x = 19530
Iteration 1
Child: x = 19525
Parent: x = 3905
Iteration 2
Child: x = 3900
Parent: x = 780
Iteration 3
Child: x = 775
Parent: x = 155
Iteration 4
Child: x = 150
Parent: x = 30
Iteration 5
Child: x = 25
Parent: x = 5

My output is the following:

x = 19530

Parent read failed
ITERATION 0
Child, read failed

I have the following code below, but for some reason my system calls keep returning negative 1 at the beginning of the loops in the parent and child processes and I don't understand why. Can anyone explain? I am on Ubuntu 16.04 linux.

// Pipe practice
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<sys/types.h>
#include<iostream>
#include<fcntl.h>
using namespace std;

int main()
{

    int x = 19530; // Original input
    size_t XSIZE = sizeof(x); // sizeo of the original input
    cout << "x = " << x << endl << endl; // first line of test output

    int child[2]; // for child pipe
    int parent[2]; // for parent pipe
    pid_t ID; // for fork() later
    ssize_t check; // ssize_t type for error checking

// opening the pipes, error handling
    if ((pipe(child)) < 0)
    { // child pipe
        cout << "Child has no pipe\n";
        return 1;
    }

    if ((pipe(parent)) < 0)
    { // parent pipe
        cout << "Parent has no pipe\n";
        return 1;
    }
// initial write to parent pipe
    if ((check = write(parent[1], &x, XSIZE)) <= 0)
    { // swap first 2 params q
        cout << "Pre-write failed\n";
        return 1;
    }

    ID = fork(); // forking, each fork will have two loops which iterate 5 times passing values back and forth
    if (ID < 0)
    {
        cout << "Fork failed \n"; // error handling for fork
        return 1;
    }

    else if (ID == 0)
    { // child does x = x-5
        for (int i = 0; i < 5; i++)
        {
            check = 0; // sets check to 0 each time to prevent error
            cout << "ITERATION " << i << endl;
            if ((check = read(parent[1], &x, XSIZE)) < 0)
            { // read the new value of x into x from parent[1]
                cout << "Child, read failed \n";
                return 1;
            }
            x = x - 5; // do the subtraction
            if ((check = write(child[1], &x, XSIZE)) < 0)
            { // write the new value into child[1] for piping for parent
                cout << "Child, write failed \n";
                return 1;
            }
            cout << "Child : x = " << x << endl;
        }
    }

    else
    { // parent does x = x/5
        for (int i = 0; i < 5; i++)
        {
            check = 0; // again, error prevention
            if ((check = read(child[1], &x, XSIZE)) < 0)
            { // read new x value from child[1]
                cout << "Parent read failed \n";
                return 1;
            }
            x = x / 5; // do division
            if ((check = write(parent[1], &x, XSIZE)) < 0)
            {
                cout << "Parent write failed \n"; // write new value to parent[1] for piping back to child
                return 1;
            }
            cout << "Parent : x = " << x << endl << endl;
        }
    }
    return 0;
}

Edit Now my output is following:

x = 19530

ITERATION 1
Child : x = 19525
ITERATION 2
Child : x = 3900
ITERATION 3
Parent : x = 3905

Parent : x = 780

Child : x = 775
ITERATION 4
Parent : x = 155

Child : x = 150
ITERATION 5
Parent : x = 30

Child : x = 25
Parent : x = 5

2
  • 2
    Lot of system calls in there, ol' Hoss. Care to expand on which system calls are giving you grief? Commented Mar 13, 2017 at 22:26
  • @user4581301 sure, I've editted it into my question. But specifically the calls inside of the loops. Both of the read() return -1. And I can't understand why that is happening.
    – Callat
    Commented Mar 13, 2017 at 22:31

1 Answer 1

2

You are confused about how pipes work. pipe returns back two file descriptors. The first one (index 0) is the read end and the second one (index 1) is the write end.

So calls like:

 check = read(parent[1], &x, XSIZE)

are always going to fail since they are attempting to read from the write end. To fix, just change the index:

 check = read(parent[0], &x, XSIZE)

You need to do the same where you are attempting to read using child[1]

3
  • This fixes my problem but now the iteration count is all over the place, please see above.
    – Callat
    Commented Mar 13, 2017 at 22:55
  • This fixes my problem but now the iteration count is all over the place, please see above. Basically the iteration count is not following the same print order as the other two print statements. I think it's because of it's lack of dependance on the read and write calls. Any idea how to work that in?
    – Callat
    Commented Mar 13, 2017 at 23:01
  • nevermind! I solved it! Thank you so much for the pipe explanation, I never would have gotten around that bug.
    – Callat
    Commented Mar 13, 2017 at 23:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.