What happens when you types ls -l in the shell…

Carlos Alvarez
4 min readAug 28, 2019

Summary for NOT informatics .. for example my mom…

  1. The terminal reads from the standard input, each of the characters and stores them in a buffer.

2. Then the shell tokens each word it finds in the buffer line.

3. Then a child process is created.

4. Then the shell searches in each of the environment variables for the PATH, in each of the PATH directories and compares if it finds the executable ls

5. If you find it in any of these directories, proceed to run it, display it on the screen and end the child process.

A picture is worth a thousand words.

Now let’s see what really happens inside the shell, I mean the C code and the linux kernel:

At the code level, this is what happens when you type “ls -l” and “enter” in the shell:
First, the shell prints the message, asking the user to enter a command. The shell reads the ls -l command from the STDIN of the getline() function, analyzing the command line in arguments that are passing to the program it is running.
The shell checks if ls is an alias. If so, the alias replaces ls with its value.
If ls is not an alias, the shell verifies if the word of a command is embedded.
The environment is copied and passed to the new process.
Then, the shell looks for a program file called ls where all the executable files are located in the system, in the shell environment (an array of strings), specific to the $PATH variable. The $ PATH variable is a list of directories that the shell searches every time you enter a command. $PATH, one of the environment variables, is analyzed using the “=” as a delimiter. Once $PATH is identified, all controls in $PATH are tokenized, further analyzed using ‘:’ as a delimiter.

The binary executable file ls will be located in one of the main subdirectories of the directory
‘/usr’ in the file ‘/usr/bin/ls’ — ‘/usr/bin’ contains most of the executable files, ie. programs ready to run.

To execute ls, three system calls are made:

FORK > EXECVE > WAIT

These system calls are calls to the Kernel code to compute something.

To create new processes to execute commands in Unix, the fork() system call is made to duplicate the parent process in the Shell, creating a child process of the parent process in the Shell.

The execve() system call is made and does three things: the operating system stops the duplicate process from the parent, loads the new program in this case: ls and starts the new ls program. execve() replaces the defining parts of the memory stack of the current process with the new stuff loaded from the ls executable file.

process difference between fork and execve

The entry to execve for ls -l will be:

execve(“/bin/ls”, {“ls” or “/bin/ls”, “-l”, NULL}, NULL);

Let’s say you have your shell, at first you will have to use `/bin/ls` and not just ls, so you have:

$ /bin/ls -l

Tokenize this line into stuff = {“/bin/ls”, “-l”, NULL}

Then do execve(stuff[0], stuff, NULL).

Then

the parent process continues to do other things, keeping track of its children as well, using the system call wait()

If the executable binary (ls) file does not exist, an error will be printed:

Command not found

By last

After ls -l is executed, the shell executes shutdown commands, frees up memory, exits, and re-prompts the user for input.

References

Special thanks to my peer Diego Vivas

Written by Carlos Alvarez y diego Vivas

--

--