When a program begins, does it take file descriptors 0, 1 and 2 for stdin, stdout and stderr by default?. And will API calls such as open(...), socket(...) not return 0, 1 and 2 since these values are already taken?. Is there any case in which open(...) or socket(...) would return 0, 1 or 2. And 0, 1 and 2 are not related with stdin, stdout, and stderr.
-
As I answered, your question don't have much sense. file descriptor 0 is always stdin. – Basile Starynkevitch Mar 13 '14 at 06:37
3 Answers
At the file descriptor level, stdin is defined to be file descriptor 0, stdout is defined to be file descriptor 1; and stderr is defined to be file descriptor 2. See this.
Even if your program -or the shell- changes (e.g. redirect with dup2(2)) what is file descriptor 0, it always stays stdin (since by definition STDIN_FILENO
is 0).
So of course stdin could be a pipe or a socket or a file (not a terminal). You could test with isatty(3) if it is a tty, and/or use fstat(2) to get status information on it.
Syscalls like open(2) or pipe(2) or socket(2) may give e.g. STDIN_FILENO
(i.e. 0) if that file descriptor is free (e.g. because it has been close(2)-d before). But when that occurs, it is still stdin by definition.
Of course, in stdio(3), the FILE
stream stdin is a bit more complex. Your program could fclose(3), freopen(3), fdopen(3) ...
Probably the kernel sets stdin, stdout, and stderr file descriptors to the console when magically starting /sbin/init
as the first process.

- 223,805
- 18
- 296
- 547
-
2Good answer, but could be better if it acknowledged the rigidity (and potential misalignment to what people asking questions like this might be trying to say) of the definitions being used. When a process redirects another FD to FD 0, then yes, *within that process* (and as inherited by child processes) whatever they redirected to 0 is now "stdin". But it's definitely no longer the "stdin" that it had previously, so in another equally valid binding of words to concepts, 0 is no longer "stdin" - and sometimes that meaning of "is it stdin?" is more relevant/useful. Still, +1 overall. – mtraceur Sep 08 '22 at 21:31
Though a couple of answers already existed but I didn't find them informative enough that they explained the complete story.
Since I went ahead and researched more, I am adding my findings.
Whenever a process starts, an entry of the running process is added to the /proc/<pid>
directory. This is the place where all of the data related to the process is kept. Also, on process start the kernel allocates 3 file-descriptors to the process for communication with the 3 data streams referred to as stdin
, stdout
and stderr
.
the linux kernel uses an algorithm to always create a FD with the lowest possible integer value so these data-streams are mapped to the numbers 0
, 1
and 2
.
Since these are nothing but references to a stream and we can close a stream. One can easily call close(<fd>)
, in our case close(1)
, to close the file descriptor.
on doing ls -l /proc/<pid>/fd/
, we see only 2 FDs listed there 0
and 2
.
If we now do an open()
call the kernel will create a new FD to map this new file reference and since kernel uses lowest integer first algorithm, it will pick up the integer value 1
.
So now, the new FD created points to the file we opened (using the open()
syscall)
Any of the data transfer that happens now is not via the default data-stream that was earlier linked but the new file that we opened.
So yes, we can map the FD 0
, 1
or 2
to any of the file and not necessary stdin
, stdout
or stderr

- 2,958
- 26
- 28
-
fwiw, the dup/dup2 man page documents this behavior (assigning the lowest available handle). So it's official. Probably best not to close standard handles without replacing them with something else. :-P – Robin Davies Mar 18 '22 at 01:53
When a program begins, does it take file descriptor 0 1 2 for stdin, stdout and stderr by default .
If you launch your program in an interactive shell normally, yes.
By @EJP:
Inheriting a socket as FD 0 also happens if the program is started by inetd, or anything else that behaves the same way.
will the API such as open(...), socket(...) not return 0 1 2 since these value are already be taken.
Yes.
Is there any case that open(...) or socket(...) would return 0 1 2.
Yes, if you do something like
close(0); close(1); close(2); open(...); /* this open will return 0 if success */

- 14,695
- 3
- 29
- 47
-
Inheriting a socket as FD 0 also happens if the program is started by inetd, or anything else that behaves the same way. – user207421 Mar 13 '14 at 02:41
-
Note that this is essentially what the shell does when you ask it to redirect these streams -- it reopens these file handles so they point to a file or a pipe as you have requested. (I've just been working on some code in the WebSphere startup logic which does something similar to set up WebSphere's native_stdout.log and native_stderr.log handling.) – keshlam Mar 13 '14 at 02:50
-
1@keshlam I/O redirection could also be implemented by using `dup()` or `dup2()`. – Lee Duhem Mar 13 '14 at 03:00