Operating Systems
At the early days of computers, there was no operating system. People were using computers by writing machine code directly. However, with this method computers were executing only one program at a time. In order to run another program, people were needed to stop the current program and load the new program into the memory. This was a very inefficient method. Although, this method is not suitable for today's computers it is still used in some embedded systems. For instance, your microwave oven has a microcontroller that runs only one program at a time. It is not needed to run multiple programs at the same time. Operating systems provide a way to run multiple programs at the same time. This is the main reason why operating systems were invented. These programs sometimes called applications.
Another problem with this method is that people were needed to write programs for each hardware combination. For instance, if you would want to run Excel on a computer, you would need a version of Excel that is written for your hardware specifically. This is a big problem because software companies need to write a program for each hardware combination which may be thousands of different combinations.For embedded systems, this is not a problem because the hardware is fixed. However, for general-purpose computers, this is a big problem. In order to solve this problem, operating systems were invented. Most operating systems provide a layer of abstraction between hardware and software. Therefore, the only part that depends on hardware is the operating system's kernel. All applications that needs to access hardware can use the kernel functions to access hardware. These functions are called system calls. Therefore, applications do not need to know the hardware details.
Also most operating systems provide a way to manage files. They provide a file system that is used to store files. This file system is a way to store files in a structured way.
Kernel
Executable Files and Processes
Machine code is a set of binary numbers that can be understood by a computer's CPU. It is the lowest level of programming language that a computer can understand. A program is indeed a machine code. However, it also contains some metadata like the name of the program, the version of the program, the author of the program, etc. Therefore a program is a file that contains machine code and some metadata.
In Linux, programs use ELF (Executable and Linkable Format) file format. Therefore, when you want to run a program in Linux, the kernel will read the ELF file and load it into right memory locations. After loading the program into memory, the kernel will jump to the entry point of the program. At this point, CPU will execute instructions of the program instead of the kernel. This is how a program is started in Linux.
On the other hand, a program can be a script file. If a program is not a binary ELF file, it is a script file. A script file is a text file that contains some unspecified code. This code can be written in any programming language. However, it should be a language that is installed on your system.
Command Line Interface
There are 2 common approaches to interact with a computer. The first one is GUI (Graphical User Interface) and the second one is CLI (Command Line Interface). GUI is a visual interface that you can use to interact with your computer. Command line interface is a text-based interface that you can use to interact with your computer. In CLI, you are giving a command to your computer and the computer runs it and gives a result to you by printing it to the screen. There are a lot of commands that you can use in CLI. Here are some of them:
A cli command is nothing more than a program that you can run from your terminal or shell. Each cli command is an
executable file located in your PATH
. When you run a command, your shell will search for the executable file in your
PATH
and if it finds it, it will run it. So, you need to put your executable file in your PATH
in order to run it
from anywhere. You can check your PATH
by using echo $PATH
command. It is a list of directories separated by :
.
You can put your executable file in one of these directories.
Let's look at how ls
command works. When you write ls
in your terminal, it will try to find an executable file named
ls
in your PATH
. It will check each directory in your PATH
one by one. If it finds it in the first directory,
it will run it directly. If it does not find it in the first directory, it will check the second directory and so on. If
it does not find it in any of these directories, it will give an error. You can check where ls
command is located
by using which ls
command. It will give you the path of the executable file. Also, terminal will check the file
permissions. If the file is not executable, it will give an error. For this reason you need to know the concept of
users, user groups and file permissions.
There are two types of executable files. The first one is a binary ELF file.
The second one is a script file. A script file is a text file that contains shebang
at the beginning of the file. Shebang is a special comment that starts with #!
. It tells the shell which program to
use to run the script. For instance, if you write #!/bin/bash
at the beginning of your script file, shell will use
bash
to run your script. If you write #!/usr/bin/env node
, terminal will run env
command with node
as the first
argument. And as a second argument, it will give your script file's path. So, env
command will run node
with your
script file's path as the first argument. Please use shebang at the beginning of your script file. Otherwise, your
script will not run.
In the challenge, you will implement an argument parser in order to parse the arguments that are given to your program.
You can get these arguments by using process.argv
array. It is an array that contains the arguments that are given to
your program. You need to follow these subcommands in order to implement your TODO app:
- list:
mytodo list
alsomytodo
(default subcommand) (--done
and--undone
flags should be supported) - add:
mytodo add "A sample task description"
- done:
mytodo done 1
- undone:
mytodo undone 1
- delete:
mytodo delete 1
- update:
mytodo update 1 "A new task description"
Standard IO, Exit Code, Environment Variables and Arguments
Each program ran from the terminal has an exit code. This exit code is just a number between -128 and 127. It is used to
indicate the status of the program. If the program runs successfully, it will return 0. If it fails, it will return a
non-zero number (You can use any non zero number between -128 and 127). You can check the exit code of the last ran
program by using echo $?
command. It will print the exit code of the last ran program. Exit codes are very important
to check the status of a command.
Also, each program has 3 standard streams in order to interact with the user. A stream is a just a file that you can
write to or read from. There are 3 standard streams in a program. These are stdin
, stdout
and stderr
. stdin
is
the standard input stream. It is used to read input from the user (keyboard). stdout
is the standard output stream.
It is used to write output to the user (screen). stderr
is the standard error stream. It is used to write error
messages to the user (screen).
However, also a command can be started with some arguments. These arguments are called command line arguments. Arguments
are just an array of strings. And your arguments should be separated by a space. For instance, if you write ls -l -a
in your terminal, ls
command will be started with 3 arguments. The first argument will be ls
, the second argument
will be -l
and the third argument will be -a
.
Basic Commands
In linux, there is
Each process in linux, has a working directory. A working directory is just a directory that the process is running in.
We can print the current working directory by using pwd
command. We can list all the files in the current directory
by using ls
command. Optionally, we can use;
-l
flag to list files in a long format-a
flag to list all files including hidden files-h
flag to list files in a human readable format-r
flag to list files in reverse order-t
flag to list files by modification time-S
flag to list files by size-R
flag to list files recursively
We can change the current working directory by using cd <path>
command. We can create a new directory by using
mkdir <directory-name>
command and remove a directory by using rmdir <directory-name>
command.
Users and Groups
File System
Permissions
Processes
Package Managers
Shell Scripting
Environment Variables
Also, there is a concept of environment variables. Environment variables are just key-value pairs that are stored in your
shell. These variables are used to get some common configuration values across different programs. For instance, you can
use EDITOR
environment variable to get the editor that you want to use. You can use PATH
environment variable to get
the directories that you want to search for executable files. Do you see the pattern? Your shell uses PATH environment
variable to search for executable files. You can use process.env
object to access these environment variables in your
program. In this challenge, you will use TODO_USERNAME
environment variable to get the assignee of the TODOs.
Stdin, Stdout, Stderr
Exercises
- Install Ubuntu on a virtual machine and explore it.