Makestation

Full Version: Pipes, Forks, and IPC
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
So recently, the lady started her Summer semester and has an Operating Systems class going on now.
The professor said they need to use C for the class. The problem is that the computer science faculty doesn't actually TEACH C until like fourth year right before you get your bachelor's, for some reason. Now the professor said that only the first assignment needs to be done in C and the rest can be done in Java.

How you'd do any low-level work with Java is completely beyond me, you can't even pass by reference in the language, let alone fork a process.

But in any case, she knows that C is my favourite language, and as a result, she came running to me when her code wouldn't compile and she needed help getting started with gcc anyway (For Windows, so naturally it would be too f*** for a complete novice to figure out.)




The Assignment and Setup:

The assignment seems really simple. Only a few lines of code. My solution did it in 75 including some whitespace and extra lines for opening curly braces.
In a (very) watered down summary:
Quote:Write a C program that uses fork() to create new processes, and make those processes write data to a pipe, and read that data from the pipe.

Now I didn't read the whole assignment, so I was missing specifics, but her code was really messy (I don't blame her, this was her first C program) and I decided to do a full rewrite.

The first thing I told her after hearing about the assignment and looking at her code is that it would be impossible to do on Windows, since that's what she was trying to do. The main problem lies in the fact that fork() isn't supported on Windows to create new processes. The other problem is that this was asking to use a variety of Linux syscalls that also aren't implemented quite the same way on Windows.

So instead, I ran her through installing Debian under the Windows Subsystem for Linux (WSL) since she has used Debian in the past and was relatively comfortable with it. Then we installed gcc and made sure it was all working correctly. finally, she got WSL setup to be the main command-line in visual Studio Code (the lightweight FOSS text-editor IDE) so she could do all the development in one place.




More Specifics and How I Cheated:

The only familiarity I have with Linux syscalls is with assembly, and using those calls is very different than using them in C. So as a result, there was a pretty big learning curve for me as well

The professor included a main() that would call the desired function so that wouldn't need to be written. It's a messy snippet, but acceptable enough for the task at hand.

I got hold of that main() and started to get to work.

Here's the rough pseudocode that she had so you can get an idea of functionality:

Code:
int main() {
    functionCallForForking(n);
    return 0;
}

void functionCallForForking(int n) {
    if(n == 1) {
        write(Process 1 Started);
        write(Process 1 Ended);
        exit();
    }
    int forks = fork();
    if(child) {
        write(Process n Started);
        functionCallForForking(n-1);
        write(Process n Ended);
    } else if(parent) {
        wait();
        exit();
    } else {
        printf(fork failed);
        exit()
    }
}

Extremely simplified. It was more like 100 lines.
But you can see the pattern. It forks, if it's the child process, it'll fork again, and if it's the parent, it'll wait for the child process to finish.

It should iterate over n processes to start, given by the command line argument which I omitted for simplicity.

Output:
Code:
$ ./a.out 5
Process 5 Started
Process 4 Started
Process 3 Started
Process 2 Started
Process 1 Started
Process 1 Ended
Process 2 Ended
Process 3 Ended
Process 4 Ended
Process 5 Ended
$ _

Now, this needs to use a Pipe structure, which is basically a queue structure, which is to say that the first thing to go into the pipe is the first thing to come out of the pipe. Think of it as a line-up at your grocery store. Whoever gets there first gets their purchase processed first, and they are the first to leave.

The tricky part is that the pipe is defined as a file descriptor.

On Linux, files can only really be accessed by a single process at the same time for writing. If you don't then you get race conditions. More on this later.

But the point is that because we're forking multiple processes that are all writing to the same pipe (or a virtual file in memory, rather,) then we're going to need to make sure that our processes do not interfere with each other during their respective reading and writing.

So here's how I cheated:

I only allowed the root process (Process 5 in the example above) to read from the pipe.
Then I changed when each process writes to the pipe.
help i cant post more the server hates me
1. That's def not 65K characters, will be looking into this and fixing.

2. Very nice work. Love that your professor came to you, that's gonna be a great reference.

3. It's surprising how confusing child processes are for many programmers. I've never once done this in C (I'm surprised that this is not supported on Windows), but in Python, I had a lot of issues with the interprocess communications being extremely slow. I found faster ways of doing it, but it was a lot of frustrating work arounds. This is the sort of reason that single threaded performance will always be important.

Nice thread.
(June 1st, 2020 at 2:03 AM)Darth-Apple Wrote: [ -> ]1. That's def not 65K characters, will be looking into this and fixing.

2. Very nice work. Love that your professor came to you, that's gonna be a great reference.

3. It's surprising how confusing child processes are for many programmers. I've never once done this in C (I'm surprised that this is not supported on Windows), but in Python, I had a lot of issues with the interprocess communications being extremely slow. I found faster ways of doing it, but it was a lot of frustrating work arounds. This is the sort of reason that single threaded performance will always be important.

Nice thread.

nah it was my gf who came to me for C help lol, not the prof.
prof just hands out the assignments and templates.
that's awesome lain, it's always fun when the teacher needs the student for help lol.

side note: I couldn't help thinking about Fork bombs when you were describing the process, because it uses the fork command to write new processes which implement the fork command when read, again and again and again until the system memory overloads and the system crashes.

it's a command loop that was particularly devastating on older systems which didn't have the RAM we do now.