Devices – Open Console for Default File Descriptors

consoledevicesfile-descriptorsxv6

I'm reading a shell program implementation in C ( the xv6 shell from MIT's 6.828 Operating System Engineering course ).

The main() function for this shell starts with the following code:

//Assumes three file descriptors open
while((fd = open("console", O_RDWR)) >= 0){
    if(fd >= 3){
        close(fd)
        break;
    }
}

This is a quote from the xv6 book which explains the code above:

"The shell ensures that it always has three file descriptors open which are the default file descriptors for the console."


I understand that open() will return a file descriptor with the lowest number available, thus this code is making sure that there are no more than three file descriptors open, which is pretty obvious after reading the author's explanation.

But, the part which I don't understand is:

  1. Why does the shell wants to close all file descriptors but 0, 1 and 2 ? After all it is guaranteed that 0, 1 and 2 will be associated with the console, isn't it? Why should the shell care about file descriptors with a greater number being closed?

  2. I guess I don't really understand the purpose of the console ( /dev/console ? ) file here.

Best Answer

This code snippet opens /dev/console. The resulting file descriptor is the lowest-numbered file descriptor that isn't already open. If that number is at most 2, the loop is executed again. If that number is 3 or above, the descriptor is closed and the loop stops.

When the loop finishes, file descriptors 0 to 2 (stdin, stdout and stderr) are guaranteed to be open. Either they were open before, and may be connected to any file, or they've just been opened, and they're connected to /dev/console.

The choice of /dev/console is strange. I would have expected /dev/tty, which is always the controlling terminal associated with the process group of the calling process. This is one of the few files that the POSIX standard requires to exist. /dev/console is the system console, which is where syslog messages sent to the console go; it isn't useful for a shell to care about this.