What happens when you type “ls -l *.c” in the shell?
Tags: linux, computerscience, ubuntu, programming
Published: 2021-11-14 10:45:39


You have to understand what a *shell* is in relation to the *kernel* to understand what really happens when you run a command.

![The shell as the interface between the kernel and the user, *RMIT University*](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sij3r8sg4vrocg6q92cl.png)

The *Kernel* is the most fundamental part of a computer operating system. It’s a program itself and it controls all other programs on the computer. It talks to hardware and software and is highly involved in resource management.

The *Shell* is an application that executes programs called commands through an interactive user interface with an [operating system](https://en.wikipedia.org/wiki/Operating_system). It is the layer of programming that understands and executes the commands a user enters. In some systems, the shell is called a *command interpreter*.

Use the syntax below to write a command with an argument.

```
command [arg1] [arg2] .. [argn]
```
#### Now what is *ls*?

*ls* is a shell command that lists files and directories within a directory. With the *-l* option, *ls *.c* will list out files and directories with a *.c* extension in a long list format which includes their respective permissions, owners, and created date and time as seen in the image below.

![Output after type ls *-l*.c* in the command line](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvcr03g9v5r6iw1scebv.png)
<figcaption>Shell project at www.alxafrica.com</figcaption>

### What happens under the hood when you type “ls -l *.c” and “enter” in the shell:

After inputting the command into the shell prompt, the shell reads the command, *ls -l*.c* using *thegetLine()* function’s STDIN data stream. From here, It stores the input into a buffer as a string.

The buffer then reads from **STDIN** to the given block size and writes each block to the standard output.

Now the string is broken into tokens by removing whitespaces and then stored in an array of strings.

The *shell* checks if any of the tokens have an alias defined. If there is, it replaces the token with it’s value.

If there isn’t, it checks if any of the tokens is a built-in function and if it’s not there either.

The shell looks for a program file called ls in the shell’s environment where all the executable files are in the system, specifically in the $PATH variable. The $PATH variable is a list of directories the shell searches every time a command is entered. One of the environment variables, $PATH is parsed using the ‘=’ as a delimiter. Once the $PATH is identified, all the directories in $PATH are tokenized, each location specified using the ‘:’ delimiter, recursively searched by appending the command at the end of the path.

Since it searches recursively, it will first search in the ``pwd`` and then its parent and so on and so forth with all other commands.

To execute ls, the following system calls are made: *fork(), execve() and wait().*
System calls are interactions we make with the kernel.

To run a command in a shell, the *fork()*  system call is made, this duplicates the shell by creating a child shell of the parent shell.

Then the *execve()* system call is made, which stops the old duplicate process (parent shell), loads up the new process(child shell which is *ls* in this case) and start the new program which gives a brand new address with the program by replacing the current process's memory stack with the new data loaded from the *ls* executable file.

Meanwhile, using the *wait()* system call, the parent process continues to keep track of it’s children in the background.



### Lastly

Once the *ls -l*.c* command is executed, the shell frees up memory, exits and prompts the user for input again.

All these happen under a few milliseconds in most cases, depending your machine power.

Did I misplace anything? let me know in the comments.