C
version | comment | author |
---|---|---|
v0.1.0 | document built | Marco Ma |
v0.1.1 | tag added | MArco Ma |
Someday I was writing technical report, then I found something like this:
main.c
log.c
After some data research and experiment. I finally notice that, when you execute main.o
, the log in log.c
is not gonna end up in standard error, but in ./fd.txt
.
There's a file descriptor table in every process maintained by kernel. According to POSIX standard, there are three standard stream:
fd | file pointer |
---|---|
0 | STDIN |
1 | STDOUT |
2 | STDERR |
3 | NULL |
4 | NULL |
Generally, all user file will end up with fd > 2
fd | file pointer |
---|---|
0 | STDIN |
1 | STDOUT |
2 | STDERR |
3 | USER FILE1 |
4 | USER FILE2 |
For example, assume we have a file descriptor table below:
fd | file pointer |
---|---|
0 | STDIN |
1 | STDOUT |
2 | STDERR |
after using
The file descriptor table will look like:
fd | file pointer |
---|---|
0 | STDIN |
1 | STDIN |
2 | STDERR |
0644
means -rw-r--r--
)open()
have no buffer, system has to access file through storage(HDD, SSD .etc).
fopen()
do have buffer, system does not have to access storage everytime.
open()
is a POSIX standard function, which is not protable.
fopen()
is a standard C library function, which is protable.
open()
return a file descriptor, which is an int
fopen()
return a file stream pointer, which is an FILE *
open() | fopen() | |
---|---|---|
buffer | NO | YES |
library | POSIX | standard library |
return | int | FILE * |
Null
This function replace the current process image to the target process image.
After all these function description, we can now back to main.c
and log.c
.
In the begining, we have a file descriptor table like this:
fd | file pointer |
---|---|
0 | STDIN |
1 | STDOUT |
2 | STDERR |
3 | NULL |
4 | NULL |
After the first few lines in main.c
.
The table looks like this:
fd | file pointer |
---|---|
0 | NULL |
1 | NULL |
2 | NULL |
3 | NULL |
4 | NULL |
Yes, nothing inside, no man's land. |
Then system starts to open file:
Now the table looks like this:
fd | file pointer |
---|---|
0 | /dev/null |
1 | ./fd.txt |
2 | NULL |
3 | NULL |
4 | NULL |
Then copy fd==1
to fd==2
The new table becomes:
fd | file pointer |
---|---|
0 | /dev/null |
1 | ./fd.txt |
2 | ./fd.txt |
3 | NULL |
4 | NULL |
Finally we could execute log
Inside log.c
fprintf() has no idea that the file descirptor table has been changed, he printed the log to fd = 2
, and that is not stderr
anymore, it's ./fd.txt
now.