Skip to content

Instantly share code, notes, and snippets.

@zaach
Created January 19, 2009 19:02
Show Gist options
  • Save zaach/49108 to your computer and use it in GitHub Desktop.
Save zaach/49108 to your computer and use it in GitHub Desktop.
# Explaining redirection and file descriptors in C
# I only had a vague notion of the process, and it
# had been a year since I had worked with C!
# Still, wasn't TOO bad of an explanation.
# The tutorial to follow along is here: http://gist.github.com/49106
Qi: hey Zact
Zach
me: zact??
Qi: lol
sorry
me: ha, np
1:32 AM Qi: hey can you explain to me the whole thing about file descriptors and what they are?
i don't really have an idea but i have an example code give to me by Paul
1:33 AM me: hmm, let me see
Qi: hey i just sent you the tutorial Paul gave us
if you could explain that, it would be great
i have copied some of his code
1:34 AM me: ok
1:35 AM Qi: can i go make some ramen noodles and come back in say 10 min
?
me: yeah, i'm looking this over
Qi: okay
10 minutes
1:46 AM Qi: im back
me: yay
1:47 AM i think i understand the code
Qi: kool
explain away as i eat
me: k
so, some background
1:48 AM every process on unix/linux has an id called the pid
Qi: k
me: if we know the pid in C we can do stuff to that other rocess
*process
Qi: k
1:49 AM me: that pfd array stores some references to the input/output ends of the pipe
1:50 AM the pipe() function assigns it automatically it seems
Qi: ok, what gets stored in d array in terms of data type?
1:51 AM me: well, it must be some arbitrary int value
Qi: ok
1:52 AM me: the C functions you use on it will know what to do, so you wn't have to worry about it much
Qi: k
me: ok, so the interesting stuff begins with the first fork() call
pid[0] = fork();
1:53 AM Qi: k
me: at that point, another process splits off and runs in parallel, beginning its execution at that same line
1:54 AM it has all the same variables and memory, so its a twin of your main process
but for one exception...
fork() will return the pid of that new process, but only to the main one
1:55 AM it will return 0 for the new process
Qi: ok
me: so that's how you can tell if you're in the new process or the main one
pid[0] will be 0 in the new process
1:56 AM Qi: ok
me: and it will be the pid of the new process in the main one
Qi: ok
me: alright, so knowing that, that first if statement will only be true for the new/child process
1:57 AM Qi: ok
1:58 AM me: so basically, the code in that child process block is going to execute a command, but first changes where it directs itsoutput to
1:59 AM by default the output goes to STDOUT, which is usuallythe command line
but, dup2(pfd[1], STDOUT);
switches it to output to the pipe
Qi: hold it
me: ya?
2:00 AM Qi: so dup2(pfd[1], STDOUT) means
that i am doing what?
2:01 AM me: well, pfd[1] is like the opening of the pipe
and STDOUT is some constant that lets the function know you're changing the output of stdout
2:02 AM you're changing it to the first parameter, which is pfd[1]
Qi: okay, so we are redirecting the output from STDOUT to pfd[1]?
2:03 AM me: yep
Qi: hold it
let me write this down
me: k
2:04 AM Qi: so what does close(pfd[0]) mean?
2:05 AM me: i think you're soposed to close all input/output things yo have open before exiting something or things might get messed up
2:06 AM Qi: so its convention and we do that at the beginning of every piping?
me: well, before killing off the process, yes
2:07 AM doesn't need ot be at the begginnin
but they did because they weren't using that end of the pipe
Qi: oh ok
2:08 AM so they are using pfd[1] and not pfd[0]?
me: yep
pfd[0] is for reading from the pipe
and we want to put stuff in the pipe, not read from it
Qi: oh okay
2:09 AM me: right, so
the main reason we want to fork and create a child process
is because of that last line in there, execlp("ls","ls",NULL);
Qi: lol
2:10 AM let me look
me: see it?
Qi: okay, so you want the child to execute ls but not the parent?
if so, what do you want to parent to do?
2:11 AM me: right, becaue once you call execute, your program stops and is replace by what you called!
so we would lose our shell if we called it in the parent
Qi: oh okay
2:12 AM me: so, we fork and have a child process do it and replace itself
meanwhile....
Qi: oooooo
me: the main process is waiting around for the child to finish
lol
2:13 AM look at the line, after the else statement
waitpid(pid[0], &status, WUNTRACED | WCONTINUED); //wait(NULL) is also okay here
Qi: yea
me: remember, pid[0] contains the pid of the child process we forked
2:14 AM and we pretty much say "wait here for that process to finish"
Qi: yea
me: once its done, we know it should have left some goodies for us in the pipe
Qi: lol
2:15 AM i like it
:)
me: :p
2:16 AM go ahead?
Qi: hold it, you mean the goodies are in pfd[1]?
where do i find my goodies?
me: lol, well, they are in the pipe
Qi: what variable holds my pipe?
me: you can only get them out of the other end, pfd[0]
2:17 AM Qi: lol
this is fun
me: ah mann, we are dorks
lol
Qi: lol
no way
we are awesome
that is to say, YOU are awesome
2:18 AM me: NO U
WE are awesome :)
Qi: lol
me: ah, but let us return the pipe, while the contents are fresh
2:19 AM Qi: ok
me: soo, we don't really need what's in there
our other process does
wc, in this case
Qi: ok
me: (word count)
Qi: ok
2:20 AM me: soo the main process is going to fork again so it can execute wc in a child (and we keep our main process)
2:21 AM Qi: ok
me: BUT, before it executes wc, it'll do some input switching
2:22 AM so we can read from the pipe (pfd[0]) instead of STDIN
Qi: so the line dup2(pfd[0], STDIN) means
that
2:23 AM we are redirecting from the stdin to pfd[0] because that's where our goodies are?
me: yep
2:24 AM and you can see they close the pipes again
Qi: yea
me: ooo, i just noticed they do some redirection too
2:25 AM Qi: what are you refering to?
me: line 75
int fildes = open("outfile", O_WRONLY|O_CREAT, 0666);
2:26 AM so, not only do we change the input to read from the pipe, we change the output to write to a file
but it works the same way, using the dup2 function...
2:28 AM so the first parameter to dup2 is just a pipe end or file, and the second parameter is whether you want to write or read
Qi: hold on
me: ya?
2:29 AM Qi: copying notes u wrote
umm..
me: sup
Qi: umm..
2:30 AM int fildes holds an integer
the dup2() figures out based on an int value what file to write to??
2:31 AM me: exactly, just like the pipe ends are just some ints
2:32 AM Qi: this is crazy
me: you get it?
Qi: yea
me: k
2:33 AM right, so we use dup2 so our process can read from the pipe and retreive the goodies
Qi: lol
2:34 AM i like goodies
:)
me: lol, mee too
then we use dup2 so it can dump it's output to a file
2:35 AM and make sure we close the files and pipes so things go smoothly
then we run execute which will use the inputs/outputs we just set up
wc will use the pipe as input and output to the file
2:36 AM Qi: ahhh ok
me: then when it's done the child process dies off
and we are left with our original main
2:37 AM Qi: darn, you're good
!!!!!!
me: ;)
Qi: but hold it one sec
got question
me: yes, you in the front
Qi: lol
umm..
2:38 AM when you say wc uses the pipe as input and output, what line are you referring to? execlp()?
me: well, that line calls wc
2:39 AM and wc will retain the input/output settings we set up with dup2
so it remembers
Qi: absorbing...
me: k
2:40 AM Qi: hmm...
so every executable file needs inputs/output settings
2:41 AM in our case, we are not using stdin or stdout
we are manually setting it up?
me: exactly
Qi: ahhhh.......
2:42 AM me: alright, and for the last bit
the last else statement is our main, which has to close the pipes too
2:43 AM and the last line means it was wating for the child process, wc, to finish
2:44 AM Qi: yes...
this is so 10^3 times clearer
thanks for your excellent explanations
me: yayay, this was fun
2:45 AM Qi: yea, this was indeed fun
me: alright, so know YOU have th power to manipulate goodies for yourself
Qi: you should post this to some blog or something
don't loose this chat conversation
i'm serious
me: ha, ok
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment