RE: Role of the Unix Console
When you ask the shell to run a program, it first fork()s. Now there is a parent process running the shell, and a child process running the same shell. The file descriptors that were open in the parent are also open in the child. If you asked for redirections, the child then changes its open file descriptors (using creat(), dup2(), open(), etc) according to the requested redirections. Then finally, the child calls exec() with the requested program's name and arguments. exec() replaces the running program image in the child with the new program, but the file descriptors aren't changed. So whatever redirections you asked for are still in place, and if there are descriptors that remained from the parent, they are still the same (shared with the parent process).
So when you run "foo > out", the shell:
fork()s, and in the child process:
newfd = open( "out", O_WRONLY | O_CREAT | O_TRUNC, (mode_t) 666 ),
dup2( newfd, stdout ); close( newfd ),
exec( "foo", { "foo", 0 }, env )
In this example, stdin and stderr are still the same as (shared with) the parent, so anything written to stderr will go to where the parent shell's stderr goes, usually the terminal in which the shell is running. The reason stdout and stderr are different is so you can redirect output to a file, pipe, socket, etc, but with errors still going to your terminal.
What happens when programs are launched from a program that isn't a shell? They normally have the same standard I/O descriptors as the parent process, which shares with its own parent, etc... the chain terminates in /dev/console which is opened by getty. /dev/console is both stdin, stdout, and stderr for process trees that never redirect to other files/devices.
(This post was last modified: 02-09-2022, 12:21 AM by robespierre.)
|