How do I use pipes in xv6 to communicate between unrelated processes? - c

I understand how IPC works and how when you make a pipe before fork() the child/children can inherit the pipe for communication. However, I cant wrap my head around how I would do this for two unrelated processes? (i.e processes that are not the parent or children of each other?).
Im asking because Im trying to get one of my .c files to communicate with another .c file via pipes, but I dont know how that works explicitly in xv6. Any help/ideas would be greatly appreciated!!

There are several ways to accomplish this, for something simple, try checking out popen(). One program can spawn an unrelated one and then can then read and write to each other.
https://man7.org/linux/man-pages/man3/popen.3.html
For other solutions you should look into FIFO files or even sockets as a means of IPC.

Pipes are not able to communicate between 2 processes unless those two processes share a common ancestor, regardless of the Linux distro you use. If you are trying to allow 2 unrelated files to communicate, one of the exec() commands must be used in the child or parent process; this page may have what you're looking for.

What pipe does is to connect the standard output of one program to the standard input of another program.
Consider the cat and wc program in xv6. cat displays the content of a file or files. Let's say we have a text file test.txt with Hello World in it. cat can display its content like this:
$ cat test.txt
Hello World
wc calculates the number of lines, words, and characters in a file, files, OR stdin. So it can be used either like this(read from a file):
$ wc test.txt
1 2 12 test.txt
or this(read from stdin):
$ wc
Hello World
<Press Ctrl-D>
1 2 12
We can use pipe to connect these two commands:
$ cat test.txt | wc
1 2 12
So here cat reads the file and prints its content into stdout, but it doesn't get displayed onto the screen. Instead it gets feeded into the stdin of wc and wc counts the lines, words, and characters in it. Notice that this communication is unidirectional. It only goes from left to right, no backwards.
You can refer to the source code of these two commands to write your program. Basically all you have to do is to make sure the previous command outputs into stdout and the subsequent command reads from stdin.

Related

C Programming w/Pipes prints weirdly to STDOUT

I'm working on a programming assignment for my Operating Systems class and I'm running into some issues with the way my output is showing up in the terminal.
The purpose of the program is to take input from a file or the STDIN and essentially pass it through 4 pipes to get the frequency of the words. I'm using calls to fork(),execlp(), and pipe() to complete this and am not having any issues with my program, however as the last child executes and prints to the terminal it looks like this:
os-class ~/cs344/Homework3 190% myword text.txt
os-class ~/cs344/Homework3 191% 1 aaaaa
1 aaaaaa
1 aaaaaaa
8 it
5 s
5 sa
(Here I could enter command for 191%, something like 'ls'..)
myword is my executable and text.txt is the file I'm using for testing. I'm mainly confused because it seems like my pipes are lined up correctly with STDIN and STDOUT. Do I need to insert a wait() somewhere?
Thanks for any suggestions and sorry if there's already an answer to this somewhere! I wasn't exactly sure what to search for.
Each parent that does fork() will need to wait() on its children or the children will continue to run after the parent has exited.
The shell (if you wrote it) also needs to wait on the programs it starts.

Another Linux command output (Piped) as input to my C program

