What happens when you type `ls -l *.c` in the shell?
Before talking about the command itself, it’s important to understand what the kernel is and what the shell is:
The kernel is the core of a computer’s operating system. It is the central, most fundamental part of the computer and has control over everything in the system. Most importantly this involves talking to the hardware and software in the system and managing resources.
The shell is also a program which allows the user to directly interface with the operating system. It interprets input from the user and executes programs based on that input. When the program is finished executing, it will display the results to the user. There can be many different types of shell programs which can be used for different reasons and commands. The shell command prompt usually starts with a $ which means it is waiting for input. The shell is also commonly known as the command line interpreter.
So what happens when you type “ls -l *.c” into a shell?
Let’s first start by understanding the command itself:
- The first part of the command is ls which is a program which lists the contents of the current directory or folder.
- The second part -l tells the list command to display the results in long format. This shows a lot more information when showing the contents including file permissions, number of links, owner name, owner group, file size, time of last modification and file / directory name.
- The third part *.c contains two important things. Firstly, the * is a wildcard which matches any character before or after it’s place. Since the .c is placed after the *, it is telling the the list program to list all files that contain the .c extension.
In conclusion, the command ls -l *.c is asking the list command to list all the files in the current directory or folder in long format that have the .c extension. The results will then display on screen to the user.
So how does the shell handle this input from the user?
- After the user gives input, the shell uses the getline() function which reads the standard input (STDIN) and parses the incoming arguments to prepare it for execution.
- The shell first checks if ls is an alias, and if it is, will replace it with the appropriate value. After that it will check if the command matches any built-ins.
- If there is still no match for the ls program, it will then look in the system folders. In this case, it will look where all the executable files are: in the $PATH:
The $PATH will then get broken up into tokens using “=” and “:” as delimiters. Then it will search for the ls program in each of the locations. Since ls is located in the /usr/bin/ directory it will then pass this information on to the system:
5. System calls are calls to the kernel to perform a specific service. To execute the ls program, three system calls are made: fork, execve and wait.
Fork() is used to create a child process from the original parent process. This is done to allow the system to do other things while the execution process is underway.
Then the system calls execve() which temporarily stops the parent process, loads up the ls program and then start it. Execve takes in all the arguments from input along with the $PATH location, (/bin/ls) and attempts to execute the program correctly.
Meanwhile, the parent process continues to do other things while keeping track of the child process created by the fork using the system call wait().
6. If the ls program ran into errors, it will display them to the user, otherwise it will output what was requested. After that, the shell will shut down the created processes, free up the memory used, exit and prompt the user for the more input.