Created
January 19, 2009 19:02
-
-
Save zaach/49108 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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