I'm now working on a small C program in Linux. Let me explain you what I want to do with a sample Linux command below
ls | grep hello
The above command is executed in the below passion (Let me know if I've got this wrong)
ls command will be executed first
Output will be given to grep command which will again generate output by matching "hello"
Now I would like to write a C program which takes the piped output of one command as input. Means, In the similar passion of how "grep" program was able to get the input from ls command (in my example above).
Similar question has been asked by another user here, but for some reason this thread has been marked as "Not a valid question"
I initially thought we can get this as a command line argument to C program. But this is not the case.
If you pipe the output from one command into another, that output will be available on the receiving process's standard input (stdin).
You can access it using the usual scanf or fread functions. scanf and the like operate on stdin by default (in the same way that printf operates on stdout by default; in the absence of a pipe, stdin is attached to the terminal), and the C standard library provides a FILE *stdin for functions like fread that read from a FILE stream.
POSIX also provides a STDIN_FILENO macro in unistd.h, for functions that operate one file descriptors instead. This will essentially always be 0, but it's bad form to rely on that being the case.
If fact, ls and grep starts at the same time.
ls | grep hello means, use ls's standard output as grep's standard input. ls write results to standard output, grep waits and reads any output from standard input at once.
Still have doubts? Do an experiment. run
find / | grep usr
find / will list all files on the computer, it should take a lot of time.
If ls runs first, then OS gives the output to grep, we should wait a long time with blank screen until find finished and grep started. But, we can see the results at once, that's a proof for that.

Create two processes when another terminal window is opened?

The topic might sound weird, but here's what I want to achieve:
In Terminal A, type command line as following:
./create proA
The first process proA is created. It outputs something like
This is process A.
Open another terminal window (called Terminal B). In Terminal B, type the following line:
./create proB
The second process proB is created. It outputs:
This is process B.
UPDATED:
I'm trying to create two processes that communicate with each other. Before going into more details, I just want to try if I can create another process that has some relationship with first process when another terminal window is opened.
Is it possible to achieve something like this? If so, can someone give any tip for how to start in c? Thanks!
The terminals don't matter for inter process communication. There are so many ways to communicate between processes that it doesn't make sense to highlight any of them here.
About having a own terminal for each process. Well:
(xterm -e "${COMMANDLINE1}" &) ; (xterm -e "${COMMANDLINE2}" &)
if you want to see only errors, you should use:
./process > /dev/null 2>&1
if you did't understood 2>&1, read below)
possible numbers:
0 — STDIN, 1 — STDOUT and 2 — STDERR
that means, all std errors will be printed in std out.

Using streams to pipe input/output between *nix processes

I'm working on a fairly simple application in C. The end goal is to pipe the output from one process to in input of another in a *nix environment (yes, I am aware of the pipe() command and dup/dup2 but I'm trying to find away around using those commands). I was wondering if there is any way to connect the streams rather than using file descriptors (The systems aren't guaranteed to be POSIX compliant).
So basically I want to do something like this (pseudo-code)
pid = fork()
if pid == 0
// assign this process's stdin to the parents stdout.
stdin = parent.stdout;
exec() // launch new process that receives the parents stdout as stdin
// child stuff....
else
// parent stuff....
I know that it probably won't be as simple as just doing an assignment as above, but is there any way to do this using only streams? I tried looking around, but couldn't find anything..
Thanks!
sorry if I'm missing the point here but the whole philosophy of *nix is one program, one job. If you need a program to dump the contents of a program to the screen then you have the cat command. If the files too big and you need page breaks you pipe the output of cat to the more command:
cat myfile.txt | more
If you need to pipe between two terminal applications then you're meant to use the command line to do so:
myprog1 | myprog2
Obviously that's the philosophical approach, so if that doesn't help then can you clarify what you're trying to pipe and why you're trying to do it in process ?

Redirecting the output of a child process

There are several ways of redirecting the output of a child process:
using freopen(3)
using dup(3)
using popen(3)
...
What should one pick if all is wanted is to execute a child process and have it output saved in a given file, pretty much like the ls > files.txt works?
What is normally used by shells?
You can discover what your favorite shell uses by strace(1)ing your shell.
In one terminal:
echo $$
In another terminal:
strace -o /tmp/shell -f -p [PID from the first shell]
In the first terminal again:
ls > files.txt
In the second terminal, ^C your strace(1) command and then edit the /tmp/shell output file to see what system calls it made to do the redirection.
freopen(3) manipulates the C standard IO FILE* pointers. All this will be thrown away on the other side of the execve(2) call, because it is maintained in user memory. You could use this after the execve(2) call, but that would be awkward to use generically.
popen(3) opens a single unidirectional pipe(7). This is useful, but extremely limited -- you get either the standard output descriptor or the standard input descriptor. This would fail for something like ls | grep foo | sort where both input and output must be redirected. So this is a poor choice.
dup2(2) will manage file descriptors -- a kernel-implemented resource -- so it will persist across execve(2) calls and you can set up as many file descriptors as you need, which is nice for ls > /tmp/output 2> /tmp/error or handling both input and output: ls | sort | uniq.
There is another mechanism: pty(7) handling. The forkpty(3), openpty(3), functions can manage a new pseudo-terminal device created specifically to handle another program. The Advanced Programming in the Unix Environment, 2nd edition book has a very nice pty example program in its source code, though if you're having trouble understanding why this would be useful, take a look at the script(1) program -- it creates a new pseudo-terminal and uses it to record all input and output to and from programs and stores the transcript to a file for later playback or documentation. You can also use it to script actions in interactive programs, similar to expect(1).
I would expect to find dup2() used mainly.
Neither popen() nor freopen() is designed to handle redirections such as 3>&7. Up to a point, dup() could be used, but the 3>&7 example shows where dup() starts to creak; you'd have to ensure that file descriptors 4, 5, and 6 are open (and 7 is not) before it would handle what dup2() would do without fuss.

Resources