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:

  1. list: mytodo list also mytodo (default subcommand) (--done and --undone flags should be supported)
  2. add: mytodo add "A sample task description"
  3. done: mytodo done 1
  4. undone: mytodo undone 1
  5. delete: mytodo delete 1
  6. 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.