├── .DS_Store
├── README.md
├── algorithms
├── basicDS.md
└── bst.md
├── language_compilation
├── bytecode.md
└── compilation.md
├── networking
├── application.md
├── datatransfereliability.png
├── dnslevels.png
├── dnsmessageformat.png
├── gbn.png
├── img
│ ├── 2Dparity.png
│ ├── ASRIP.png
│ ├── DNSCDN.png
│ ├── IGMPnMCRP.png
│ ├── LANMACs.png
│ ├── SSLrecord.png
│ ├── TCPHTTPStreaming.png
│ ├── TLS.png
│ ├── VCNetwork.png
│ ├── VCSetup.png
│ ├── VPN.png
│ ├── almostSSLHandshake.png
│ ├── blockCipher.png
│ ├── cNGraph.png
│ ├── cbSpanningT.png
│ ├── cdmaEncDec.png
│ ├── clientPlayoutDelay.png
│ ├── cyptcomponents.png
│ ├── datagramNetwork.png
│ ├── dhcpClientServer.png
│ ├── dhcpProcess.png
│ ├── dualStack.png
│ ├── duplication.png
│ ├── eBGP_iBGP.png
│ ├── edc.png
│ ├── ethernetFrame.png
│ ├── hiddenTerminals.png
│ ├── hopCount.png
│ ├── inernetNetworkLayer.png
│ ├── inputPortProcessing.png
│ ├── interConnectedASs.png
│ ├── interfaceAddressSubnet.png
│ ├── interleaving.png
│ ├── ipFragReass.png
│ ├── ipv4Datagram.png
│ ├── ipv6DgFormat.png
│ ├── ipv6Tunneling.png
│ ├── linkHops.png
│ ├── linkLayerACK.png
│ ├── mcRoutingAlgos.png
│ ├── monoalphabetic.png
│ ├── multicastGroup.png
│ ├── nat.png
│ ├── network4Switches.png
│ ├── outputPortProcessing.png
│ ├── polyalphabetic.png
│ ├── publicKeyEnc.png
│ ├── routerArch.png
│ ├── routerSubnets.png
│ ├── routingAlgoForwardingTable.png
│ ├── rtsCts.png
│ ├── senderRecIntruder.png
│ ├── spanningTree.png
│ ├── switchingTechniques.png
│ ├── twoSenderCDMA.png
│ ├── webPageRJourney.png
│ ├── wifiFrame.png
│ └── wifiLANArchitecture.png
├── journeymail.png
├── link.md
├── lowlevel.md
├── mail.png
├── multimedia.md
├── network.md
├── networking-and-internet.md
├── receivewindow.png
├── request.png
├── response.png
├── security.md
├── sr.png
├── stack.png
├── tcpsegment.png
├── tcpsendreceivebuffers.png
├── transport.md
├── typesofqueries.png
├── udpformat.png
└── wireless.md
├── os
├── Advanced Aspects of Virtual Memory.md
├── README.md
├── concurrency.md
├── img
│ ├── MLFQ.png
│ └── addressSpace.png
├── overview.md
├── paging.md
├── processes.md
├── scheduling.md
└── virtualMemoryOS.md
└── systems
├── computerSystems.md
├── concurrent.md
├── errorHandling.md
├── exceptionalControlFlow.md
├── img
├── L1.png
├── addrTranslation.png
├── alu.png
├── argumentList.png
├── blockLinkedList.png
├── boundaryTag.png
├── cacheorg.png
├── call_proc.png
├── callret.png
├── canary.png
├── computerSystems
│ ├── contextSwitching.png
│ ├── hardware.png
│ ├── memH.png
│ ├── osAbstractions.png
│ └── virtMemSpace.png
├── directedReachabilityGraph.png
├── dram.png
├── e8bitfloat.png
├── echostack.png
├── envp.png
├── excepHandAddr.png
├── exception.png
├── exceptionTable.png
├── fourmux.png
├── fullyasoc.png
├── heap.png
├── heapBlockFormat.png
├── i7cache.png
├── implicitFreeListHeap.png
├── ioRedirectionDup2.png
├── kernelOpenFiles.png
├── lcf.png
├── lineMatchwordSel.png
├── linux32Stack.png
├── linuxPageFaultHandling.png
├── linuxVM.png
├── linuxVMOrg.png
├── mallocFree.png
├── minVal.png
├── mmapArgs.png
├── modernProc.png
├── multLevelAddrTranslation.png
├── multLevelPageTable.png
├── pa.png
├── pageFault.png
├── pageHit.png
├── pageLevelMemProtection.png
├── pageTable.png
├── parentChildFileDescs.png
├── princMemHier.png
├── privateCopyOnWrite.png
├── process2files.png
├── processAddressSpace.png
├── processGraph.png
├── processSeparateAddressSpace.png
├── ram.png
├── registerFile.png
├── registerState.png
├── repManInfo
│ ├── endian.png
│ ├── floatcases.png
│ └── ieeefloats.png
├── setSelection.png
├── sharedObject.png
├── singleBitMux.png
├── sixBitFloat.png
├── stackFrameStructure.png
├── stackOps.png
├── stackarguments.png
├── struct.png
├── tlb.png
├── va.png
├── vmAsCache.png
├── wordEq.png
└── wordmux.png
├── linking.md
├── machineLevelRep.md
├── memoryHierarchy.md
├── network.md
├── optimizingPerformance.md
├── processorArchitecture.md
├── repManInfo.md
├── systemLevelIO.md
└── virtualMemory.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/.DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Notes on CS Fundamentals:
2 | - [Computer Systems:](systems/)
3 | + [A Tour of Computer Systems](systems/computerSystems.md) :white_check_mark:
4 | + [Representing and Manipulating Information](systems/repManInfo.md) :white_check_mark:
5 | + [Machine-Level Representation of Programs](systems/machineLevelRep.md) :white_check_mark:
6 | + [processor Architecture](systems/processorArchitecture.md) :arrows_counterclockwise:
7 | + [Optimizing Program Performance](systems/optimizingPerformance.md) :white_check_mark:
8 | + [The Memory Hierarchy](systems/memoryHierarchy.md) :white_check_mark:
9 | + [Exception Control Flow](systems/exceptionalControlFlow.md) :white_check_mark:
10 | + [Virtual Memory](systems/virtualMemory.md) :white_check_mark:
11 | + [System-Level IO](systems/systemLevelIO.md) :white_check_mark:
12 | + [Network Programming](systems/network.md) :arrows_counterclockwise:
13 | + [Concurrency](systems/concurrent.md) :black_circle:
14 |
15 | - [Networking:](networking/)
16 | + [A Tour of the Internet and Networking](networking/networking-and-internet.md) :white_check_mark:
17 | + [The Application Layer](networking/application.md) :white_check_mark:
18 | + [The Transport Layer](networking/transport.md) :white_check_mark:
19 | + [The Network Layer](networking/network.md) :white_check_mark:
20 | + [The Link Layer](networking/link.md) :white_check_mark:
21 | + [Wireless and Mobile Networks](networking/wireless.md) :white_check_mark:
22 | + [Multimedia Networking](networking/multimedia.md) :white_check_mark:
23 | + [Security in Computer Networks](networking/security.md) :white_check_mark:
24 |
25 | - [Operating Systems](os/):
26 | + [Overview](os/overview.md) :white_check_mark:
27 | + [Processes](os/processes.md) :white_check_mark:
28 | + [Scheduling](os/scheduling.md) :white_check_mark:
29 |
30 | - [Algorithms and Data Structures:](algorithms/)
31 | + [Basic Data Structures (Queues, Stacks, Linked Lists, Hash Tables)](algorithms/basicDS.md) :arrows_counterclockwise:
32 | + [Binary Search Trees](algorithms/bst.md) :arrows_counterclockwise:
33 | - [Compilers and Languages](language_compilation) :arrows_counterclockwise:
34 | + [Compilers and Interpreters](language_compilation/compilation.md) :arrows_counterclockwise:
35 | + [Bytecode](language_compilation/bytecode.md) :arrows_counterclockwise:
36 |
37 | - Discrete Math:
38 | - Distributed Systems:
39 | - Databases:
40 |
41 | - Programming (Functional and Beyond)
42 | - Applied Cryptography
43 |
--------------------------------------------------------------------------------
/algorithms/basicDS.md:
--------------------------------------------------------------------------------
1 | ## Stacks:
2 | - Stacks are an abstract LIFO data structures where last inserted data are the first to be popped out. They are great for reversing stuff and checking balanced sequences in syntax parsers.. etc. They can be implemented using arrays or linked lists. Linked lists might be a little less intuitive but they are generally more efficient spacewise and timewise.
3 |
4 | ## Queues:
5 | - Queues are FIFO (first in, first out). They are essential
6 |
7 | ## Linked Lists:
8 | - A **linked list** is a linear data structure just like an array where multiple objects can be traversed one after the other, but it's fundamentally different from an array.
9 | - An array is a contiguous chunk of memory cells where objects can be accessed by indices located between the bounds of the array. The elements of a linked list are accessed through **pointers** (or object references). They are like beads in a rosary (tasbeeh). You can only access it from one or both of its heads.
10 | - The main **advantage** of a linked list is its dynamic nature as opposed to the fixed nature of an array. A linked list also provides for faster insertions and deletes because there is no need for shifting. The absence of element shifting is all the better if the location of the insert or delete is towards the head of the linked list.
11 | - The most basic linked list, a **singly linked list** consists of one or more **nodes**, each nodes has *key* (the node's data) and a *pointer* (usually named *next*) that points to the next node. The first element of a linked to which no other list element points is the **head** of the list. The las element whose *next* pointer points to a null is the list's **tail**. When the list's head points to a null, the list is empty!
12 | - A linked list can be:
13 | * Either a **singly** or **doubly**. In a **doubly linked list** a node has two pointers one pointing to the next node and another pointing to the previous node.
14 | * Either **circular** or not. If the next pointer of a singly linked list's tail points to the list's head, the list is said to be circular.
15 | * Either **sorted** or **sorted**.
16 | - The different types of linked lists offer different advantages to different operations. Theoretically inserting and removing an element from the tail of a doubly LL can be achieved in constant time `O(1)` as opposed to `O(N)` in a singly LL.
17 | - Inserting, removing from and searching a linked list should be fairly obvious and can be learned from code examples.
18 | - There is some mumbling about sentinels and I don't get it and I kinda don't care!
19 |
20 | ## Hash Tables:
21 | - A hash table supports the 3 basic operations: *insert, search *and *delete*. Inserts and deletes are generally `O(1)` in hash tables, and although searches can be as bad as `O(1)` as in linked lists, hash table search do generally approach `O(1)` especially in well constructed tables.
22 | - In a hash table, the position of a value (or its key) is computed using the value itself.
23 | - When the number of actual keys is small compared to the possible number of a table's keys, the table becomes effective in guaranteeing a constant time for the 3 operations aforementioned. A less effective has table suffers from *collisions* where more than one keys map to the same index. This can be mitigated using either *chaining* or *open addressing*.
24 | - A good hash table can be achieved with a good *hash function*. A hash function is used to extract a hash table's key from a given value.
25 |
26 | ### How Hash Tables Work:
27 | - To understand hash tables, it might be wise to first learn about *direct addressing*. Direct addressing is good way to guarantee `O(1)` speed for inserts, deletes and searches and it's practical if the range of possible values to be stored in a table is small. In a *direct-address table*, each slot (or bucket) corresponds to a key in the range of things we want to store. For example, if the range of possible values we are dealing with is 0 to 20, then we have a direct-address table of length 21 where 0 would be stored in position 0, element 3 would be stored in slot 3 ...etc. All the operations in such table have a constant time complexity. The problem is that such tables can only handle small ranges of possible values making them impractical for most applications although they perform well for situations where the possible ranges of values are small and already known.
28 | - Hash tables allow you to efficiently store a small range of values even if the range of possible range of values is so large and still be able to retrieve such values in an average time of `O(1)`.
29 | - Instead of mapping directly to an array's index as in direct-address tables, a function is used to map value to its slot in a hash map where is the size of the hash map is much much smaller than the universe of possible values than can be mapped into it.
30 | - Because we are mapping from a large universe of possible values to a small range, it possible and common that two values map to the same slot in hash table resulting in a **collision**. Collisions can be resolved by chaining or open addressing but it would be amazing if we could resolve collisions altogether.
31 | - Avoiding or minimizing collisions can be done through choosing a good hash function. A good hash function appears to be random. Collisions can't be totally avoided but can be minimized by a seemingly-random hash function.
32 |
33 | ### Chaining:
34 | - One way to handle collisions is through the use of chaining. When two or more values map to the same bucket in a hash table, a linked list is constructed and the keys are placed into it. The bucket holds a pointer to the linked list head.
35 | - Insert in a hash table with chaining is `O(1)` while search and delete can have a linear worst case. CLRS claims that if we use a doubly linked list, deletes would have constant worst case but I don't really understand how that's possible.
36 | - The worst case time of hashing with chaining can be `O(N)` if all the keys hash to the same slot resulting in an n-long linked list. Added to this is the time to compute the hashing function.
37 | - With a good hash function dictionary operations in a hash table with chaining should take an average `O(1)` time.
38 |
39 | ### Hash Functions:
40 | - It's all about hash functions, gov'na! A good hash function is one that satisfies the asumption that each key is equally likely to map to any bucket. There is no way however to test such condition. Popular hashing schemes include the heuristic **hashing by division** and **hashing by multiplication** and the randomized **universal hashing**.
41 |
42 | #### 2. Hashing by Division:
43 | - In this method, the hash value is equal to the remainder of dividing the key *k* by the the size of the hash table *m* as in:
44 | ***h(k) = k mod m***
45 | - To get useful hash values avoid making *m* a power of 2. It's preferable to make *m* a prime number not close to a power of 2 to avoid many collusions!!!??
46 |
47 | #### 1. Hashing by Multiplication:
48 | - Hashing by multiplication is done through two steps:
49 | 1. The key *K* is first multiplied by a constant number *A* where *0 < A < 1* and the fractional part of this result is extracted.
50 | 2. The fractional part extracted from the previous operations is again multiplied by the size of the hash table *m* and the floor this operation is the hash value. This can be expressed as follows:
51 | ***h(k) = ⌊m (kA mod 1)⌋***
52 | - The size *m* of the hash table in not important but it's preferable that it be a power of two to make it easier for binary computers!!! And for other arcane and super-nerdy reasons!
53 | - The value of the constant *A* is also unimportant by the legendary Knuth suggests that it be equivalent to***(√5 - 1) / 2*** and God knows why!
54 |
55 | #### 3. Universal Hashing:
56 | - In universal hashing, we using a random hashing function from a class of carefully designed hash functions. The randomly selected function is independent of the key to be stored. This generally results in good performance and little collisions.
57 | - We can construct a class of universal hash functions as follows:
58 | 1. We pick a value *p* which must be a a prime number larger than *m* the size of the wanted hash table and such that every key value *k* is in the range 0 to *p* - 1.
59 | 2. We pick two values *a* such that *0 < a < p -1* and *b* such that *1 < b < p -1*
60 | 3. We now define a function *hab* as follows:
61 | ***hab(k) = ((ak + b) mod p) mod m***
62 | - There is talk of number theory and some big words and I have no clue!!! Might come back to this after a course on discrete math!
63 |
64 | ### Open Addressing:
65 | - In addition to chaining, **open addressing** is used to resolve collisions. We use to this technique to store all the elements of a hash table in the array itself without resorting to external (or internal) linked lists. In open addressing, when a collision occurs, we search for the next open slot somewhere else in the table itself until we find such slot and insert the element. This might result in filling up the table. ("The load factor *α* can never exceed 1"). I think the load factor means the elements in the table divided by the size *m* of the table.
66 | - The advantage of open addressing lies in the fact that pointers are not used. Pointers eat up too much memory and eliminating them results in the ability to place more data in the same amount of space which might also lead to fewer collisions and faster data retrieval (CLRS). We also have the potential to make full use of the space available in the array itself.
67 | - In open addressing, we successively examine each slot in the table until we find an empty one and fill it with the given element. I don't know exactly if the probing start at slot 0 in the table or start with the slot directly following the current slot and wraps around when the end of the table is reached! These might be just implementation details, but the general idea is to follow a consistent scheme for searching an open slot to insert or retrieve data.
68 | - Deleting elements in open addressing can be confusing, so it is better to mark deleted elements as deleted instead of making them a `null`. Not sure if I understand the previous sentence!
69 | - There are three common probing schemes in use:
70 | * **Linear probing**
71 | - Linear probing can be done with the following function:
72 | ***h(k, i) = (h'(k) + i) mod m***
73 | where:
74 | + *m* refers to the size of the table as usual.
75 | + *i* is a number between 0 and *m* - 1. The probing function will be run in a loop with i increasing with each iteration so that the first probe will examine *T[h'(k)]* where T refers the table, the second iteration is *T[h'(k) + 1]* and this will continue until we reach the end of the tble at *T[h'(k) + m - 1]*. At this point we wrap around and start at slot *T[0]* and continue until we reach slot *T[h'(k) - 1]*.
76 | + *h* is called an *auxiliary hash function* in this context. It's the actual hashing function that determine where the pre-collision slot is located.
77 | - The problem with linear probing is that it results in **primary clustering**. Long clusters of occupied slots build up in the table increasing search time.
78 | * **Quadratic probing**
79 | - Quadratic probing can be done with the following function:
80 | ***h(k, i) = (h'(k) + c1i + c2i2) mod m***
81 | where:
82 | + *c1* and *c2* are some constants.
83 | - Quadratic probing generally results in better results with less clustering (it results in a form of clustering called **primary clustering** which is not as bad as primary clustering). A good choice of *m*, *c1*, and *c2* can lead to good results but that's voodoo I can't understand!
84 | * **Double probing**
85 | ***h(k, i) = (h1(k) + ih2(k)) mod m***
86 | - I don't quite understand what's going on here!
87 | - Anyways, the subsequent probes appear random and there is little to no clustering as in the previous two probing techniques.
88 |
89 | ### Perfect Hashing:
90 | - Hashing provides good average-case performance. **Perfect hashing** provides an excellent worst-case performance provided it is used with a fixed set of keys (something like reserved words in a programming language).
91 | - A form of hashing that guarantees an *O(1)* worst-case performance is a perfect hashing.
92 | - Perfect hashing is achieved with 2 levels of hashing using universal hashing in each level.
93 | - In the first level we construct a hash table similar to tables constructed with hashing with chaining but instead of a linked list we use a another hash table all while using universal hashing.
94 | - A slot from the first hash table points to a smaller hash table that also uses universal hashing. To avoid collisions in the secondary table, we need to make its size the square of the number of values that hash to the given slot. This might seem like an overkill for the amount of storage space it would eat up, but the CLRS folks prove that it's only *O(N)*.
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/algorithms/bst.md:
--------------------------------------------------------------------------------
1 | # Binary Search Trees:
2 | ## Binary Search Trees:
3 | - Trees are some of the most versatile
4 | - A search tree supports such varied operations as: *search, minimum, maximum, predecessor, successor, insert* and *delete*.
5 |
6 | ## Red-Black Trees:
7 | - While a generic binary search tree can, just can and are supposed to support operations in _O(h)_ time. this is not guaranteed! A tree is useful if its height is not too large, otherwise it becomes just a clunky linked list slugging at a _O(n)_ time. To guarantee an _O(h)_ speed, we need to balance our BST. Several schemes are devised to balance a search tree including the famous AVL trees and **red-black trees**.
8 |
9 | ### Properties of Red-Black Trees:
10 | - Each node in a red-black tree has an extra bit of storage for the node's *color* which can be either red or black. Coloring a tree in this manner ensures that any path from the root to a leaf is no bigger than twice the length of any other path making the tree approximately balanced.
11 | - Nodes which don't have parents or children have pointers to NIL values. These are leaves or **external nodes**, while nodes with non-NIL parent and children pointers are considered **internal nodes**
12 | - Generally speaking a red-black tree is a binary tree with the following characteristics:
13 | 1. Every node is either red or black
14 | 2. The root is black.
15 | 3. Every leaf (NIL node) is black.
16 | 4. If a node is red, both its children are black.
17 | 5. For each node, the paths from it to each of its descending leaves contain the same number of black nodes.
18 | - A **sentinel** node can be used to replace the NIL values to better avoid boundary issues. This sentinel will replace all the NIL child values at the leaves and NIL value of the root's parent. This way all the nodes will treated as regular nodes and "null pointer" errors will be avoided.
19 | - The number of black nodes in a simple path from but not including a node _x_ down to a leaf is called the **black height** and is denoted by *bh(x)*. The black height of a tree is the black height of its root.
20 | - Should you really need to prove that the height of a red-black tree is _2lg(bh(T) + 1)_, give that that _T_ is for tree and _bh(...)_ is for black height as mentioned before.
21 |
22 | ### Rotation:
23 | - *Insert* and *delete* operations in a red-black tree with *n* keys take *lg(n)* time. These operations might also violate the red-black tree properties because they modify the tree. To restore the properties of the red-black tree, we need to change the color of some nodes and modify the pointer structure.
24 | - The pointer structure can be changed with **rotation**. Rotation leads to preserving the properties of a red-black tree. The following diagram shows the two types of rotation that can be performed on a subtree in a red-black tree:
25 | ```
26 | z Left rotation x
27 | / \ <------------ / \
28 | x γ α z
29 | / \ Right rotatation / \
30 | α β ---------------> β γ
31 | ```
32 | - When we do a **left rotation** around node `x`, it's assumed that its right side `z` is not a NIL. A left rotation can be performed on any node `x` in the tree whose right child is not NIL. `z` replaces `x` as the new root of the subtree. `x` becomes the left child of `z` and `β` becomes the right side of `x`.
33 | - A right rotation is symmetrical to the left rotation. `x` becomes the root of the subtree and it's assumed the left child of the subtree's root is not NIL.
34 | - The following snippet shows how left rotation is done:
35 |
36 | ```py
37 | def leftRotate(tree, x):
38 | z = x.right
39 | x.right = z.left
40 | if z.left is None:
41 | z.left.p = x
42 | z.p = x.p
43 | if x.p is None:
44 | tree.root = z
45 | elif x is x.p.left:
46 | x.p.left = z
47 | else:
48 | x.p.right = z
49 | z.left = x
50 | x.p = z
51 | ```
52 |
53 | ### Insertions:
54 |
55 | ```py
56 | def rbInsert(tree, z):
57 | y = None
58 | x = tree.root
59 |
60 |
61 | ```
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/language_compilation/bytecode.md:
--------------------------------------------------------------------------------
1 | # Bytecode:
2 | ## Table of Contents:
3 | ## Bytecode:
4 | ### Why Bytecode:
5 | - Walking the AST as demonstrated in jlox is simple and easy to implement and is also potable as it can run on any platform where Java runs. However, this approach is slow and extremely memroy inefficient. The tree contains a bunch of pointers scattered all over heap memory and each node consumes a lot of this memory. There is basically no good use of spatial locality and hence cache.
6 | - A language can also be designed so it compiles directly to the metal. This results in extremely fast and efficient code as this code is simple and very low level. The problem with machine code is that its hard and modern processor have very complex and diverse architectures. Designing a language that compiles to machine code needs a lot of specialization and familiarity with the target architectures. Such a language is also not portable across processors.
7 |
8 | ### What Bytecode Is:
9 | - **Bytecode** is a middle-of-the-road solution that tries to combine the simplicity and portability of walking the AST on the one hand, and the speed and memory efficiency of machine code.
10 | - bytecode is basically an emulation of machine code which is "dense, linear sequence of binary instructions." It is cache friendly with low overhead. However, it doesn't run directly
--------------------------------------------------------------------------------
/language_compilation/compilation.md:
--------------------------------------------------------------------------------
1 | # Compilers and Interpreters:
2 | - High level languages such as C and Python cannot be understood by computers. We must translate the C and Python source code into something that a machine can make use of. This is done by **compilers** and **interpreters.** These are different types of programs but they are also similar in many ways which we will see later. In this summary, we will see the different steps taken to translate human readable code into something machines can understand and execute (we will also see how high-level lanugages are also translated to other high-level languages).
3 |
4 | ## Scanning:
5 | - The first step in comilation/interpretation is called **scanning** (or **lexing** or even **lexical analysis**). It basically turns a stream of characters into **tokens** which can be composed of one or more characters. Let's look at how the following C line would be lexed:
6 | ```c
7 | // This is a program
8 | int average = (min + max) / 2;
9 | ```
10 | - This line consists of this stream of characters : (**`/`**, **`/`**, **` `**, **`T`**, **`h`**, **`i`**, **`s`**, **` `**, **`i`**, **`s`**, **` `**, **`a`**, **` `**, **`p`**, **`r`**, **`o`**, **`g`**, **`r`**, **`a`**, **`m`**, **`i`**, **`n`**, **`t`**, **` `**, **`a`**, **`v`**, **`e`**, **`r`**, **`a`**, **`g`**, **`e`**, **` `**, **`=`**, **` `**, **`(`**, **`m`**, **`i`**, **`n`**, **` `**, **`+`**, **` `**, **`m`**, **`a`**, **`x`**, **`)`**, **` `**, **`/`**, **` `**, **`2`**, **`;`**, **` `**, **` `** ) which seems kinda incomprehensible even for a human. We need to turn them into the smallest meaningful individual units such as operator symbols, variable names and key words and ignore all white space such as new line and tabs, etc. This stream of characters will then be lexed into (
11 | **`int`**, **`average`**, **`=`**, **`(`**, **`min`**, **`+`**, **`max`**, **`)`**, **`/`**, **`2`**, **`;`**).
12 |
13 |
--------------------------------------------------------------------------------
/networking/datatransfereliability.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/datatransfereliability.png
--------------------------------------------------------------------------------
/networking/dnslevels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/dnslevels.png
--------------------------------------------------------------------------------
/networking/dnsmessageformat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/dnsmessageformat.png
--------------------------------------------------------------------------------
/networking/gbn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/gbn.png
--------------------------------------------------------------------------------
/networking/img/2Dparity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/2Dparity.png
--------------------------------------------------------------------------------
/networking/img/ASRIP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/ASRIP.png
--------------------------------------------------------------------------------
/networking/img/DNSCDN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/DNSCDN.png
--------------------------------------------------------------------------------
/networking/img/IGMPnMCRP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/IGMPnMCRP.png
--------------------------------------------------------------------------------
/networking/img/LANMACs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/LANMACs.png
--------------------------------------------------------------------------------
/networking/img/SSLrecord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/SSLrecord.png
--------------------------------------------------------------------------------
/networking/img/TCPHTTPStreaming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/TCPHTTPStreaming.png
--------------------------------------------------------------------------------
/networking/img/TLS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/TLS.png
--------------------------------------------------------------------------------
/networking/img/VCNetwork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/VCNetwork.png
--------------------------------------------------------------------------------
/networking/img/VCSetup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/VCSetup.png
--------------------------------------------------------------------------------
/networking/img/VPN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/VPN.png
--------------------------------------------------------------------------------
/networking/img/almostSSLHandshake.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/almostSSLHandshake.png
--------------------------------------------------------------------------------
/networking/img/blockCipher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/blockCipher.png
--------------------------------------------------------------------------------
/networking/img/cNGraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/cNGraph.png
--------------------------------------------------------------------------------
/networking/img/cbSpanningT.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/cbSpanningT.png
--------------------------------------------------------------------------------
/networking/img/cdmaEncDec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/cdmaEncDec.png
--------------------------------------------------------------------------------
/networking/img/clientPlayoutDelay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/clientPlayoutDelay.png
--------------------------------------------------------------------------------
/networking/img/cyptcomponents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/cyptcomponents.png
--------------------------------------------------------------------------------
/networking/img/datagramNetwork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/datagramNetwork.png
--------------------------------------------------------------------------------
/networking/img/dhcpClientServer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/dhcpClientServer.png
--------------------------------------------------------------------------------
/networking/img/dhcpProcess.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/dhcpProcess.png
--------------------------------------------------------------------------------
/networking/img/dualStack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/dualStack.png
--------------------------------------------------------------------------------
/networking/img/duplication.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/duplication.png
--------------------------------------------------------------------------------
/networking/img/eBGP_iBGP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/eBGP_iBGP.png
--------------------------------------------------------------------------------
/networking/img/edc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/edc.png
--------------------------------------------------------------------------------
/networking/img/ethernetFrame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/ethernetFrame.png
--------------------------------------------------------------------------------
/networking/img/hiddenTerminals.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/hiddenTerminals.png
--------------------------------------------------------------------------------
/networking/img/hopCount.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/hopCount.png
--------------------------------------------------------------------------------
/networking/img/inernetNetworkLayer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/inernetNetworkLayer.png
--------------------------------------------------------------------------------
/networking/img/inputPortProcessing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/inputPortProcessing.png
--------------------------------------------------------------------------------
/networking/img/interConnectedASs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/interConnectedASs.png
--------------------------------------------------------------------------------
/networking/img/interfaceAddressSubnet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/interfaceAddressSubnet.png
--------------------------------------------------------------------------------
/networking/img/interleaving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/interleaving.png
--------------------------------------------------------------------------------
/networking/img/ipFragReass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/ipFragReass.png
--------------------------------------------------------------------------------
/networking/img/ipv4Datagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/ipv4Datagram.png
--------------------------------------------------------------------------------
/networking/img/ipv6DgFormat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/ipv6DgFormat.png
--------------------------------------------------------------------------------
/networking/img/ipv6Tunneling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/ipv6Tunneling.png
--------------------------------------------------------------------------------
/networking/img/linkHops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/linkHops.png
--------------------------------------------------------------------------------
/networking/img/linkLayerACK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/linkLayerACK.png
--------------------------------------------------------------------------------
/networking/img/mcRoutingAlgos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/mcRoutingAlgos.png
--------------------------------------------------------------------------------
/networking/img/monoalphabetic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/monoalphabetic.png
--------------------------------------------------------------------------------
/networking/img/multicastGroup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/multicastGroup.png
--------------------------------------------------------------------------------
/networking/img/nat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/nat.png
--------------------------------------------------------------------------------
/networking/img/network4Switches.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/network4Switches.png
--------------------------------------------------------------------------------
/networking/img/outputPortProcessing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/outputPortProcessing.png
--------------------------------------------------------------------------------
/networking/img/polyalphabetic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/polyalphabetic.png
--------------------------------------------------------------------------------
/networking/img/publicKeyEnc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/publicKeyEnc.png
--------------------------------------------------------------------------------
/networking/img/routerArch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/routerArch.png
--------------------------------------------------------------------------------
/networking/img/routerSubnets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/routerSubnets.png
--------------------------------------------------------------------------------
/networking/img/routingAlgoForwardingTable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/routingAlgoForwardingTable.png
--------------------------------------------------------------------------------
/networking/img/rtsCts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/rtsCts.png
--------------------------------------------------------------------------------
/networking/img/senderRecIntruder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/senderRecIntruder.png
--------------------------------------------------------------------------------
/networking/img/spanningTree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/spanningTree.png
--------------------------------------------------------------------------------
/networking/img/switchingTechniques.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/switchingTechniques.png
--------------------------------------------------------------------------------
/networking/img/twoSenderCDMA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/twoSenderCDMA.png
--------------------------------------------------------------------------------
/networking/img/webPageRJourney.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/webPageRJourney.png
--------------------------------------------------------------------------------
/networking/img/wifiFrame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/wifiFrame.png
--------------------------------------------------------------------------------
/networking/img/wifiLANArchitecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/img/wifiLANArchitecture.png
--------------------------------------------------------------------------------
/networking/journeymail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/journeymail.png
--------------------------------------------------------------------------------
/networking/lowlevel.md:
--------------------------------------------------------------------------------
1 | # Notes on Low Level Networking:
2 | ## Physical Layer:
3 | - Messages are send through a wire using a signal of some sort, maybe an alternation of different voltage levels (let's say between 0V and 5V). The trick is in timing. You can have 2 seconds of 5V, 1 second of 0V, 5 seconds of 5V, 4 seconds of 0V. Your 5V and 0V are called **symbols**; they are used to represent information of sorts: 1 bit for example can be represented by 5V and 0Vs is used to represent a 0 bit.
4 | - The rate at which the symbols are sent is called the **symbol rate**. Symbol rate of 1 signal per second is a 1 **baud** symbol rate. 10 symbols per second is 0.1 baud.
5 | - Information can be shared in network using a variety of ways including **copper wire**, **fiber optics** where a beam of light keeps getting reflected through two layers of fiber glass until it reaches the other end. **RF** (radio frequency) uses something similar which I don't understand, but generally speaking you alternate between two symbols which get converted by the machine to a binary format??!!
6 | - It common for computers to have different clock rates which means they can't communicate correctly. Communication between the two results in **clock slips** if the sending computer is faster than the receiving machine or extra bits vice-versa. Multiple ways are used to achieve a **synchronized clock** between different computers in order to communicate correctly: they include **GPS antennas** (GPS satellites have atomic clocks that can be used to synchronize machines), the machines themselves can have **atomic clocks**, but these are expansive and largely unpractical solutions. You might also have two wires one for the data and the other for clock rate so that the sending computer's clock rate is used by the receiver to read the data accurately, but this technique is also mired with problems.
7 | - A smarter workaround combines both the data and the clock rate, but uses different symbols. Instead of having 0V represent 0 and 5V represent 1, a 0 is represented by a transition from 5V to 0V and a 1 is represented by a transition from 0V to 5V. This is called **Manchester coding**.
8 |
9 | ## Framing:
10 | - The data a machine sends or receives is just a string of 1s and 0s and there is no way for machine to know exactly how start reading it. Where does a letter or number start or end? Does a binary string represent one small number or two? To solve this problem we use **framing** which a way of delimiting data before it's sent. There are several framing schemes that divide data into **frames** (which usually are around 1000-bite long). There are different framing protocols such as:
11 | 1. **HDLC (High Level-Data Link Control)**: In this protocol each frame starts with a **flag** which follows the pattern **`01111110`**. There are cases where a sequence of bits are similar to the flag even though they are not meant to signal the beginning of a new frame. In such cases the protocol stuffs an extra zero after each string of 5 ones in what's called **bit stuffing**. The receiver will ignore every zero that follows 5 one bits. THis way, it knows exactly that a flag is the start of a new frame.
12 | 2. **Ethernet** frames are kinda more elaborate. They are separated by a silent gap of zeros (no signal) which is required to be at least 96 bits in length. This is called an **IFG (Inter-frame Gap)**. Following the IFG is a **preamble** of 56 bits which is the start of a frame it's a pattern of ones each followed by a zero **`10101010101010101010101010101010101010101010101010101010`**. The preamble is followed by the **SFD (Start of Frame Delimiter)**. THe SFD is one byte that has alternating 1s and 0s just like the preamble except for the last bit which is a one instead of a 0: **`10101011`**. Following the SFD comes the data which is a combination of payload and meta-data which we will see later. The size of a frame tends to be between 64 and 1500 bytes. It's not recommended to have very large frames because errors are always a possibility and in the case of an error we don't want to resend a very large frame. In the case of reasonably sized frames we might only need to resent a small amount of data to recover from an error. There are situation where large frames (called **jumbo frames** of 9000 bytes are used).
13 | - Frames are a **data link layer** concept. There two main data link types, **PTP (point to point)** and **multi-point** or **broadcast** data links. PTP is where to computers talk directly to each other. A computer simply put data into frames and send them directly to another. This is mainly used by ISPs where networking equipment in different cities are linked through PTP and where fiber glass might usually be used. They cover large distances. Multipoint data link is where data is broadcast to the whole network where each computer in the network can receive the data sent by our computer. Examples of a multi-point data link include a wireless network where all computers can communicate directly with each other, a cable residential broadband network, and Ethernet network.
14 | - An Ethernet frame generally follows this format (called **Ethernet Logical Link Control (LLC)**):
15 | ```
16 | +----------------+---------------+-----------+----------+--------------/ /--+-----------------+
17 | | Preamble/SFD | Destination | Source | Ether | Payload | Frame Check |
18 | | | Address | Address | Type | Payload | Sequence |
19 | +----------------+---------------+-----------+----------+--------------/ /--+-----------------+
20 | 8B(7B/1B) 6B 6B 2B Varies 4B
21 | ```
22 | - The **destination address** and **source address** are called Ethernet Addresses or **Mac Addresses**. These are unique addresses built into the hardware of a computer. They look as follows: **`01:0D:F2:23:AA:0E`**. To send a message to another computer in the same Ethernet network, the destination address of the computer you wanna send to is placed in the destination address of the frame and the source in source address. The data is then sent to the Ethernet switch of the network which will forward it to the destination computer if it has its address. If doesn't have that address, it sends it to all computers in the network. The computer whose address matches the message's destination address will read it and other computers just ignore it. To send the data to all other computers in the network the destination address should have the address **`FF:FF:FF:FF:FF:FF`**.
23 | - The **`Ether type`** is a 2 byte field that gives information on the format of the payload of the frame. The most common Ether type is IP (an Internet packet) that has the value **`0800`**.
24 | - The **payload** is the content itself and other stuff. Its size has a usual upper limit of 1500 bytes but can be as big as 9000 bytes as in the case of the aforementioned jumbo frames.
25 | - The **Frame check sequence** (4 bytes) is a number computed based on the content of the frame (from the destination source to the payload). The receiving computer recomputes this number and if it doesn't match the received number it detects an error.
26 | - Other data link protocols have different frame formats such the PPP format which we will not cover here!
27 |
28 | ## Layers:
29 | - In the last two sections we touched on the bottom two networking layers (in both the **OSI** and **TCP/IP** models).
30 | - The **physical layer** has to do with the physical properties of networks and how signal is transmitted through these. These include copper wire, fiber optics and radio frequency. We also covered methods of synchronizing clocks and data encoding between computers in what is called Manchester code. There are equivalent methods in other media such as **QAM** and **NRZ**.
31 | - The **data link** is all about framing and data format. We covered two widely used data links protocols Ethernet which uses preambles and SFDs to delimit frames and HDLC which uses flags instead. We also covered the Ethernet frame format (called Ethernet LLC (logical link control)) and mentioned the PPP LLC.
32 |
33 | ## The Internet Protocol:
34 | - How would a computer in an Ethernet network in Bangalore communicate with another computer in an Ethernet network in Lucknow?
35 | - Most probably Lucknow is connected to Bangalore through multiple PPP links. A PPP node can only send data to another PPP node that is directly connected to it. How can data be forwarded between the different PPP links?
36 | - Let's call our source computer host A and our destination host B. When host A sends data, none of the computers in the Bangalore network will receive it because none of them has the destination address specified in the frames sent by host A. Another problem is that the PPP links don't understand mac addresses. To solve this problem we need a universal address that is not specific to a certain type of link. The solution is the **Internet Protocol (IP)** which is a protocol used to connect multiple networks.
37 | - The PPP nodes are also **IP routers**. The IP router connected to the Bangalore network will receive a packet containing a destination IP address and then decides which route it forwards to. When the routing decision is made the message is encapsulated into a PPP frame that will be send to the specified PPP node.
38 | - Routers serve two purposes:
39 | 1. **Routing** which is the process of building **routing tables** which map IP addresses to routes.
40 | 2. **Forwarding** is the actual transfer of the packet from one router to another until the packet reaches its destination.
41 | - An IP address is a 32-bit value. There are 232 possible IP addresses (about 4 billion). The protocol geeks were afraid we'd run out of IP addresses so they add another IP address scheme called IPv6 to mitigate their fears. This one has 2128 possible IP addresses.
42 | - The router does a lot of hard work but it doesn't have to store all 4 billion IP addresses in its routing table. It can just store the first 2 bytes of IP ranges and the first 3 IP address ranges which correspond to other routers. It might store the actual addresses that are directly linked to it. The router will search its table and match the IP address it receives to the longest matching entry in its table.
43 |
44 | ## The Journey of a Packet over the Internet:
45 | - When trying to send data to Lucknow, the IP packet makes part of the the Ethernet frame payload. The destination address of this frame, however, is not the final destination but is the first router the message needs to go to. The sender doesn't automatically know the MAC address of this router. The computer has to somehow be configured to know the IP address of the router. The sender will first check if destination IP against the subnet mask (the 24-bit significant range of an IP address) and if it is not there, the packet will be sent to the router.
46 | - Before sending the frame to the router, however, host A needs to discover the router. The host broadcasts to all other computers in the network asking if they have the router's IP address and if so send back a response containing the mac address of the router. This is called **Address Resolution Protocol (ARP)**. ARP is the payload of the Ethernet frame (whose Ether type is **`0806`** meaning that the payload is of type ARP) and it looks as follows:
47 | ```
48 | +------------+-----------+----------+----------+-----+--------------+---------------+---------------+---------------+
49 | | HW Address | Protocol | HW Addr | Protocol | Op | Hardware Addr| Protocol Addr | Hardware Addr | Protocol Addr |
50 | | Type | Addr Type | Length | Addr Len | Code| of Sender | Of Sender | Of Target | Of Target |
51 | +------------+-----------+----------+----------+-----+--------------+---------------+---------------+---------------+
52 | ```
53 | - The different segments of the ARP packet have the following meanings:
54 | * **HW address Type**: this is usually **`1`** because we are using Ethernet (The protocol we want to map to).
55 | * **Protocol address Type**: most probably **`0800`** since we are trying to map hardware address to the IP protocol.
56 | * **HW address Length**: most probably **`6`** for Ethernet (Mac Addresses are 6 bytes in length).
57 | * **Protocol address Length**: matches IP address length which is **`4`** bytes (for IPv4).
58 | * **Op Code**: can be either a **`1`** or **`2`**. 1 for a broadcast question when host A is searching for the router, and 2 when the host A receives a response from the router telling it that it has the given hadrware address.
59 | * **HW address of Sender**: Mac Address of the sender
60 | * **Protocol address of Sender** IP Address of the sender.
61 | * **HW address of Target** ...
62 | * **Protocol address of Target** ...
63 | - Basically, if the IP address is not in the subnet mask, host A broadcasts an Ethernet frame whose payload is an ARP packet. The ARP asks "who owns the router's IP?". The router responds with a frame that also containing an ARP packet where it gives its MAC address to the host A. Now that host A has the MAC address of the router it can send it what it wants.
64 | - Now that host A has successfully located the router, it sends it a frame with Ether type **0800** meaning it is a frame of type IP. The payload of this frame contains an IP packet which consists of a an **IP header** which has some information about the IP packet and some of kid of body or payload.
65 | - The header of an IP packet is usually made of 5 or 6 32-bit words which contain information on how the IP packet should behave in the network. Important information in the header include the IP version (IPv4 or IPv6), the time to live (to prevent the packets from looping forever in the Internet), the source and destination addresses, the header checksum for error checking, the protocol field which indicates the type of the protocol inside the IP's body ... etc.
66 | - Once our packet reaches the first router it will hop from one router to another following a path set to it by the routing tables of each router until it reaches the final router where the destination IP address is detected. Now this router will do some ARP voodoo and asks for the Mac address of the computer that has that IP address and then it goes there.
67 |
68 | ## TCP:
69 | - There is only so much data you can fit inside a data link frame which means you have to split that data into multiple packets which you stuff inside the frames. Data sent in chunks stuffed inside multiple frames are not always guaranteed to arrived safe to the destination IP address. There is a very high chance many of these packets get lost in the way due to multiple reasons in the physical or other layers such routers or links between routers becoming congested. Losing packets means we might get incomplete garbage data on the other end of the communication line. Packets might also arrive not in the order they were sent because they might have taken different routes. **Transmission Control Protocol (TCP)** is the savior here. It provides a **byte stream service** that is **connection oriented** and **reliable**. It kinda mimics a phone call. It involves a **handshaking** which establishes that two computers can talk to each other before they can send data to each other.
70 | - The TCP segment itself is encapsulated inside an IP datagram. It, too, has a header which contains important data about how it travels through the network. The IP protocol number for TCP is **`6`**.
71 | - The **source port** and **destination port** are important TCP headers. A computer can connect to the rest of the world through multiple **ports**. These two headers tell ports apart. TCP connections are also bidirectional. TCP also provides its own **checksum** to account for errors.
72 | - When two computers are communication using TCP, the computer that initiates the connection is called the client and the other is the server but once the connection is established data starts flowing in both directions. TCP needs two pieces of information, the IP address and the port number as in **`127.0.0.1:3000`**.
73 | - I will cover more of TCP in other articles.
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/networking/mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/mail.png
--------------------------------------------------------------------------------
/networking/networking-and-internet.md:
--------------------------------------------------------------------------------
1 | # Networking and Internet: an Overview:
2 | ## Table of Contents:
3 | * [Table of Contents](#table-of-contents)
4 | * ["I heard there is rumors on the Internets"](#i-heard-there-is-rumors-on-the-internets)
5 | * [Network Edge](#network-edge)
6 | + [A Primer on Physical Media Used in Networking](#a-primer-on-physical-media-used-in-networking)
7 | * [Network Core](#network-core)
8 | + [Packet Switching](#packet-switching)
9 | + [Circuit Switching](#circuit-switching)
10 | * [Delay, Loss and Throughput in a Packet-Switched Network](#delay-loss-and-throughput-in-a-packet-switched-network)
11 | + [Delay](#delay)
12 | + [Packet Loss](#packet-loss)
13 | + [End-to-End Delay and Others](#end-to-end-delay-and-others)
14 | + [Throughput](#throughput)
15 | * [Protocol Layers and Models](#protocol-layers-and-models)
16 | + [Encapsulation in Networking](#encapsulation-in-networking)
17 | * [Network Security](#network-security)
18 | + [Networks as a Malware Delivery System](#networks-as-a-malware-delivery-system)
19 | + [The Network Infrastructure Itself Can Be Attacked](#the-network-infrastructure-itself-can-be-attacked)
20 | + [The sniffers](#the-sniffers)
21 | + [Spoofing](#spoofing)
22 |
23 | ## "I heard there is rumors on the Internets":
24 | - Let's just say that the Internet is a gigantic network that connects millions or billions of **end systems** or **hosts**. The network itself is made of many **communication links** which intersect at **packed switches** which can be either **routers** or **link-layer switches**. The data itself is encapsulated into **packets** which are smallest discrete quantities of data that can be transported through a network at a certain abstraction level.
25 | - The Internet is provided by **Internet Service Providers (ISPs)** which of which is "in itself a network of packet switches and communication links". ISPs are organized in some sort of a hierarchy. You have international and national ISPs and under those are residential ISPs, cable ISPs, university ISPs ...etc.
26 | - Communication in the Internet and in any kind of network indeed is controlled and regulated with **protocols** and there is a ton of these. Networking is all about the protocols, baby! Internet Standards are developed by the **Internet Engineering Task Force(IETF)** through so-called **Requests for Comments (RFCs)** which define the different Internet protocols.
27 | - From a programmer's perspective, the Internet is the infrastructure that allow **distributed applications** to exist. This type of application is not tied to a single computer. Instead it uses other computers to do its job.
28 |
29 | ## Network Edge:
30 | - We can think of the Internet and any network in general as consisting of an **edge** and a **core**. The edge is where end systems and hosts are. The computer on which this is being typed is part of the edge of the Internet and the home network it is connected to.
31 | - At the edge of the Internet are so-called **access networks**. An access network is one that connects an end system to the first router in the Internet. It sounds like home routers are not part of such routers.
32 | - Residential Networks get access to the Internet through several methods:
33 | + **Digital Subscriber Line (DSL)**: in a DSL both telephone data and Internet data are transmitted between the home network modem and the **DSLAM (DSL Access Multiplexer)**. This DSLAM combines signal from telephone lines and from data allows both to pass to the home network. This data is encoded in different frequencies. At home, they get split by a splitter and the modem extracts Internet data while phone data passes to the phone and there is no interference between the two as they are transmitted on different frequencies. DSL speed degrades as a function of distance from the DSLAM because it was optimized to work best in relatively short distances.
34 | + In **Cable** the Internet is transmitted through cable television lines. It usually employs a combination of fiber optics and coaxial cables. The **cable modem termination system (CMTS)** plays the same role in cable access as in DSLAM in DSL.
35 | + **Satellite** Internet.
36 | + **Dial up**: this one is especially painfully slow!
37 | - **Local Area Networks (LAN)** were restricted to corporates and universities but have gradually become used in home networks where DSL or Cable are combined with LAN technologies to create wired or wireless LAN networks.
38 |
39 | ### A Primer on Physical Media Used in Networking:
40 | - When a bit of information is sent from one end system to another it might morph into different forms as electrons moving through a wire or radio waves propagated in the air or as optic pulses in fiber-optic cable. These physical media can be divided into two types: **guided media** where bits are transmitted through solid media such as copper wire and **unguided media** where the data is propagated/broadcast in the air as waves for other systems to capture its signal.
41 | - Some of the popular physical media used in networking including:
42 | 1. **Twisted-Pair Copper:** These are used mainly for land line telephone. They consist of a pair of shielded copper wires twisted together to reduce interference from close-by electrical fields. Each pair is a single line of communication. These are popularly called Ethernet wires. One of form of these**Unshielded Twisted Pairs (UTP)** are used for computer networking. These are popularly called Ethernet cables. These usually have multiple pairs of wire. They can transmit data at a rate between 10 Mbps and 10Gbps. This rate is affected by the thickness of the wire and distance between the transmitter and receiver. This medium is inferior to fiber optics, but it is still in use and it's the de facto medium for LAN networks.
43 | 2. **Coaxial Cable:** is a pair of concentric shielded copper wires. The inner wire is a thick wire while the outer one is a mesh of shorts. They are used in television and cable and can achieve high transmission rates.
44 | 3. **Fiber Optics:** The data in these is transmitted through pulses of light. They result in very high bit rates and might not need any amplification for up to a 100 km. They are excellent for long distance links but are not very practical for LANs because the optical devices such as transmitters, switches and receivers are expansive.
45 | 4. **Terrestrial Radio Channels:** These are convenient for users as they require no wiring and are divided into 3 categories: those that operate over 1 or 2 meters (I can't think of an example), those that operate within a short distance such as wifi and those that operate over a long distance such as cell phone towers..etc.
46 | 5. **Satellite Radio Channels**: These can provide relatively high speed internet where there is no cable/DSL.
47 |
48 | ## Network Core:
49 | - The Internet core is the gigantic mesh of links and packet switches that connects end systems.
50 | - There are two ways data can be moved through communication links: **packet switching** and **circuit switching**.
51 |
52 | ### Packet Switching:
53 | - In packet switching messages are broken into packets, something like discrete amounts of bits, over communication links and packet switches (this can be either routers or link-layers switches). Transmitting such packets through multiple kinks and routers/switches involves so-called **store-and-forward**. Before a packet switch starts outputting the first bit of packet it receives, it must first receive the whole packet. After all, a switch/router must receive, store and process a packet before forwarding it. This results in some delay which is proportional to the number of links separating the communicating end-systems.
54 | - A packet switch usually have multiple links attached to it. For each link, the packet switch has an **output queue (or output buffer)**. The output queue is used to store packets if the link is too busy or congested with other packets (this link might have a slower rate or it might be targeted by multiple links at the same time). The time a packet might spend in this buffer is called **queuing delay**. The queuing buffer is of a finite size and if the number of packets exceeds that size, some packets will be dropped (**packet loss**). Packet loss might occur to either packets already in the buffer or new coming packets.
55 | - The way a router/switch decides what link to forward a packet to is done with **forwarding tables**. **Routing protocols** are used to dynamically populate forwarding tables.
56 |
57 | ### Circuit Switching:
58 | - This type of switching is based on reserving a path for exchanging bits. We mention it here only to tout the fact that packet switching is superior and much more scalable than circuit switching. It allows of a large number of simultaneous users of the network.
59 |
60 | ## Delay, Loss and Throughput in a Packet-Switched Network:
61 | - The finite physical nature of the Internet and networks in general constrains the **throughput** (he amount of data per second that can be transferred through the network) leading to delay and packet loss.
62 |
63 | ### Delay:
64 | - We've seen a couple types of delay earlier, but there are others which we will cover here in more detail. All these types of delay accumulate to produce what we called **total nodal delay**. The effects of delay can be clearly seen in real time systems such as in video chatting. Types of delay include (Remember that only one packet can be transmitted on a link at a time.):
65 | 1. **Nodal processing delay**: Routers do to main types of processing that cause delay in the order of microseconds or less. These are deciding which link to direct a packet to and checking if the packet has any errors. After that the packet is directed to the queue preceding the appropriate link.
66 | 2. **Queuing delay**: This is the delay a packet experiences while in a links queue. IF the queue is empty this delay is practically zero, but it is high if the queue is full.
67 | 3. **Transmission delay**: A packet can only be transmitted after all the packets that went before it have been transmitted. Transmission delay is equivalent to the transmission rate of a link (10Mbps, 1Mbps ... etc.) This can be in the order of microseconds and even milliseconds.
68 | 4. **Propagation delay**: This is related to the propagation speed of links. Some media might be faster than others. For example, fiber optics are much faster than copper wires. The propagation delay is tied the distance of a link divided by the propagation rate of the link's medium.
69 | - Propagation delay might be confused with transmission delay, but they are different. Propagation is more related to the distance of the link while propagation is related to how much data is being transmitted through the link (packet size and how data a link can transmit at a time).
70 |
71 | ### Packet Loss:
72 | - Queuing delay is an interesting beast and many PHDs and books were written about. It's mired in uncertainty as it depends on multiple factors such as packet sizes. Different packets will suffer from different queuing delay. Statistics and probability rules are used to measure queuing delay. The main side effects of queuing delays is packet loss. The size of a queue is finite and if a packet arrives at a full queue it gets dropped and lost in the core abyss!
73 |
74 | ### End-to-End Delay and Others:
75 | - **End-to-end** refers to the total delay between end systems. What we have looked at earlier was nodal delay which is delay in a single node between a computer and a router or between two routers. This type of delay can be examined using the famous **traceroute** utility.
76 | - Other types of delay include delays caused by end systems themselves. End systems might throttle the rate at which they send data to a shared network to not congest it. Some applications such those using the VoIO protocol for video/voice chatting might take a very long time packetizing data hence causing so called packetization delay.
77 |
78 |
79 | ### Throughput:
80 | - Throughput is generally the amount of data per second that can b transmitted between two end systems. Through can be subdivided into two types: **instantaneous throughput** which we can use to describe for example the right at which a file is being downloaded at a specific moment in time. The **average throughput** is the rate in bits per seconds at which an entire file is downloaded.
81 | - Throughput seems very similar to transmission rate, but throughput is a combination of all overhead and other rates, not just the pure transmission rate of the link.
82 | - Throughput might not be so obvious in a multi-link network where links have different throughput. Generally speaking the throughput in an end-to-end path is capped by the rate of the **bottleneck link** (the link with the lowest throughput).
83 | - Today access networks are the real bottleneck! The core of the Internet operates at a very high speed.
84 | - Another important consideration about throughput is when a link is linked to many links whose total throughput is larger than that link, then the throughput of that common link average throughput of all the links that feeds the common link. I hope that makes sense!!
85 |
86 | ## Protocol Layers and Models:
87 | - Networks are extremely complicated. Fortunately we have we use models to organize and simplify our knowledge about the structure and many components, protocols and technologies of networking.
88 | - One great way of describing networking is the so-called layered architecture. Networking in general and networks are described into terms of layers of things. These layered models allow for modularity as parts of a complex system can be changed without affecting the overall system. They also allow us to discuss specific parts of a system without having to bother or be confused by what lies in other layers.
89 | - Networking protocols are organized in simple layered models that do a great job at simplifying the dizzying nature of networks and allowing for easy understanding of how protocols (be they hardware or software protocols) do their job and interact with other protocols in other layers.
90 | - One very popular layered networking model is the **seven-layer ISO OSI reference model**:
91 |
92 |
93 |
94 | Application |
95 |
96 |
97 |
98 | Presentation |
99 |
100 |
101 |
102 | Session |
103 |
104 |
105 | Transport |
106 |
107 |
108 | Network |
109 |
110 |
111 | Link |
112 |
113 |
114 | Physical |
115 |
116 |
117 |
118 | - Another popular model which today's de facto model is the **five-layer Internet protocol stack**:
119 |
120 |
121 |
122 | Application |
123 |
124 |
125 | Transport |
126 |
127 |
128 | Network |
129 |
130 |
131 | Link |
132 |
133 |
134 | Physical |
135 |
136 |
137 |
138 | - Some people are opposed to protocol layering arguing that it introduces repetition such as the fact that indeed multiple protocols on different layers check for errors while this checking could have been done in just one layer. Interdependence between protocols from different layers kinda beats the purpose of layering which seems contrived and artificial.
139 | - Layers be layering:
140 | + **Application**: This is where protocols of specific applications exist. Here you have HTTP for web page applications, SMTP for email, DNS for website names, FTP for file transfer..etc. You can define your own protocols for your applications here use use the existing protocols. This layer's packets are called **messages**.
141 | + **Transport**: packets here are called **segments** and this layer is all about transport. It breaks large application messages into manageable segments to transport them through the network. It has the two famous protocols **TCP** and **UDP**. TCP provides and connection-oriented type of transport and strives to establish reliability and recovery of lost segments and prevention of congestion. UDP just sends segments and doesn't care about too much control.
142 | + **Network**: Packets are called **datagrams**. This layer acts like a postal service. The transport layer passes it information about the destination of the transport segment and this takes care of carrying the segment to the appropriate end-system. It includes the **IP** protocols which tells it where to forward the datagram and many types of **routing protocols** which guide the journey of a datagram.
143 | + **Link**: The network needs the assistance of the link layer to move the datagram (which gets wrapped in a link layer **frame**) through a link. There are several link layer protocols such as Ethernet, WiFi, cable's DOCSIS and PPP. The same frame might be handled by different protocols before it reaches its final destination.
144 | + **Physical**: Here individual bits move in the form of electrons, light pulses or radio waves through coaxial cable, UTP, fiber optics or air/the void. This layer's protocols are tied to the link layer's protocols, for example, Ethernet is both a link layer and physical layer protocol.
145 |
146 | - The **OSI** model is old and respected. It's mostly the same as the 5-layer Internet stack, except for two layers: the **presentation layer** which deal with application specific features such as compression and encryption, and the **session layer** which handles data synchronization and delimiting between applications. The Internet stack removes these two layers and delegates the responsibility of implementing them the app developer if she sees need for them.
147 |
148 | ### Encapsulation in Networking:
149 | - when you send a piece of data through the Internet or any other network, it moves up and down the network stack depending on multiple circumstances. This movement up and down the stack happens at different depths depending on the node: They can move through the whole 5 layers in an end system but can only travel through the 3 bottom layers in a router because those are all the layers a router needs to be useful. In a link-layer switch data moves up and own only the first 2 bottom layers. The following figure shows the steps of such a journey:
150 | 
151 | - An important concept that allows for this interlayer interaction **encapsulation**. Upper layer data is encapsulated in lower layer packets: meaning that a layer receives a packet from the layer above it, adds its **header** information to the received packet, thus constructing a packet of its kind.
152 | - In the 5-layer Internet stack, an application layer message is passed down to the transport layer which adds transport layer header information to the application message thus turning it into an application layer segment. The transport header information allows the packet to be directed to the right application in the end system and checks for errors and maybe allows for reliability in the case of TCP. The segment is then passed to the network layer where it becomes the payload of a an IP datagram. It receives source and destination information which allows it to be routed to its final destination. The datagram is then encapsulated into a link layer frame which allow it to move through the a link the appropriate next node. Frames themselves are carefully arranged bit patterns that move through the underlying hardware. When the frames are received by the application in the destination end system, they are reassembled and reconstructed back into the original messages that were sent by the original end system.
153 | - This was a very brief and simplified overview of how a message moves through the network. In reality, there is much more to this process. One important process that take place in data's journey through the network is splitting large messages into smaller chunks that can be fitted inside a segment and breaking a segment up to parts that can be encapsulated inside datagrams... etc.
154 | - The following [figure](https://en.wikipedia.org/wiki/Internet_protocol_suite#/media/File:IP_stack_connections.svg) at Wikipedia is an excellent illustration of how encapsulation works in general.
155 |
156 | ## Network Security:
157 | - Networks are vulnerable to many attacks that might target the hosts connected to it, its users and the network itself. The attackers might want to damage the networks, the hosts or invade the privacy of the users. The network engineer must strive to find out how such attacks are carried out, defend the network and its users against such attacks and think of ways to design networks that are immune to such attacks. Network security is an important field and this section provides an overview of common network security threats.
158 | - The reason for the Internet being so insecure is the fact that its original creators strove to make a transparent network based mutual trust!! They didn't know that most people are kinda scumbags!
159 |
160 | ### Networks as a Malware Delivery System:
161 | - **Malware** is bad software that infects your computer and can do terrible things like sending information to unauthorized actors, delete your files or shut down your computer. Most probably, you'd get a virus from the Internet. It's possibly that your computer becomes a part of a **botnet** which is a network of infected zombie computers that a bad actor uses to spread spam and carry DDoS attacks. Malware is also usually self-replicating meaning it creates copies of itself to infect your computer even more or it sends copies of itself over the network to infect other computers.
162 |
163 | ### The Network Infrastructure Itself Can Be Attacked:
164 | - The most common attack on a network is **Denial of Service (DoS)**. In this attack a network or part of it such as a server is rendered unusable by legitimate users. DoS can be achieved using several types of attacks such as:
165 | - **Vulnerability attack**: is achieved through sending a well-crafted sequence of packets to a vulnerable server/host. If the sequence is correct the host stops or crashes.
166 | - **Bandwidth flooding**: is done literally flooding the target with so many packets that its access linked so congested that it can't receive legitimate packets.
167 | - **connection flooding**: is done with flooding a host with fully-open or half-opened TCP connections that it stops receiving legitimate connections.
168 | - DoS attacks can be detected and blocked, but an even worse and harder to detect and defend against version of this attack exists. It's called **DDoS**, distributed DoS. This is done usually with a botnet where connections from different distributed hosts.
169 |
170 | ### The sniffers:
171 | - A passive receiver can be placed in the vicinity of a wireless transmitter and obtain a copy of every packet that moves in the network. This is called a **packet sniffer**. It is more ever more dangerous because its activity can't be detected and it can be the first step in other more lethal attacks. Even though most sensitive data today is strongly encrypted, the dangers of this attack shouldn't be underestimated. Wired LANs are also susceptible to sniffing.
172 |
173 | ### Spoofing:
174 | - Spoofing is all about masquerading as somebody you are not! One form of spoofing is **IP spoofing** where you can create a packet with an arbitrary source address, add a real destination address to it and some content and send it in the wild Internet.
175 |
--------------------------------------------------------------------------------
/networking/receivewindow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/receivewindow.png
--------------------------------------------------------------------------------
/networking/request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/request.png
--------------------------------------------------------------------------------
/networking/response.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/response.png
--------------------------------------------------------------------------------
/networking/sr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/sr.png
--------------------------------------------------------------------------------
/networking/stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/stack.png
--------------------------------------------------------------------------------
/networking/tcpsegment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/tcpsegment.png
--------------------------------------------------------------------------------
/networking/tcpsendreceivebuffers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/tcpsendreceivebuffers.png
--------------------------------------------------------------------------------
/networking/typesofqueries.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/typesofqueries.png
--------------------------------------------------------------------------------
/networking/udpformat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/networking/udpformat.png
--------------------------------------------------------------------------------
/os/Advanced Aspects of Virtual Memory.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/os/Advanced Aspects of Virtual Memory.md
--------------------------------------------------------------------------------
/os/README.md:
--------------------------------------------------------------------------------
1 | # Introduction:
2 | ## Table of Contents:e
3 | ## What This Is:
4 | - These are the notes I am taking while reading *Operating Systems: Three Easy Pieces* by Remzi H.Arpaci-Dusseau and Andrea C. Arpaci-Dusseau, available [here](https://pages.cs.wisc.edu/~remzi/OSTEP) and [here](http://www.ostep.org).
5 | - The book is structured around three major concepts, hence the name. The topics are: **virtualization**, **persistence**, and **concurrency**. Each of the three major sections is divided further into smaller chapters that kinda tiny, no more than ten pages each.
6 | - Each topic and subtopic probably revolves around a certain problem and steps to solve it. There are practical exercises and whatnot! There are also historical sketches explaining the evolution of operating systems, blah blah!
7 | - These notes will be extremely terse, unless waffling on is of absolute necessity!
8 |
--------------------------------------------------------------------------------
/os/concurrency.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/os/concurrency.md
--------------------------------------------------------------------------------
/os/img/MLFQ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/os/img/MLFQ.png
--------------------------------------------------------------------------------
/os/img/addressSpace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/os/img/addressSpace.png
--------------------------------------------------------------------------------
/os/overview.md:
--------------------------------------------------------------------------------
1 | # Introduction to Operating Systems:
2 | ## Table of Contents:
3 | * [Table of Contents](#table-of-contents)
4 | * [An Operating System Is](#an-operating-system-is)
5 | * [Virtualizing the CPU](#virtualizing-the-cpu)
6 | * [Virtualizing Memory](#virtualizing-memory)
7 | * [Concurrency](#concurrency)
8 | * [Persistence](#persistence)
9 |
10 | ## An Operating System Is:
11 | - The **Von Neumann** model of computing dictates that a processor **fetches**, **decodes**, and then **executes** instructions. So when you run a program in a computer, this is what happens in fact over and over: a bunch of instructions are fetched from memory, decoded and then executed. Much of this magic happens behind the scenes without you noticing a thing. It is thanks to **operating systems** that such voodoo happens seamlessly.
12 | - An operating system:
13 | - Makes it **easy to use programs**.
14 | - Allows multiple programs to run simultaneously without clashes. They share the same memory and their data doesn't get scrambled together.
15 | - Facilitates communication between the computer and devices attached to it.
16 | - Gives the user an easy interface for interacting with the device's hardware.
17 | - An operating system can alternatively be thought of as a **resource manager**, since it manages how resources such as CPU time, memory and disk space are shared between different running programs.
18 | - An OS can be thought of as doing three major tasks, **virtualization**, **concurrency**, and **persistence**. The rest of this book will explain what these words mean.
19 |
20 | ## Virtualizing the CPU:
21 | - A typical computer has one or a few CPUs, but it can run a large number of programs simultaneously as if there are many CPUs. This is what we mean by virtualizing the CPU, we give the user the illusion that the computer has many CPUs running at the same time. Our job is understand how the OS achieves this illusion.
22 |
23 | ## Virtualizing Memory:
24 | - Two programs running simultaneously, have independent address spaces. Two identical memory addresses for two programs would contain different data. How is it possible? How does each running program seem to have the whole memory space to itself? This is again done with memory virtualization where each program has a virtual memory space to itself that is mapped to actual physical memory. This is another way OSs make running programs easy!
25 |
26 | ## Concurrency:
27 | - Different processes have their own memory spaces each that are not shared with other processes. There is also the concept of **thread**, which can be thought of as a *process lite*. Threads are different lines of execution but they operate on a shared memory. Sharing memory between threads in multi-threaded programs causes a lot of headaches because of the very unpredictable results such programs can give. We will learn in the concurrency section the causes of this problem and how to write correct programs involving concurrency.
28 |
29 | ## Persistence:
30 | - Persistence is all about storing data safely using so-called **file systems**. A lot of hard work by the OS goes into this!
31 |
--------------------------------------------------------------------------------
/os/paging.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/os/paging.md
--------------------------------------------------------------------------------
/os/processes.md:
--------------------------------------------------------------------------------
1 | # Processes
2 | ## Table of Contents:
3 | * [Intro](#intro)
4 | * [Processes](#processes)
5 | + [A Process](#a-process)
6 | + [Process API](#process-api)
7 | + [Creating a Process](#creating-a-process)
8 | + [Process States](#process-states)
9 | + [Data Structures](#data-structures)
10 | * [Unix Process API](#unix-sprocess-api)
11 | + [`fork()`](#fork())
12 | + [`wait()`](#wait())
13 | + [`exec()`](#exec())
14 | + [Why an API?](#why-an-api)
15 | * [Limited Direct Execution](#limited-direct-execution)
16 | + [Direct but Limited Execution](#direct-but-limited-execution)
17 | + [Exception!!](#exception!!)
18 | s
19 | ## Intro:
20 | - Processes are probably the most basic and powerful abstraction provided by operating systems. In this document, we will follow the book's discussions of processes, sometimes briefly because much of this topic has been discussed in another system's document. Our discussion of the topic will be divided into 3 lage sections:
21 | - The first section will discuss the general idea of what a process is and how an OS uses it.
22 | - The second section will dive deep into some of the most important UNIX system calls designed specifically for creating and managing processes.
23 | - The third section studies the concept of **limited direct execution** and how the OS uses itt to create efficient processes that it can still control and supervise.
24 |
25 | ## Processes:
26 | - How do we get the illusion of having so many CPUs in a computer? This is done mainly through what's often called one of the greatest ideas (abstractions) in all of computer science, namely **processes**. A process is the live running version of a program.
27 | - The OS "wraps" programs in processes and manages these processes making running multiple (many many) programs at the same time an easy task. You don't have to worry about the availability of the CPU or any of that nonsense.
28 | - The CPU is virtualized through the use of processes. The CPU would run a process for some time, stops running it and jumps to another process, then jumps back to the current process and then another continuously and tirelessly. This jumping around is called **time sharing**. Time sharing is one of those nerdy words OS designers like to throw around.
29 | - CPU virtualization can be achieved through the use of:
30 | - Low level **mechanisms** such as the so-called **context switching** which refers to the continuous switching between different processes.
31 | - High-level intelligence referred to usually as **policies** is also used to guide CPU and other kinds of virtualization. For example, **scheduling policies** based past behavior of programs, their performance and other metrics, help the OS decide scheduling priorities for processes, what process to run next and how much time is allocated to a process.
32 |
33 | ### A Process:
34 | - A process can be thought of in terms of the system components it affects/ accesses during its lifetime which are collectively called its **machine state**. The machine state of a process includes the following:
35 | - *Memory*, which contains the program's instructions and the data the process reads/writes. This memory is part of the process and is called its **address space**.
36 | - *Registers* are also a crucial part of a process including the **program counter (PC)**, **stack pointer**, and **frame pointer** which manage various aspects of the program such as its return address, etc.
37 |
38 | ### Process API:
39 | - This is not a real process API but generic features/aspects a typical process might or should have:
40 | - **Create**: An OS needs to offer a way for the user or other programs to start a process. When you double-click a program you're instructing the OS to start a new process to run that program.
41 | - **Destroy**: A way to kill a process. Some processes might terminate on their own upon the completion of their tasks.
42 | - **Wait**: ??! Waiting for a process to stop running??!! But why? :confused:.
43 | - **Control**: A process can be suspended and then resumed.
44 | - **Status**: The API might need to tell us if the process is running, suspended, etc. General information about the process's current status.
45 |
46 | ### Creating a Process:
47 | - Turning a program into a process, in other words getting the program to be running involves:
48 | - **Loading** an executable containing the program's code and static data (such as its initialized data) from disk to the process's address space.
49 | - Once the program is loaded, the OS allocates a **runtime stack** for the process which will be used for the return address, local variables, function parameters, etc.
50 | - Memory is also allocated for the **heap** which is used for dynamically-allocated data for data structures like linked lists and whatnot. Memory is allocated on the heap by calling `malloc()` and freed with `free()`. The OS manages such allocation/freeing of memory.
51 | - Initialization tasks related mainly to IO devices. Each Unix process, for example, has three open file descriptors: standard input, standard output, and standard error.
52 | - After all the steps listed above take place, the OS can jump to the program's entry point `main()` and transfer execution to the process/program.
53 |
54 | ### Process States:
55 | - A running process can be in one of three states:
56 | - **Running**.
57 | - **Ready**: The process is ready and can be run if the OS chooses to run it.
58 | - **Blocked**: The process cannot run currently, because it might be waiting for another operation to finish, example: waiting for an I/O operation to finish or return something.
59 | - These states have to do directly with OS **scheduling**. A running program can be either **scheduled**, meaning it is running currently or **de-scheduled**, meaning it is ready when the scheduler decides to give it a slice of time to run. When a process is blocked, it might also be de-scheduled while in this state of blockage.
60 | - There can be other states we didn't mention earlier such as:
61 | - *Initial* state for when the process has just started.
62 | - *Final* or *zombie* state before the process is torn down. This for example, allows a parent process to examine the return value of a process for whatever reason.
63 |
64 | ### Data Structures:
65 | - A process keeps several data structures to track different information about processes, such as a list of running processes, ready processes, and blocked ones. This might be called a **process list**.
66 | - Another important piece of information the OS holds is so-called **register contexts** for de-scheduled processes. They contain snapshots of the register state for processes so when the process is scheduled again, their register state is restored. This is used for **context switching** which we will see later.
67 |
68 | ## Unix Process API:
69 | - This will be a basic overview of process creation in the UNIX system(s). It studies three very common Unix system calls `fork()`, `exec()` which are used for creating new processes, and `wait()` which allows a process to wait for its child process(es) to finish executing.
70 |
71 | ### `fork()`:
72 | - **`fork()`** is a weird system call and can be confusing. Check the following example. It shows a function calling `fork()`. It involves the use of `getpid()` function which allows you to get the **process identifier (PID)** for a function, which allows you identify a specific process to, for example, stop it from running or something:
73 | ```c
74 | #include
75 | #include
76 |
77 | int main(int argc, char const *argv[]) {
78 | int rc = fork();
79 | printf("Hello, world! I am %d\n", (int) getpid());
80 | printf("%d\n===========\n", rc);
81 | return 0;
82 | }
83 | ```
84 | - The output of the function is as follows:
85 | ```
86 | Hello, world! I am 86057
87 | 86058
88 | ===========
89 | Hello, world! I am 86058
90 | 0
91 | ===========
92 | ```
93 | - Notice that the second print statement is executed twice, and it has echoed two different PIDs. The first print statement was executed only once. It looks like thee are two similar copies of the same function but not exactly. All statements starting with the call to `fork()` get also executed for the child process.
94 | - Notice, though, that although the same instructions are executed for both the parent and child processes (starting with the call to `fork()`), the values are different as every one of the two processes has its own address spaces, registers, and whatnot. `rc` for example is used to denote the PID of the newly created child process. Notice that the `rc` value for the child process is `0` because it hasn't created any children of its own!
95 | - ANother interesting observation, about this program is that the order of execution between child and parent processes is not deterministic. Print statements within the parent process might execute before those of the child or vice-versa. This **non-deterministic** behavior is mainly due to the CPU scheduler and how it works. The following code illustrates the use of `wait()`:
96 |
97 | ```c
98 | #include
99 | #include
100 | #include
101 |
102 | int main(int argc, char const *argv[]) {
103 | int rc = fork();
104 | int rc_wait = wait(NULL);
105 |
106 | printf("Hello, world! I am %d\n", (int) getpid());
107 | printf("rc: %d, rc_wait: %d\n===========\n", rc, rc_wait);
108 |
109 | return 0;
110 | }
111 | ```
112 | - The output is as follows (The child process with a larger PID will always finish first):
113 | ```
114 | Hello, world! I am 86216
115 | rc: 0, rc_wait: -1
116 | ===========
117 | Hello, world! I am 86215
118 | rc: 86216, rc_wait: 86216
119 | ```
120 |
121 | ### `wait()`:
122 | - The **`wait()`** (alternatively **`waitpid()`**, which is more complete) allows you the make the order of execution between child and parent more complete. It basically allows the child to finish executing before.
123 |
124 | ### `exec()`:
125 | - `wait()` allows you to run copies of the same program as different processes, but you can also run different programs through creating new processes by calling **`exec()`** as in the following example:
126 | ```c
127 | #include
128 | #include
129 | #include
130 | #include
131 |
132 | int main(int argc, char const *argv[]) {
133 | char *argz[3];
134 | argz[0] = strdup("vim");
135 | argz[1] = strdup("os.c");
136 | argz[2] = NULL;
137 |
138 | execvp(argz[0], argz);
139 |
140 | return 0;
141 | }
142 | ```
143 | - The example allows you to call shell programs form your C code. Notice that we are actually calling `execvp()`. There multiple variants of `exec()`.
144 | - `exec()` and its variants don't create new processes, but instead it "it loads code (and static data) from that executable and overwrites its current code segment (and current static data) with it." The heap and stack of the function or program calling `exec()` get reinitialized. `exec()` basically "transforms the currently running program ... into a different running program".
145 |
146 | ### Why an API?
147 | - The book claims that the existence of these three seemingly convoluted routines for creating new processes instead of just offering a simple way of creating a new process is to make it easier to create shell programs. I am not really convinced! ANwyays, what happens is that the shell is just another program running as a process. When you invoke a shell program such `ls` or `grep`, the shell process fork a child process of its own, calls `wait()` to let the process child finish before returning to it, then calls `exec()` which replaces its code and static data with those of the program it calls.
148 | - The book claims that easy redirection of input/output is one great example why these routines exist.
149 |
150 | ## Limited Direct Execution:
151 | - The authors came up with the term **limited direct execution** to describe how processes are controlled by a modern regular OS. Processes need to be both *performant*, and also be *controlled* by the OS. Performance means its instructions run natively on the CPU, and controls refer to the requirement that a process shouldn't access resources it is not supposed to access or run longer than the time allotted to it.
152 |
153 | ### Direct but Limited Execution:
154 | - Direct execution means the process runs directly on the CPU. This is why C, for example, is faster than Java (or why x86 instructions are faster than Java bytecode as the former run directly on the metal, while the latter run on a intermediate machine which translates it to x86 instructions). The problem with direct execution is that process code can do anything it wishes. Process instructions are identical to the instructions used to make the OS itself, so the processes might change and access data it's not meant to access, or might run forever and take over the system's resources.
155 | - We know that an OS manages computer resources, so it allows certain operations and restrict others. It gives users different levels of control over the system, etc. If processes are not limited, they can do anything, so the OS becomes less usable.
156 | - To make the instructions of a process less dangerous, we limit their capabilities. Certain operations such as accessing IO devices, creating and destroying other processes, etc. cannot be done directly by processes, but are done through indirectly, through system calls and whatnot!
157 | - But how can processes be limited? This is done by having processes run in two modes:
158 | - **User mode** in which the process is limited in what it can do. It cannot, for example, perform an IO operation.
159 | - **Kernel mode** in which the kernel code runs. It can do anything it want
160 | - If the user process wishes to execute certain restricted operations, it needs to do so through a system call. These system calls are done by the OS itself on behalf of the user process. When the user process wants to perform a restricted operation, it executes a special **trap** instruction. This instruction jumps into the kernel raising privilege to the kernel mode. The system performs the restricted operation, and the OS calls a **return-from-trap** instruction which returns to the calling user and lowers privileges.
161 |
162 | #### Exception!!
163 | - *It turned out that much what I've been reading so far of this book has already been already detailed in Computer Systems, a Programmer's Perspective!! That book didn't discuss "policies", and the "whys" of things, but did thoroughly described much of OS functionality, especially Unix*. I will continue reading this book but will mostly focus on stuff not covered yet in the systems book. I will also spend more times on they whys and design aspects of OSs and why certain aspects were in certain ways in Unix or whatever OS. At least, I am glad that spending a few months reading the systems book was so far really really worth it!
164 |
165 |
--------------------------------------------------------------------------------
/os/scheduling.md:
--------------------------------------------------------------------------------
1 | # Scheduling:
2 | ## Table of Contents:
3 |
4 | ## Intro:
5 | - This chapter will cover the very important OS topic of scheduling. **Scheduling** basically refers to the **high-level policies** used by the OS to manage slices of time it allots to each process. While *Computer Systems, a Programmer's Perspective* went into great detail describing the low-level mechanisms of how processes are created, stopped, etc. It only acknowledged the existence of a scheduling mechanism (or should I say policy/policies?!) and never said what it was, how it worked, etc. Our discussion of scheduling will be divided into 4 major sections with each section roughly corresponding to a chapter from the book:
6 | - An overview of scheduling.
7 | - An overview of a popular scheduler (or scheduling policy) called **multi-level feedback queue (MLFQ)**.
8 | - Covers another popular scheduler: **proportional share**.
9 | - Discusses scheduling in multiprocessor hardware.
10 | - Again, I will try to avoid unnecessary waffling and not repeat anything that was covered in CSAPP.
11 |
12 | ## Scheduling:
13 | ### Preliminary Assumptions and Some Useful Metrics:
14 | - Processes running in a system are collectively called the **workload**, and processes can also be called **jobs** (I believe this weird alternative terminology might come from the fact that OS scheduling took much of its inspiration from the field of operations management). To understand scheduling step by step, let's start by making some basic but truly unrealistic assumptions about the workload:
15 | 1. Jobs run for the same amount of time.
16 | 2. Jobs arrive at the same time (to the CPU or scheduler? :confused:).
17 | 3. Jobs run to completion (A job is not interrupted midway to perform another job).
18 | 4. Jobs us the CPU only, and don't perform any IO operations.
19 | 5. The scheduler (or CPU :confused:) knows the run-time of each job.
20 | - The topic of scheduling is heavy on metrics as a self-respecting OS is all about metrics and scheduler play a central role in the performance of an OS. Let's start with a very basic metric: the **turnaround time** metric. It is the amount of time separating when the job first arrives to the system and the moment when it completes running:
21 | - ***Tturnaround = Tcompletion - Tarrival***
22 | - Because we are assuming at the moment that all jobs arrive to the system at the same time, ***Tarrival = 0*** which means ***Tturnaround = Tcompletion***. We will change this assumption later for sure!
23 | - This section focuses on performance metrics, but there are also **fairness** metrics, and performance can be increased at the expense of fairness and vice versa!
24 |
25 | ## First In, First Out (FIFO):
26 | - A **first in, first out (FIFO)** scheduling scheme dictates the job that arrives first needs to be done first. Imagine 3 jobs A, B and C arriving all at once but each respectively arrives slightly before the other. Imagine that A takes 100 ms to run, and B and C take 10 ms each (we've just relaxed the first assumption: jobs don't run for the same amount of time anymore). The average turnaround for this workload is ***(100 + 110 + 120) / 3 = 110***. Do B and C have to wait such a long time for A to finish executing?! It seems kinda wasteful! This problem is called the **convoy effect**. It is akin to standing in line for a cash register with a soda bottle behind a lady with a cartful of groceries!
27 |
28 | ## Shortest Job First (SJF):
29 | - The **shortest-job-first (SJF)** scheme tries to answer this specific convoy effect by picking the shortest jobs to run first, so B and C will be run before A. Their turnaround is ***(10 + 20 + 120)/ 3 = 50***. This is a great improvement over the FIFO approach.
30 | - Let's now relax our second assumption and imagine that A arrives at time 0 ms, B arrives at 10 ms, and C arrives at time 20 ms. The three still run respectively for 100, 10 and 10 milliseconds. When B and C arrive, A would have already started running, and B and C won't start running until A finishes. SJF still suffers from the convoy problem.
31 |
32 | ## Shortest Time-to-Completion First (STCF):
33 | - To address the convoy problem in SJF that arises from jobs arriving at different times, we have to relax the 3rd assumptions. Jobs need not run to completion anymore. A job can be interrupted midway and the context be switched to another job. The scheduler is said to **preempt** a job and run another. Schedulers that do this are called **preemptive schedulers**. They use context switching and timer interrupts to achieve this.
34 | - The **shortest time-to-completion-first (STCF)** scheduler (also called **preemtive shortest job first (PSJF)**) does just that. The long job A starts at 0. Each time timer interrupt occurs control is returned to the kernel which decides whether to continue the job. If the shorter job B is available, it runs and completes, and then the kernel comes back to job A to complete it.
35 |
36 | ## Response Time, Another Metric:
37 | - **Response time** is defined (at least according to the authors of the book) as:
38 | ***Tresponse = Tarrival - Tfirstrun***
39 | - Others might define response time as distance in time between the arrival of the job and when it first produces as a job.
40 | - Anyways, response time appear particularly in applications requiring interactivity such as shell programs which you expect to respond quickly.
41 | - The problems associated with response time arise when, for example, 3 jobs arrive at the same time. Imagine they all run for equal periods of time. The second job has to wait for the first one to complete, and the third job has to wait for the previous two! The response of the third job is too bad and the average of the three is also bad.
42 |
43 | ## Round Robin (RR):
44 | - Imagine again that three same-length jobs arrive at the same time. STCF won't work here, because they all have the same time length, and there is no reason why the STCF scheduler would switch to another one. **Round Robin (RR)** scheduler comes to the rescue! It doesn't run jobs to completion, but instead divides time into **time slices** (also called **scheduling quantum**), and then run first program during first slice, then switch to the second job in the second, slice, etc. The length of a time slice must be a multiple of the timer interrupt.
45 | - To achieve high response-time performance, time slices need to be small; but smaller time slices can incur heavy overhead emanating from constant context switching! Context switching is a heavyweight operation that involves saving and restoring registers and some cache magic and whatever, and abusing can be really bad for overall performance!
46 | - We need to make trade-offs and tweak the size of time slices until we get to a sweet spot between responsiveness and lowering the costs of context switching. We need to ***amortize*** (yeah, whatever) the cost of context switching (the authors say that if it takes fixed 1 millisecond to context switch, this would mean a 10% performance penalty on a 10 millisecond time slice. If we make the time slice 100ms long, the cost of context switching becomes 1 % as per time slice).
47 |
48 | ## Performance vs. Fairness:
49 | - RR is great for response time but terrible for turnaround. RR favors fairness, but it hurts performance. SOme jobs that could've finished earlier have to share time with others! Systems are all about trade-offs and achieving both performance and fairness is a great example of this need for fairness!
50 |
51 | ## Adding IO:
52 | - Let's now abandon our 4th assumption. If two jobs arrive to the system and one job makes an IO request, the scheduler should not wait for that job to complete its IO operation and sit idle. It should immediately switch to the second job and run a slice of it before returning to it when the IO operation is done. The book says that a job involving multiple IO requests should break that job into separate jobs and treat each CPU burst other than when the job is blocked during the IO fetch as if it were an independent job. The IO blocked time should be used to run other jobs.
53 |
54 | ## No ***A Priori*** Knowledge about the Job Run-Time:
55 | - OSs don't know anything about the length of jobs so it cannot tell for how long they can run, so that was a wrong assumption. Smart schedulers, however can make modest predictions about future based what they've seen in the past! We will see this in the next section about MLFQ.
56 |
57 | ## Multi-Level Feedback Queue (MLFQ) Scheduler:
58 | - The **multi-level feedback queue (MLFQ)** was first described by a certain Corbato et al. in 1962 and has been a very influential ever since!
59 | - MLFQ tries to achieve two goals:
60 | - Minimize *turnaround time*. How can a scheduler minimize turnaround time by running shorter jobs before longer jobs STCFs style without knowing how long a process would run?
61 | - Minimize *response time*, but we know that minimizing response time can come at the expense of turnaround time. How can a scheduler do both in a satisfactory manner?!
62 |
63 | ### MLFQ, the Basics:
64 | - MLFQ has different implementations that differ in details, but the general rules are very similar.
65 | - MLFQ has a number of queues, and each queue has a different **priority level**. At any point in time a queue can have 0 or more jobs. MLFQ uses the priority levels of job's queues to decide which next job to run. A queue can have multiple jobs which would have the same priority. In such case, MLFQ can decide which of these to run by using some algorithm. The authors suggest round-Robin (RR). These rules can be summarized as:
66 | - **Rule 1**: If ***priority(A) > priority(B), then run A***.
67 | - **Rule 2**: If ***priority(A) = priority(B), then run A and B in RR***.
68 | - But how does MLFQ set priority? Well, instead of assigning fixed priorities to jobs, MLFQ moves a job up and down the priority scale based on its *observed behavior*. For example, a job that repeatedly let go of the CPU while waiting for a a keyboard input is an interactive application whose priority must be high. An application with intensive use of the CPU for longer times gets a low priority. In this way, MLFQ *learns* from the *history* behavior of processes to predict their *future*.
69 | - The following diagram shows how MLFQ works. Jobs A and B have a high priority, while C and D have lower priorities:
70 | 
71 | - For the rest of this section, we will try to understand how priority changes over time. We will continue to improve and add on more rules to our MLFQ until we have a complete picture of how it works.
72 |
73 | ### Changing priority:
74 | - A job doesn't live its entire life inside one queue, but its priority changes dynamically as it lives. Imagine that our workload is a mixed bag of IO-bound interactive short running jobs, and a long running CPU-bound non-interactive jobs. The priorities of such jobs can be changed according to these rules:
75 | - **Rule 3**: When a job first arrive to the scheduler it is placed in the highest priority queue.
76 | - **Rule 4a**: If a job uses an entire time slice without letting go of the CPU, its priority is reduced.
77 | - **Rule 4b**: If a job lets go of the CPU before its time slice is over, the job stays in the same priority queue.
78 | - Following these rules, imagine we have a long-running CPU-bound job arriving at the scheduler. It is first placed at the highest priority queue. It eats through the whole first time slice so it gets downgraded to the next lower priority queue. It keeps doing so until it reaches the bottom of the queue.
79 | - Imagine a second job, but this time a short job enters the system before the first long job is over. The short job is placed in the highest priority queue. This short job might either stay in the highest queue or at worst be downgraded one or queues only because it is short. The scheduler will interrupt the long job, and switch to executing this short job because it still has a higher priority. This way, MLFQ mimics SJF.
80 | - What happens when a highly responsive job that include many successive IO requests enters the scene? Such a job will probably never eats up through a whole time slice, so it will stay at the highest priority queue at all time so it achieves the high performance it deserves.
81 |
82 | #### Problems with our MLFQ Implementation so Far:
83 | - Our configuration of MLFQ so far suffers from several major flaws:
84 | - The lower priority queues might be **starved** of all CPU time, especially when there are too many interactive applications placed in higher queues.
85 | - Malicious actors might optimize their job behavior so it look like a highly interactive job. This makes it monopolize CPU time. Such attacks are especially dangerous in data centers with shred CPUs and memories.
86 | - A job might also change its behavior over time, so it can start as CPU-bound application but at some point it becomes an interactive job. This job in urgent need of response time is in a very low priority queue has no way of elevating itself back to where it really belongs.
87 |
88 | ### Boosting Priority:
89 | - We can periodically **boost** the priority of all jobs, by for example moving all jobs to the topmost priority queue. We can device a new rule now:
90 | - **Rule 5**: After a time period S, move all jobs to the topmost priority queue.
91 | - This boosting achieves two goals. First, the CPU bound jobs don't get starved of CPU times as they move up the priority hierarchy and compete with higher priority jobs using RR. Second, jobs that have become suddenly interactive can now be treated as they deserve and be given better response time.
92 | - The value S after which a boost needs to happen must be set with care. If S is too large, starvation of lower-queue long running jobs will still be prone to starvation. If S is too small, short-running job might not get the responsiveness they need.
93 |
94 | ### Better Accounting:
95 | - Now we need to make our MLFQ resilient to schedule gaming. I don't really understand this part. The authors say that even interactive jobs will be downgraded down the priority hierarchy as if a long job that includes interactivity is treated almost exactly as one that is IO-bound :confused:!! They suggest the following rule (which replaces rules 4a and 4b):
96 | - **Rule 4**: Every job will keep moving down the priority scale regardless of their use of IO and letting go of the CPU time too soon.
97 | - This configuration is not as easy to game, but
98 | - At least, the SJT principle will be still maintained in this new configuration.
99 |
100 | ### Additional Issues:
101 | - One important issue to consider when designing an MLFQ scheduler is so-called parameterization which include:
102 | - Deciding how many queues to use.
103 | - Should queues have the same time slices? If not, how big a time slice per queue should be?
104 | - How often should priority be boosted?
105 | - There are no ready answers for these questions. Designers need to fine tune these parameters until they reach satisfactory results.
106 | - An example of MLFQ parameterization is the choice of time slices for queues. Higher priority queues have shorter slices as they'd usually contain shorter jobs, and the slices get larger as you move down to lower-priority queues. Low priority jobs would use more CPU per slice as they are mainly hungry for CPU.
107 | - The Solaris implementation of MLFQ allows system administrator to alter the way priorities and scheduling work to suit her desires.
108 |
109 | ## Proportional Share Scheduler:
110 | - Another widely used scheduler is the **proportional share** or **fair share** scheduler. Instead of optimizing for turnaround or response time, it tries to guarantee that each job gains a certain percentage of CPU time. An early form of proportional share scheduling was the so-called **lottery scheduling**. In such a type of scheduling, we often run a lottery to determine which process should run next, and processes that should run more often need to be given higher chances of winning.
111 |
112 | ### Basics, Tickets and Shares:
113 | - Each process has a number of tickets, and the number of tickets a process has corresponds with its share/proportion of CPU time (or whatever resource). If processes A and B have 75 and 25 tickets respectively, then A has a 75% share of CPU time, and B has 25%. Let's suppose that A has tickets 0 through 74, while B has tickets 75 through 99. The scheduler will pick a ticket whose number is between 0 and 99 at random. 7, and 57 for example will belong to A, while 89 will be B's. This probabilistic setup will not guarantee exact proportion but will approximate it over long runs.
114 | - The choice of randomness will at least free the system from the burden of tracking which processes has used how much state. There are other good side effects to choosing randomness but I don't understand them to be honest!
115 |
116 | ### Implementation:
117 | - I have absolutely no idea what's going on here!!!! Come on!!
118 |
119 | ### The Linux Completely Fair Scheduler (CFS):
120 | - I don't really see how this scheduler relates to the ones just mentioned, the lottery schedulers, apart from the fact that it is another fair share scheduler. Anyways, this doesn't kinda seem as voodooy as the previous subsection which was all jumbled up!
121 | - The **completely fair scheduler (CFS)** used in Linux divides the CPU between all jobs evenly in a dynamic and scalable fashion (I don't know how this scalability is achieved). What probably sets this scheduler apart is that it does very little work to schedule jobs since time is shared as evenly as possible between different processes. This is a source of great efficiency!
122 | - CFS divides CPU time evenly between different processes through so-called **virtual runtime (`vruntime`)**. This `vruntime` increases evenly for each running process as time progresses. When a scheduling decision need to be made, the scheduler picks the process with the lowest `vruntime`.
123 | - How does CFS avoid context switching too often or less often? Over-context- switching is bad for performance, while less context switching might mean less fairness in the short time! (really? :confused:). CFS provides a number of parameters to fix this problem. One such parameter is **`sched_latency`** which is used to determine the run time of a job before considering a switch. CFS uses something like 48 ms for `sched_latency` :confused: and divides this by the number of running processes. If we have 4 processes, this means each job gets 12 seconds before switching occurs. Just remember that `vruntime` increases with time, but when does it stop growing? and how about newly arriving processes?
124 | - Another important parameter is the so-called **`min_granularity`** which acts as some kind of minimum threshold for the size of a run time of a process. This is useful when there are way too many processes. If we divide 48, our dear `sched_latency`, by a 100 then we will need to context switch every half millisecond which is really bad! A typical value for `min_granularity` is 6 ms.
125 | - Different processes can be assigned **weights** to indicate different priorities. This can be done by the Unix **nice** processor level, *what??!!* :confused:!! I believe different processes acquire different time slice priorities through this mechanism.
126 | - Instead of using a simple list for tracking running processes, CFS uses a red-black tree which has a very efficient read time of ***O(log n)***. This is how CFS scalability is achieved. This structure only tracks running processes. Processes that go on sleeps during an IO operation for examples are not kept track of.
127 | - A job that goes on a sleep while waiting for an IO response don't get their `vruntime` increased during their sleep which means they get starved of CPU time by their siblings that didn't sleep and now have a much larger `vruntime`. CFS tries to fix this by assigning the just reawaken process a `vruntime` from a process in the tree (probably the one with the smallest `vruntime`). Anywayss, processes waking froma n IO sleep never get a fair share CPU time.
128 |
129 | ## Multiprocessor Scheduling:
--------------------------------------------------------------------------------
/os/virtualMemoryOS.md:
--------------------------------------------------------------------------------
1 | # Basics of Virtual Memory
2 | ## Table of Contents:
3 | ## Intro:
4 | - Virtual memory is one of the most important services offered by a self-respecting operating system. Dealing directly with physical memory can be very frustrating as it requires you to keep track of so many things. OS designers thought of automating some this away and figured this thing called virtual memory. Virtual memory basically means that addresses programs are all virtual. Each address is a virtual address that can at some point have a corresponding physical address. This book claims that virtual memory has two main benefits:
5 | - *Ease of use*, as the user doesn't have to trundle through directly the muddy perilous physical memory. Every process has available to a large array of bytes that is easy to use. All processes have a uniform virtual address space. This makes programs simple and easy to use, modify, etc.
6 | - *Isolation and protection*. Each process has its own independent address space that it can modify as it pleases, but it cannot mess with other processes address spaces.
7 |
8 | ## Address Spaces:
9 | - An address space can be viewed as a program's of view of the system's memory. It is a foundational abstract probably as important as the process abstraction.
10 | 
11 |
12 | ## Unix Memory API:
13 | -
14 |
15 | ## Address Translation:
16 | -
17 |
18 | ## Segmentation:
19 | -
20 |
21 | ## Free-Space Management:
22 | -
--------------------------------------------------------------------------------
/systems/concurrent.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/concurrent.md
--------------------------------------------------------------------------------
/systems/errorHandling.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/errorHandling.md
--------------------------------------------------------------------------------
/systems/img/L1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/L1.png
--------------------------------------------------------------------------------
/systems/img/addrTranslation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/addrTranslation.png
--------------------------------------------------------------------------------
/systems/img/alu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/alu.png
--------------------------------------------------------------------------------
/systems/img/argumentList.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/argumentList.png
--------------------------------------------------------------------------------
/systems/img/blockLinkedList.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/blockLinkedList.png
--------------------------------------------------------------------------------
/systems/img/boundaryTag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/boundaryTag.png
--------------------------------------------------------------------------------
/systems/img/cacheorg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/cacheorg.png
--------------------------------------------------------------------------------
/systems/img/call_proc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/call_proc.png
--------------------------------------------------------------------------------
/systems/img/callret.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/callret.png
--------------------------------------------------------------------------------
/systems/img/canary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/canary.png
--------------------------------------------------------------------------------
/systems/img/computerSystems/contextSwitching.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/computerSystems/contextSwitching.png
--------------------------------------------------------------------------------
/systems/img/computerSystems/hardware.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/computerSystems/hardware.png
--------------------------------------------------------------------------------
/systems/img/computerSystems/memH.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/computerSystems/memH.png
--------------------------------------------------------------------------------
/systems/img/computerSystems/osAbstractions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/computerSystems/osAbstractions.png
--------------------------------------------------------------------------------
/systems/img/computerSystems/virtMemSpace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/computerSystems/virtMemSpace.png
--------------------------------------------------------------------------------
/systems/img/directedReachabilityGraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/directedReachabilityGraph.png
--------------------------------------------------------------------------------
/systems/img/dram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/dram.png
--------------------------------------------------------------------------------
/systems/img/e8bitfloat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/e8bitfloat.png
--------------------------------------------------------------------------------
/systems/img/echostack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/echostack.png
--------------------------------------------------------------------------------
/systems/img/envp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/envp.png
--------------------------------------------------------------------------------
/systems/img/excepHandAddr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/excepHandAddr.png
--------------------------------------------------------------------------------
/systems/img/exception.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/exception.png
--------------------------------------------------------------------------------
/systems/img/exceptionTable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/exceptionTable.png
--------------------------------------------------------------------------------
/systems/img/fourmux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/fourmux.png
--------------------------------------------------------------------------------
/systems/img/fullyasoc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/fullyasoc.png
--------------------------------------------------------------------------------
/systems/img/heap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/heap.png
--------------------------------------------------------------------------------
/systems/img/heapBlockFormat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/heapBlockFormat.png
--------------------------------------------------------------------------------
/systems/img/i7cache.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/i7cache.png
--------------------------------------------------------------------------------
/systems/img/implicitFreeListHeap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/implicitFreeListHeap.png
--------------------------------------------------------------------------------
/systems/img/ioRedirectionDup2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/ioRedirectionDup2.png
--------------------------------------------------------------------------------
/systems/img/kernelOpenFiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/kernelOpenFiles.png
--------------------------------------------------------------------------------
/systems/img/lcf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/lcf.png
--------------------------------------------------------------------------------
/systems/img/lineMatchwordSel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/lineMatchwordSel.png
--------------------------------------------------------------------------------
/systems/img/linux32Stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/linux32Stack.png
--------------------------------------------------------------------------------
/systems/img/linuxPageFaultHandling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/linuxPageFaultHandling.png
--------------------------------------------------------------------------------
/systems/img/linuxVM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/linuxVM.png
--------------------------------------------------------------------------------
/systems/img/linuxVMOrg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/linuxVMOrg.png
--------------------------------------------------------------------------------
/systems/img/mallocFree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/mallocFree.png
--------------------------------------------------------------------------------
/systems/img/minVal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/minVal.png
--------------------------------------------------------------------------------
/systems/img/mmapArgs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/mmapArgs.png
--------------------------------------------------------------------------------
/systems/img/modernProc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/modernProc.png
--------------------------------------------------------------------------------
/systems/img/multLevelAddrTranslation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/multLevelAddrTranslation.png
--------------------------------------------------------------------------------
/systems/img/multLevelPageTable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/multLevelPageTable.png
--------------------------------------------------------------------------------
/systems/img/pa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/pa.png
--------------------------------------------------------------------------------
/systems/img/pageFault.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/pageFault.png
--------------------------------------------------------------------------------
/systems/img/pageHit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/pageHit.png
--------------------------------------------------------------------------------
/systems/img/pageLevelMemProtection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/pageLevelMemProtection.png
--------------------------------------------------------------------------------
/systems/img/pageTable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/pageTable.png
--------------------------------------------------------------------------------
/systems/img/parentChildFileDescs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/parentChildFileDescs.png
--------------------------------------------------------------------------------
/systems/img/princMemHier.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/princMemHier.png
--------------------------------------------------------------------------------
/systems/img/privateCopyOnWrite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/privateCopyOnWrite.png
--------------------------------------------------------------------------------
/systems/img/process2files.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/process2files.png
--------------------------------------------------------------------------------
/systems/img/processAddressSpace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/processAddressSpace.png
--------------------------------------------------------------------------------
/systems/img/processGraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/processGraph.png
--------------------------------------------------------------------------------
/systems/img/processSeparateAddressSpace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/processSeparateAddressSpace.png
--------------------------------------------------------------------------------
/systems/img/ram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/ram.png
--------------------------------------------------------------------------------
/systems/img/registerFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/registerFile.png
--------------------------------------------------------------------------------
/systems/img/registerState.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/registerState.png
--------------------------------------------------------------------------------
/systems/img/repManInfo/endian.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/repManInfo/endian.png
--------------------------------------------------------------------------------
/systems/img/repManInfo/floatcases.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/repManInfo/floatcases.png
--------------------------------------------------------------------------------
/systems/img/repManInfo/ieeefloats.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/repManInfo/ieeefloats.png
--------------------------------------------------------------------------------
/systems/img/setSelection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/setSelection.png
--------------------------------------------------------------------------------
/systems/img/sharedObject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/sharedObject.png
--------------------------------------------------------------------------------
/systems/img/singleBitMux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/singleBitMux.png
--------------------------------------------------------------------------------
/systems/img/sixBitFloat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/sixBitFloat.png
--------------------------------------------------------------------------------
/systems/img/stackFrameStructure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/stackFrameStructure.png
--------------------------------------------------------------------------------
/systems/img/stackOps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/stackOps.png
--------------------------------------------------------------------------------
/systems/img/stackarguments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/stackarguments.png
--------------------------------------------------------------------------------
/systems/img/struct.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/struct.png
--------------------------------------------------------------------------------
/systems/img/tlb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/tlb.png
--------------------------------------------------------------------------------
/systems/img/va.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/va.png
--------------------------------------------------------------------------------
/systems/img/vmAsCache.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/vmAsCache.png
--------------------------------------------------------------------------------
/systems/img/wordEq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/wordEq.png
--------------------------------------------------------------------------------
/systems/img/wordmux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/img/wordmux.png
--------------------------------------------------------------------------------
/systems/linking.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmaazouzi/cs-topics/baeafb1942b6980b94178e22d6f57142ab0192f9/systems/linking.md
--------------------------------------------------------------------------------
/systems/network.md:
--------------------------------------------------------------------------------
1 | # Network Programming:
2 | ## Table of Content:
3 | ## Introduction:
4 | - *A more in depth treatment of networking in general can be found [here](https://github.com/ahmaazouzi/cs-topics/tree/master/networking). I will assume the reader of this document is already familiar with some basic networking concepts such as the client-server model*.
5 | - Network applications are everywhere and most of them rely on the most basic programming model. They also rely on many of the concepts we have seen so far such as processes, signals, byte ordering, memory mapping and dynamic memory allocation. This chapter will revolve around how a basic web server works and networking from a systems perspective.
6 | - "Internet clients and servers communicate using a mix of sockets interface functions and Unix I/O functions [...] The sockets functions are typically implemented as system calls that trap into the kernel and call various kernel-mode functions in TCP/IP."
7 |
8 | ## The Client-Server Model:
9 | - A *server* serves *responses* to *requests* from *clients*. Clients and servers are not machines, but they are processes. The client and server processes might reside in the same machine, which is called a *host* in networking lingo.
10 |
11 | ## Networks:
12 | - You can find most of this section's content and more [here](https://github.com/ahmaazouzi/cs-topics/blob/master/networking/lowlevel.md).
13 |
14 | ## The Global IP Internet:
15 | - The whole Internet can be thought of as a collection of hosts with the following properties:
16 | - The set of hosts is mapped to a set of 32-bit *IP addresses*.
17 | - The set of IP numbers is mapped to a set of names called *Internet Domain Names*.
18 | - A process on one Internet host can communicate with a process on any other Internet host over a *connection*.
19 |
20 | ### IP Addresses:
21 | - An IP address is a 32-bit unsigned integer.
22 |
23 | ### Internet Domain Names:
24 | ### Internet Connections:
25 |
26 |
27 |
28 | ## The Socket Interface:
29 | ## Web Servers:
--------------------------------------------------------------------------------
/systems/optimizingPerformance.md:
--------------------------------------------------------------------------------
1 | # Optimizing Program Performance:
2 |
3 | * [introduction](#introduction)
4 | * [Capabilities and Limitations of Optimizing Compilers](#capabilities-and-limitations-of-optimizing-compilers)
5 | * [Eliminating Loop Inefficiencies](#eliminating-loop-inefficiencies)
6 | * [Reduction in Strength](#reduction-in-strength)
7 | * [Reducing Procedure Calls](#reducing-procedure-calls)
8 | * [Eliminating Unneeded Memory References](#eliminating-unneeded-memory-references)
9 | * [Understanding Modern Processors](#understanding-modern-processors)
10 | * [Loop Unrolling](#loop-unrolling)
11 | * [Enhancing Parallelism](#enhancing-parallelism)
12 | + [Multiple accumulators](#multiple-accumulators)
13 | + [Reassociation Transformations](#reassociation-transformations)
14 | * [Some Limiting Factors](#some-limiting-factors)
15 | * [A Performance Improvement Strategy](#a-performance-improvement-strategy)
16 | * [Profiling](#profiling)
17 | + [Amdahl's Law](#amdahls-law)
18 |
19 | ## Introduction:
20 | - This document is not about effective data structures or algorithms. It's mostly about how to make the compiler generate more optimized code. It also advises you on the general etiquette of optimization. Don't wholesale sacrifice the readability and extendability of your programs, be open to using trial and error and optimize mostly when necessary, etc.
21 | - Topics we will discuss in the document include (in no particular order):
22 | - Identifying and eliminating or reducing *optimization blockers*, aspects of a program that depend largely on the execution environment and the compiler have no idea about.
23 | - Reducing unnecessary code such as function calls and memory references
24 | - Exploiting our knowledge of how a processor process instructions and how a certain goal can be achieved through different instructions or combinations of instructions, some of which are more efficient than the others. We can also direct the compiler to make use of so-called *instruction-level parallelism*.
25 | - We introduce such tools as *profilers* that are used to identify bottlenecks in the code and parts that require optimization. We will also hand-examine or eye-examine assembly code to identify bottlenecks.
26 |
27 | ## Capabilities and Limitations of Optimizing Compilers:
28 | - Modern compilers are so smart! They can use the result of a single computations in several places and reduce the number of times computations are done.
29 | - Compilers such GCC offer us ways to control optimization. The simplest optimization control is to specify the level of optimization with an option like **`-Og`**, **`-O1`**, **`-O2`** or **`-03`**. We will mostly work with level 1 optimization. One side effect of raising the optimization level is that it results in hard to debug code and larger code size. Optimizing our code rationally using the tricks we will learn here can make optimization level 1 vastly better than blindly applying a higher level of optimization to it.
30 | - As there can apparently be unsafe optimization, one must only use **safe optimizations** which result in a code with the exact same behavior for all cases. The following program shows how naive optimizations can result in bad code:
31 | ```c
32 | void twiddle1(int *xp, int *yp){
33 | *xp += *yp;
34 | *xp += *yp;
35 | }
36 |
37 | void twiddle2(int *xp, int *yp){
38 | *xp += 2 * *yp;
39 | }
40 | ```
41 | - This is a case where trying to optimize code involving memory references can get a little murky. `twiddle2` is more efficient than `twiddle1` because the latter uses 3 memory references, while the former uses only 3 (memory references are generally considered as expensive operations). What if both **`xp`** and **`yp`** reference the same memory location. this will result? There is no reason why they shouldn't. In this case the two operations will have different results. `twiddle1` will result in 3 times the value at **`xp`**, while `twiddle2` will quadruple that value. Normally the compiler would optimize `twiddle1` to a form similar to that of `twiddle2`, because the compiler can't by any means determine if **`xp`** and **`yp`** would point to the same location in memory, it will not optimize `twiddle1` to `twiddle2`. This is called **memory aliasing** where two pointers may point to the same location. Memory aliasing, where multiple pointers might reference the same memory location is a major **optimization blockers**, a situation where the compiler doesn't compile a segment of code because it cannot determine whether memory is aliased or not.
42 | - Function calls are another major optimization blocker. Consider the following code:
43 | ```c
44 | int counter = 0;
45 |
46 | int f(){
47 | return counter++;
48 | }
49 |
50 | int func1(){
51 | return f() + f() + f();
52 | }
53 |
54 | int func2(){
55 | return 4 * f();
56 | }
57 | ```
58 | - `func2` might seem like an optimized `func1` and it might be in certain cases, but what if it produces side effects? In this example `f()` modifies the global variable `counter` making `func1` function differently from `func2`.
59 | - A compiler GCC does not try to do this kind of optimization because it assumes a function might cause side effects, this is why it's on the programmer to write more efficient code that leaves to the compiler only cases where there are no optimization blockers.
60 |
61 | ## Eliminating Loop Inefficiencies:
62 | - **Loop-invariant code motion** is one pretentious phrase to describe a method used to optimize loops. It involves removing *loop Loop-invariant expressions*, which are expressions that don't change while the loop is executing. Such a repetitive expression which computes the same thing over and over can be moved out of the loop body and its result be used instead. The following code shows bad code with Loop-invariant computations inside a loop and its equivalent with that code moved out of the loop:
63 | ```c
64 | ...
65 | for (int j = 0; j < n; j++){
66 | a[n * i + j] = b[j];
67 | }
68 |
69 | ...
70 | ...
71 |
72 | int ni = n * i; // This computation was moved outta loop
73 | for (int j = 0; j < n; j++){
74 | a[ni + j] = b[j];
75 | }
76 | ```
77 | - Compilers might be stomped and not always move loop-invariant expressions outside loops, especially if they involve aliased memories or function calls. A call to an expensive function that does the exact same thing in every iteration can be extremely costly. In such cases, the programmer might have to do such a motion manually.
78 | - The book discusses code that transform strings from upper to lower case. It involves a call to `strlen` in every iteration of the loop over the string's character. This is an expensive function that iterates over the whole string in every iteration that when run over a long string can cause some considerable performance hits. I personally wrote code that opened a database connection on every iteration of a loop!! Stupid me, but it was caught before I pushed it for review!
79 |
80 | ## Reduction in Strength:
81 | - Expensive operations can be replaced by cheaper ones. For example
82 |
83 | ## Reducing Procedure Calls:
84 | - The main thing to keep in mind about unnecessary procedure calls is that it's a major optimization blocker and the average compiler might not want optimize blocks containing unnecessary function calls lest they might have side effects. If the programmer is certain that reducing function calls will always yield the correct result, they can intervene and do it manually.
85 |
86 | ## Eliminating Unneeded Memory References:
87 | - Consider the following code and its unoptimized compiled assembly:
88 | ```c
89 | void someLoop(int *xp){
90 |
91 | int i;
92 | for (i = 0;i < 10; i++)
93 | *xp = *xp + 1;
94 | }
95 | ```
96 | ```
97 | .L3:
98 | movl (%rdi), %eax # Reading xp
99 | addl $1, %eax
100 | movl %eax, (%rdi) # writing to xp
101 | addl $1, %edx
102 | ```
103 | - The assembly snippet corresponding to the loop body shows how memory is unnecessarily accesses twice on each iteration. Add to this the issue of memory aliasing, and you end up with unoptimizable code. The overhead incurred by reading and writing in the loop with each iteration can be replaced by doing the computations inside the loop but moving the memory reference outside the loop. We only need the final result to be placed in **`*xp`**. I still don't see an explanation of what the big deal with memory references.
104 | - Wasteful memory references also apply to array indexes and arrays might suffer more from this problem.
105 |
106 | ## Understanding Modern Processors:
107 | - The techniques we've seen so-far are general common sense that should work for any platform, but there are times when we might have to optimize for a specific architecture or processor. This require some intimate knowledge of how our processor works.
108 | - One very important feature of modern processors is their ability to perform so-called **instruction-level parallelism**, whereby it can processor multiple/many instructions simultaneously while preserving the semantics of a program having instructions that run in sequence one after the other.
109 | - Instruction-level parallelism can be limited by two lower bounds:
110 | - The **latency bound** which takes place when a series of instructions must be performed in a strict sequence, one after the other. ILP cannot be done in such cases.
111 | - The **throughput bound** is the limitation caused by the "raw computing capacity of the processor’s *functional units*," whatever this really means
112 | - Some modern processors are deemed *superscalar*, meaning that they can processor multiple instructions per clock cycle and out-of-order. These processors consists of two parts:
113 | - The **instruction control unit (ICU)** which reads instructions from memory and generate primitive operations from them
114 | - The **execution unit (EU)** which execute the operations generated by the ICU.
115 | - The following diagram shows the rough general structure of a superscalar processor:
116 | 
117 | - The ICU fetches instructions from the *instruction cache* which contains recently used instructions and in general the ICU fetches instructions ahead of time an decodes them to send operation down to the EU and wastes no time, well, until it encounters a *branch* (basically a conditional jump). In this case the ICU does *speculative execution*, meaning that it predicts which branch to take and it starts to fetch, decode and even execute instructions in that branch even before it determines for sure that it is the correct branch to take. If the processor finds out it used the wrong branch, it resets everything to the branch point and starts again fetching, decoding and executing in the other direction.
118 | - When the ICU decodes an instruction, it might produce multiple primitive operations from a single instruction. These operations might then go on to be executed in parallel.
119 | - When the EU receives the primitive operations (usually multiple operations at once), it dispatches them to its *functional units* which are specialized units that perform specialized operations such as multiplications but can also do integer addition or shifting regardless of their specialties. Using the load and store functional units, the EU can read from and write to memory usually through a proxy of fast caches.
120 | - Speculative execution doesn't store data in registers until it makes sure that the branch is correct. The EU decides if the branch is correct and if not it directs the branch unit to go back, discard the incorrect processing and start over. This can be especially costly performancewise.
121 | - The *retirement unit* within the ICU is responsible for keeping track of the processing and preserving the sequential semantics of the program. It maintains a queue and a register file. The queue it uses for decoded instructions. If an instructions is predicted correctly, it is retired and the registers are updated accordingly, but if the instruction is mispredicted, then it is flushed from the queue.
122 | - To keep track of things being changed speculatively before any writing into the register file, the different execution units communicate with each other using *register naming* which involves a table that tracks the different operations being speculatively executed in the EU. These execution units communicate directly with each other without having to refer to the register file :open_mouth:.
123 | - The ability of superscalar processors to perform out-of-order instructions can be limited by **data dependencies** and need active care on the programmer's side to avoid their limitations. Data dependencies refer to situations where the an operation or instruction depends on other operations to run first to produce its operands. This depending instruction cannot start until the its operands are made ready by the previous operations it depends on.
124 |
125 | ## Loop Unrolling:
126 | - The following two C code snippets illustrate how loop unrolling works:
127 |
128 | ```c
129 | int x;
130 | for (x = 0; x < 100; x++)
131 | delete(x);
132 | ```
133 | ```c
134 | int x;
135 | for (x = 0; x < 100; x += 5 ){
136 | delete(x);
137 | delete(x + 1);
138 | delete(x + 2);
139 | delete(x + 3);
140 | delete(x + 4);
141 | }
142 | ```
143 | - Loop unrolling basically means reducing the number of iterations of a loop by increasing the number of elements computed on each iteration. Such a transformation reduces loop indexing and the number of times the finishing condition has to be checked. It also exposes ways in which the loop and program can be optimized further (we might see this later).
144 | - You need to pay special attention to the upper limit to not overrun the bounds of whatever array we are looping over. If our array's length is ***n***, and the factor by which we unroll our loop is ***k*** (equal 5 in our code example above), then its upper limit should equal ***n - k + 1***.
145 | - When you unroll loops, the compiler does some of its extra magic to optimize the code even more in ways that don't have to do with the direct effects of unrolling such as reducing iteration overhead.
146 | - Compilers also unroll loops when run on with higher optimization levels.
147 |
148 | ## Enhancing Parallelism:
149 | ### Multiple accumulators:
150 | - One situation where sequential data dependencies might become an annoying optimization blocker is when you we iterate over an array while adding or multiplying elements we encounter to some kind of accumulator. Sometimes it might be hard to do extra optimizations the value changes over each iteration and we have to wait for the ever changing new value of the accumulator. This can be overcome by using multiple accumulators that can be combined after the loop finishes. You might for example have one accumulator operating on even indexes, while another on odd numbers. Just make sure your accumulators cover all the indexes. There might be some trailing elements that don't get covered by your alternating accumulators. This can be done together with loop unrolling to achieve maximal efficiency.
151 | - I am honestly not following with the metrics devised by the book's authors and all the diagrams and whatnot, but I am understand the idea of data dependency and how it hinders parallelism. It reminds me of the JVM multithreading and how certain operations don't land themselves well to multithreading because of something similar to data dependencies.
152 |
153 | ### Reassociation Transformations:
154 | - *Reassociation transformation* refers to changing the ordering of operations through the use of parentheses in expressions. The main hurdle stomping instruction-level parallelism and pipelining are data dependencies. These dependencies can be broken through reassociations. By separating the accumulator, for example, from the rest of the chain of operation, parallelism can work at maximum capacity because the rest of the chain is independent from the accumulator (the part suffering from the data-dependency problem).
155 |
156 | ## Some Limiting Factors:
157 | - In addition to throughput and latency limitations that modern processors might face when processing certain programs, there are other limitations such as *register spilling* and the penalties incurred by *branch mispredictions*.
158 | - A system has a limited number of register which can be used to enhance parallelism, but if we run out of registers that we need for multiple accumulators, these values will be stored in the memory stack instead (this is called **register spilling**). This will significantly reduce the performance of our program and optimization starts having a reverse effect. Now the program has to read from the stack and write back to it when it original didn't have too.
159 | - Processors keep getting smarter but **misprediction penalties** are still possible and they can be a real hurdle in the way of producing efficient code.
160 |
161 | ## A Performance Improvement Strategy:
162 | - To make your program perform better do the following in the given order:
163 | - *High-Level Design*: Choose the right algorithms and data structures.
164 | - *Basic Coding Principles*: Avoid optimization blockers through the use of good clean code. Examples of this include:
165 | - Eliminate excessive function calls and move computations out of loops. Make balanced compromises code efficiency and modularity.
166 | - Eliminate unnecessary memory references. Use temporary variables to hold intermediate results and keep memory references out of loops if possible. Don't use arrays and global variables until computations are finished.
167 | - *Low-Level Optimizations*:
168 | - Unroll loops to reduce overhead and enable further optimizations.
169 | - Help increase instruction-level parallelism through the use of multiple accumulators and reassociations.
170 | - "Rewrite conditional operations in a functional style to enable compilation via conditional data transfers".
171 | - When optimizing، make sure to not alter the program's behavior. Subtle bugs and alteration to the program's behavior can easily creep in, especially when messing with array bounds and for the fact that optimization generally makes code more unreadable and complex.
172 | - Employ more tests on optimized code and code in general to check for all sorts of mistakes that might be introduced during the optimization process.
173 |
174 | ## Profiling:
175 | - It might be hard to identify parts of a large program that really need optimization. Optimization can cost time and make our programs less readable and less extendable. **Profilers** are tools programmers use to monitor the performance of
176 |
177 | - *Profiling* means the use of special tools that analyze how much time different parts of a program take while running.
178 | - UNIX's *GPROF* is one popular profiler that does two things. It tells us how much CPU time a function takes to run, and tells us how many times a function has been called (categorized by the calling function).
179 | - Profiling a program with GPROF can be done in 3 steps:
180 | 1. First compile your program with the **`-pg`** option as in **`gcc -O1 -pg prog.c`**.
181 | 2. Run your program as usual **`./a.out`**. This will generate a `gmon.out` file which contains profiling data.
182 | 3. Run GPROF with the program as its input **`gprof a.out`**. This will analyze `gmon.out` file and give you the details of the profiling.
183 | - Profiling can quickly show you bottlenecks in your program especially a large one. You can quickly see functions that get called too often or those that take too long to finish. These information can help identify possible opportunities for more optimization.
184 |
185 | ### Amdahl's Law:
186 | - Amdahl's law, formulated by Gene Amdahl, simply states that the overall effect of improving a specific part of a system depends on two factors: how significant that part of the system is and by how much its performance has been sped up.
187 | - Suppose we have a system where running an application requires time ***Told***. Suppose also that a certain part of the system takes ***α*** fraction of the running time of the application and we have improved the performance of this part by a factor of ***k***. This means the program originally took
188 | ***αTold*** and now takes ***αTold/k***. The overall execution time is:
189 | - ***Tnew = (1 - α)Told + (αTold)/k***
190 | - ***= Told[(1 - α) + α/k]***
191 | - From the formula above we can compute the speedup ***S = Told/Tnew*** as:
192 | - ***S = 1 / ((1 - α) + α/k)***
193 | - To really speed up the system, we need to improve the performance of large parts of the system. This law can be used to manage priorities and decide whether improving the performance of certain parts of the program are really worth the cost.
194 | - It looks like I've been using Amdahl's law to prioritize what school subjects to spend more time studying since primary school!
195 |
196 |
197 |
--------------------------------------------------------------------------------
/systems/processorArchitecture.md:
--------------------------------------------------------------------------------
1 | # Processor Architecture:
2 | - *(**Warning:** This summary is messy and just bad. It has some good information, but I don't think this book is doing a great job at explaining processor architecture. I think that the **MIPS** instruction set from that other book is probably better)*.
3 | -------------------------------
4 |
5 | * [The Y86-64 Instruction Set Architecture](#the-y86-64-instruction-set-architecture)
6 | + [Instruction Encoding](#instruction-encoding)
7 | + [CISC vs RISC](#cisc-vs-risc)
8 | * [Logic Design and the Hardware Design Language](#logic-design-and-the-hardware-design-language)
9 | + [Combinatorial Circuits and Boolean HCL Expressions](#combinatorial-circuits-and-boolean-hcl-expressions)
10 | + [Word-Level Combinational Circuits and HCL Integer Expressions](#word-level-combinational-circuits-and-hcl-integer-expressions)
11 | + [Memory and Clocking](#memory-and-clocking)
12 | * [Sequential Y86-64 Implementations](#sequential-y86-64-implementations)
13 |
14 | - We've been digging very close to the metal and were able to see at the machine-language level stuff C abstracted away from us. Machine language consists of sequences of very basic instructions that perform such operations as addition and checks for equality. These instructions are known collectively as an ISA (instruction set Architecture) of the processor. They also make for yet another abstraction layer which decouples the work of processor designers from that of compiler designers. Multiple processors with different architectures can have the same ISA against which compile designers improved and optimize the code generated by their compilers.
15 | - This chapter will dig in beyond the ISA and explore the design of the processor hardware and how this hardware executes the instructions of a particular ISA. This will allow us to appreciate the hard work put in by processor designers and help us have a better understanding of how computers work. We will also see another example of abstraction at work: how the ISA appears to execute instructions in sequence, but the actual processor performs its work in parallel where multiple instructions are executed simultaneously, but programs still behave in expected fashion as if instructions run one after the other.
16 | - The original content studies a toy processor and an associated instruction set called Y86-64. I have no interest in this Y86-64, and I will just look at general concepts and principles of logic and hardware design language (HDL) and the implementation of sequential vs. pipelined processors!! I will avoid details and just focus on general ideas.
17 |
18 | ## The Y86-64 Instruction Set Architecture:
19 | ### Instruction Encoding:
20 | - An important topic that I found interesting in this section is *instruction encoding*. How instructions are represented in the hardware. Each instruction (in this particular Y86-64 ISA) is between 2 and 10 bytes in lengths and consists of:
21 | - *The initial or instruction byte* defines its type. This instruction itself is split into two parts:
22 | - The *code* or high-order part is used to define a family or class of instructions that do similar operations, something like JMP or MOV.
23 | - The *function* low-order part defines specific stuff the instruction does, is it a `jle` or `jge`. Some instructions only have this byte such as `ret`.
24 | - *Register-specifier byte* is used in instructions that require one or more operands. This byte is divided into two fields. The first field is mostly used as a source and the second one as a destination and in something that has to do with computing addresses. Instructions that only have one register as an operand, can denote the empty half of the register-specifier byte with some agreed upon value like `0xF` or whatever.
25 | - An optional 8-byte *constant word* used in instructions that have an immediate or a memory location as one of its operands.
26 | - Each instruction has a unique hex value. The instruction byte can tell us what the instruction is and does and what the rest of the bytes following it do. My question is "how does the processor determine the start of an instruction?" are instructions aligned so each one is 10 bytes in length, even those that are only 1-byte in length? This is makes sense for memory, but maybe not. Because the processor can tell the size of an instruction from its starting byte, it knows exactly where to jump next.
27 |
28 | ### CISC vs RISC:
29 | - x86-64 ISA and the x86 ISA family are deemed *CISC (complex instruction set computers)*. This type of computers came first. Instruction sets grew so big as to accommodate a large number of operations and tasks. In archaic mainframes, there were instructions that even performed high-level tasks such as evaluating polynomials and doing decimal arithmetic. Early microprocessors used limited instruction sets, but as processing power became trivial they too went the CISC way. x86 followed this path.
30 | - Sometime in the 1980s, IBM researchers conceptualized the *RISC (reduced instruction set computers)* philosophy as an alternative approach to CISC which required powerful hardware and involved instructions that weren't even used that much. They proposed a simple instruction set that could run in cheap hardware and be organized in efficient pipelines.
31 | The following table summarizes how CISC differs from RISC:
32 |
33 | | CISC | RISC (Early) |
34 | | --- | --- |
35 | | Many many instructions | Very few instructions |
36 | | Arithmetic/logic operations on registers and memory operands | Arithmetic and logic operations on register operands only. Referencing memory is only done with limited number of instructions such as those storing register content in memory or copying memory content to registers, etc. This is called *load/store architecture* |
37 | | The ISA hides implementation *artifacts*, whaat :confused:. What the programs sees is a simple clean surface hiding some nasty stuff | Artifacts are exposed to to machine-level. Programmers can optimize their code against these artifacts |
38 | | Condition codes are built-in side effects for branching | No condition codes. Explicit test instructions are stored in normal registers and used for testing |
39 | | Major use of the stack by procedures for passing arguments and return addresses | Registers are used for passing arguments and return addresses. Some processes don't use any memory references. These usually have more registers (32) |
40 | - Overtime, CISC and RISC got closer to each other. RISC started incorporating many more instructions, though not too many. CISC also moved towards RISC and started translating instructions into RISC-like instructions that could be easily pipelined. However, CISC processors, represented by by x86 dominated laptops and desktops mainly because of its backward compatibility, while RISC dominated smart phones due to its power efficiency and weak-hardware friendliness
41 |
42 | ## Logic Design and the Hardware Design Language:
43 | - A digital system consists of 3 major components: *combinatorial logic* to do computations on bits, *memory elements* to store bits, and *clock signals* to regulate updates to memory elements.
44 | - This section will briefly go over these three elements and introduce HCL (hardware control language) which is a toy HDL *(hardware description language)*. It's probably not as real as Verilog and VHDL which are actually used in the process of creating microprocessors, but the point to be exposed to logic design and the work of hardware designers (though at a superficial level).
45 |
46 | ### Combinatorial Circuits and Boolean HCL Expressions:
47 | - Three basic logic gates are discussed: ***AND***, ***OR***, and ***NOT***.
48 | - These basic gates are then combined to construct **combinatorial circuits**. These combinatorial circuits can be used to perform higher-level operations, but there are some constraints on how logic gates can be combined to make such circuits:
49 | 1. Every logic gate input must be connected to exactly one of these 3 elements:
50 | a. System input (*primary input*): I believe this is something like a keyboard, maybe!
51 | b. The output of a memory element.
52 | c. The output of a logic gate.
53 | 2. The outputs of two logic gates cannot be connected together.
54 | 3. The network cannot be *cyclic*, meaning there cannot be a loop in any of the network's paths.
55 | - A basic combinatorial circuit that checks for equality between two bits can be represented in HCL as follows:
56 | ```
57 | bool eq = (a && b) || (!a && !b)
58 | ```
59 | - The following diagram shows a *multiplexer*, also called a *MUX*:
60 | 
61 | - A multiplexer selects a value from a set of data signals (inputs) based on the input of a control signal. In this image, the ***s*** is the control signal. When this signal is 1, the output is equal to to ***a***, and ***b*** when the ***s*** is 0. This circuit can be represented by the following HCL:
62 | ```
63 | bool out = (s && a) || (!s && b)
64 | ```
65 |
66 | ### Word-Level Combinational Circuits and HCL Integer Expressions:
67 | - Combinational circuits operating on single bits can be assembled into larger networks that operate on words rather than individual bits. The words themselves can be anything form integers, addresses, register identifiers or instruction codes.
68 | - Word-level combinatorial circuits operate are constructed from individual gates that operate on the individual bits of the input words and their outputs are constructed from the individual bits or the results of evaluating the individual input bits. The following image tests for equality between words ***A*** and ***B***. It applies the equality expressions we saw earlier to every individual bit from the two words. It compares A0 with B0, A1 with B1 ... A63 with B63. If the outputs of these gates are 1, then the two word are equal. This is decided by the AND gate to the right which outputs 1 only if all these outputs are true. The right side of the image shows an abstract simplification suitable for representing word operations (Notice how individual bits are drawn with a dashed line):
69 | 
70 | - Just remember that HCL is just an educational tool and probably nobody uses it to design actual hardware to just get an idea how these things are done. From now on we will treat words as data belonging to the type **`int`** and will not specify the word sizes.
71 | - HCL allows comparison between words so the circuit comparing two words in the image above can be expressed as follows:
72 | ```
73 | bool Eq = (A == B);
74 | ```
75 | - The following diagram shows a word-level multiplexer:
76 | 
77 | - The word-level multiplexer is identical to the bit-level one in that its outputs is one of the two inputs based on control bit ***s***. The cool thing is that a single inverter ***s*** is enough to compare whole words and didn't have to be repeated.
78 | - Multiplexers are fundamental components of a processor or any digital system and we will see many forms of these. They allow us to select a word from a set of inputs based on some control conditions. A multiplexing function is described using a *case expression* which looks as follows:
79 | ```
80 | [
81 | select_1: expr_1;
82 | select_2: expr_2;
83 | .
84 | .
85 | .
86 | select_k: expr_k;
87 | ]
88 | ```
89 | - This expression contains a series of cases where each *select_x* is a boolean denoting the condition of selection and and an *expr_x* indicating the result of the selection. The selection expressions are not mutually exclusive, but are evaluated in sequence. The first expression that yields 1 is selected as the following code shows:
90 | ```
91 | word Out = [
92 | s: A;
93 | 1: B;
94 | ];
95 | ```
96 | - The second selection expression in this example is 1 meaning that if no other selection was made, the expression should be defaulted to this one.
97 | - Multiplexers can be more complex with many more inputs and many more control signals with different combinations. Examine the following figure the the code following it which show how combining multiple control signals allows for many complex selection criteria:
98 | 
99 | ```
100 | word Out4 = [
101 | !s1 && !s0 : A;
102 | !s1 : B;
103 | !s0 : C;
104 | 1 : D;
105 | ]
106 | ```
107 | - The following circuit finds the minimum value among a set of words A, B and C:
108 | 
109 | ```
110 | word Min3 = [
111 | A <= B && A <= C : A;
112 | B <= A && B <= C : B;
113 | 1 : C;
114 | ]
115 | ```
116 | - Combinatorial logic circuits can so complex as to support many operations. The following diagram shows one such combinatorial circuit, called *arithmetic/logic unit*. It performs 4 kinds of arithmetic types of operations. The operation it performs on its inputs depends on the signal of the control input. The control signal matches the function codes of the 4 arithmetic operations of Y86-64 which we haven't seen!
117 | 
118 |
119 | ### Memory and Clocking:
120 | - Combinatorial circuits don't store any information. They only react to input and generate an output equal to some function of the input. Information is instead stored in **sequential circuits** which have state and performs computations on that state. These storage devices are controlled by a systewide *clock*, which is a periodic signal that determines when new values are to be loaded in these sequential devices. There are two types of memory classes:
121 | - **Clocked Registers** can store single bits or words. The clock controls when values are loaded into their inputs.
122 | - **Random access memories** which store multiple words and use addresses to write and read data. They include virtual memory and register files. Register identifiers are used as register addresses.
123 | - Being a sequential circuit controlled by a clock, the register's state remains the same even if its input has changed. The state only changes to reflect the value of its input when the clock signal rises. The following diagram shows how the register state remains ***x*** even though its input is ***y***. Once the clock rises, the register state becomes ***y*** reflecting the value in its input. The state of a register only changes when the clock signal rises. "Registers serve as barriers between the combinational logic in different parts of the circuit. Values only propagate from a register input to its output once every clock cycle at the rising clock edge". Registers hold important values such as the program counter (PC) and condition codes (CC):
124 | 
125 | - The following image shows a typical clocked register:
126 | 
127 | - The register file shown in the diagram above has:
128 | - Two *read ports* named *A* and *B*. This means the register file can read the values of two registers at the same time. The two read ports have address inputs (*srcA* and *srcB*) which are register identifiers indicating which registers to read from. They also have data outputs (*valA* and *valB*) extracting data from the given addresses.
129 | - One *write port* named *W*. It has an *address input* *dstW* and a value output *valW*.
130 | - The memory is kinda simpler. It has one address input indicating where to write or read from, a *data in* of value to be written into the given address, and a *data out* for reading. The *read* and *write* are used to control if at a given moment data should be read from memory or written to it. The *error* signal is set to 1 if there is an error such as when trying to write in non-existing address outside the bounds of existing memory:
131 | 
132 |
133 | ## Sequential Y86-64 Implementations:
134 | - A sequential processor is one that processes instructions one after the other and each instruction is broken into different operations that are run in a sequence of stages. Instructions differ in what they do and in their structures but they are all run using the same sequence of stages.
135 | - Processing an instruction can be done in the following sequence of stages:
136 | - **Fetch** reads the bytes of an instruction from memory. It extracts the instruction code and instruction function which constitute the first byte of the instruction. It also possibly extracts one register specifiers from the register byte and maybe an 8-byte value containing a memory address or an immediate value. It then computes the PC value which is the current value of PC plus the length of the currently fetched instruction.
137 | - **Decode** reads the operands from the two registers
138 | - **Execute** is done by the ALU. The ALU performs the instruction's operation or computes the effective address of a memory reference, etc.
139 | - **Memory** reads data from memory or writes data into it.
140 | - **Write back** writes data into one or two results into the register file.
141 | - **PC update** involves setting the PC to the address of the next instruction.
142 | - The processor runs in an infinite loop performing instruction until it encounters an exception of sorts. It stops or enter an exception handling state.
143 |
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/systems/systemLevelIO.md:
--------------------------------------------------------------------------------
1 | # System Level IO:
2 | ## Table of Content:
3 | * [Introduction](#introduction)
4 | * [Unix IO](#unix-io)
5 | * [Opening and Closing Files](#opening-and-closing-files)
6 | * [Reading and Writing Files](#reading-and-writing-files)
7 | * [Robust Reading and Writing with the Rio Package](#robust-reading-and-writing-with-the-rio-package)
8 | * [Reading File Metadata](#reading-file-metadata)
9 | * [Sharing Files](#sharing-files)
10 | * [IO Redirection](#io-redirection)
11 | * [Standard I/O](#standard-i/o)
12 | * [Putting It Together Which I/O Functions Should I Use?](#putting-it-together-which-i/o-functions-should-i-use)
13 |
14 | ## Introduction:
15 | - **Input/Output (IO)** is the process of copying data between main memory and external devices such as networks, displays or storage devices. An **input** operation copies data from an IO device to main memory, while **output** is copying data from main memory to an IO device.
16 | - All languages provide out-of-the-box higher-level IO packages which include such important functions as `printf`. These higher-level functions themselves are based on the system-level *Unix IO* functions provided by the kernel. The higher-level IO packages do most of what a programmer really needs, so why study the low-level Unix IO? There are a few reasons which include:
17 | - **Understanding Unix IO is a prerequisite to understanding other systems concepts:** IO concepts are central to systems in general and many other aspects of systems are deeply interdependent with IO. For example, creating a new process does involve one aspect or another of IO. Processes themselves are also fundamental to understanding IO. We have touched in previous documents on a few IO topics when we discussed memory hierarchy, virtual memory and processes. This document will be a deeper treatment of IO and its particular features.
18 | - **There are IO services that can only be accessed by raw Unix IO:** There are some IO services that cannot be accessed with language higher-level IO packages such as file metadata (file size or creation date). IO packages also have shortcomings that prevents them from being used safely in network programming.
19 | - This document will be an introduction to the general concepts of Unix IO and standard IO and how to use them effectively.
20 |
21 | ## Unix IO:
22 | - A Unix **file** is a sequence of ***m*** bytes:
23 | - ***B0, B1, ..., Bk, ..., B***
24 | - All IO devices such as networks, disks, displays, keyboards, etc. are modeled as files and all input and output are performed by reading from and writing to these files. This simple mapping between devices and files allows for a simple interface known as the **Unix IO** which allows for all IO operations to be done in a consistent way across different types of devices:
25 | - **Opening files**: An application indicates that it wants to access an IO device by asking the kernel to **open** its file. The kernel returns a small nonnegative number called a **descriptor**. The descriptor identifies the file in all the following operations. The kernel keeps track of all information about the open file, while the application keeps track of the file descriptor. When you create a process by a Unix shell, the process starts life with 3 open files: **standard input** with descriptor 0, **standard output** with descriptor 1, and **standard error** with descriptor 2. `` holds constants for these descriptors: **`STDIN_ FILENO`**, **`STDOUT_ FILENO`**, and **`STDERR_FILENO`**.
26 | - **Changing the current file position**: The **file position** of an open file is a byte offset of a certain value from the beginning of a file. It is initially 0 and is maintained by the kernel. The application can explicitly set the file position with the **seek** operation.
27 | - **Reading and writing files**: A **read** operation copies ***n > 0*** bytes from a file to memory starting at the current file position, and incrementing the file position by ***n***. If the size of the file is ***m*** bytes, then when the file position is equal to or larger than ***m***, a condition called **edge-of-file (EOF)** is triggered. EOF can be detected by the application. There is no *"EOF character"* at the end of the file! *Thank you!!* The **write** operation follows similar steps with the exception that it copies bytes from memory to the file.
28 | - **Closing files**: When the application finishes accessing the file, it tells the kernel to **close** the file. The kernel frees "the data structures it created when the file was opened and restor[es] the descriptor to a pool of available descriptors." If the terminal terminates normally or unexpectedly, the kernel closes all open files and frees their memory resources.
29 |
30 | ## Opening and Closing Files:
31 | - The **`open`** function can open an existing file or create a new file:
32 | ```c
33 | #include
34 | #include
35 | #include
36 |
37 | int open(char *filename, int flags, mode_t mode); // Returns descriptor, or -1 on error
38 | ```
39 | - The `open` function "converts" a `filename` to a file descriptor and returns the descriptor number to the calling process. The descriptor returned is the smallest descriptor that is not current opened in the process.
40 | - The **`flags`** argument tells us how the process wants to access the file:
41 | - **`O_RDONLY`**: Read only.
42 | - **`O_WRONLY`**: Write only.
43 | - **`O_RDWR`**: Write and read.
44 | - The `flags` argument can also be *OR*'d with more instructions for writing:
45 | - **`O_CREAT`**: If a file with the given name doesn't exist, create a *truncated* version of it.
46 | - **`O_TRUNC`**: If the file exists, truncate it (empty it).
47 | - **`O_APPEND`**: Before writing, set file position to the end of the file.
48 | - The following examples opens a file with the intention of starting to write at the end of it:
49 | ```c
50 | fd = open("somefile.txt", O_WRONLY | O_APPEND, 0);
51 | ```
52 | - The mode arguments decides the accessing permission bits of a new file. These bits are shown in the following table:
53 |
54 | | Mask | Description |
55 | | --- | --- |
56 | | `S_IRUSR` | User (owner) can read this file |
57 | | `S_IWUSR` | User (owner) can write this file |
58 | | `S_IXUSR` | User (owner) can execute this file |
59 | | `S_IRGRP` | Members of the owner's group can read this file |
60 | | `S_IWGRP` | Members of the owner's group can write this file |
61 | | `S_IXGRP` | Members of the owner's group can execute this file |
62 | | `S_IROTH` | Others (anyone) can read this file |
63 | | `S_IWOTH` | Others (anyone) can write this file |
64 | | `S_IXOTH` | Others (anyone) can execute this file |
65 |
66 | - The context of each process has a `umask` (whatever that means) which is set by the `umask` function. When a process creates a new file with the `open` function using the `mode` argument, the access permission bits of the file are set to `mode & ~umask`
67 | - The following macros define an example of default `mode` and `umask` you can make:
68 | ```c
69 | #define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
70 | #define DEF_UMASK S_IWGRP|S_IWOTH
71 | ```
72 | - The following code uses the definitions above to create a new file where only the owner has read and write permissions, while everyone else has read permissions only:
73 | ```c
74 | umask(DEF_UMASK);
75 | fd = Open("somefile.txt", O_CREAT|O_TRUNC|O_WRONLY, DEF_MODE);
76 | ```
77 | - Opened files can be closed with the **`close`** function which takes a file descriptor as an argument. Closing a descriptor that is already closed results in an error:
78 | ```c
79 | #include
80 |
81 | int close(int fd); // Returns 0 if ok, -1 on error
82 | ```
83 |
84 | ## Reading and Writing Files:
85 | - Applications perform input with the **`read`** function and output with the **`write`** function:
86 | ```c
87 | #include
88 |
89 | // Returns: number of bytes read if OK, 0 on EOF, −1 on error
90 | ssize_t read(int fd, void *buf, size_t n);
91 |
92 | // Returns: number of bytes written if OK, −1 on error
93 | ssize_t write(int fd, const void *buf, size_t n);
94 | ```
95 | - The `read` function copies at most `n` bytes from the file pointed to be descriptor `fd` to memory location `buf`. On error, `read` returns -1, and returns 0 on EOF. Normally, it returns the number of bytes that were coppied from `fd` to `byte`.
96 | - **`write`** does the exact same thing but in reverse: it copies bytes from memory location `buf` to file `fd`.
97 | - The following code copies standard input to standard output one byte at a time:
98 | ```c
99 | #include
100 | #include
101 |
102 | int main(){
103 | char c;
104 | while(read(STDIN_FILENO, &c, 1) != 0)
105 | write(STDOUT_FILENO, &c, 1);
106 | exit(0);
107 | }
108 | ```
109 | - The current file position can be manipulated with the **`lseek`** function.
110 | - In some cases `read` and `write` transfer less bytes than the application requests. These are called *short counts* they are not necessarily errors, but might occur for some reasons such as:
111 | - *Encountering EOF on reads*: If the application requests a 100 bytes from a file that has only 20 bytes, the first `read` will return the short count 20 and the next `read` returns the short count 0, coz it encounters EOF.
112 | - *Reading text lines from a terminal*: If the open file is associated with the terminal (keyboard, display, etc.), `read` can only read one line at a time. If you requests chunks of 100 bytes and a line is shorter than 100, you get a short line.
113 | - *Reading and wring sockets*: If the open file is a network socket, "then internal buffering constraints and long network delays" can cause short counts. Short counts can also happen due to the Unix *pipe*.
114 | - Short counts are almost never encountered when reading from or writing to disk except on EOF, but to have reliable network applications, we need to overcome short counts caused by network latency and other reasons.
115 |
116 | ## Robust Reading and Writing with the Rio Package:
117 | - *This section went over creating a IO package resilient to short counts, but what I thought was interesting is the difference between buffered and unbuffered IO. I understand the general idea, but I'm not sure about the details. Basically, with buffering a whole block of bytes gets written or read at once, instead of reading/writing each byte individually. The block of bytes gets stored somewhere between operations. The common opinion is that buffering reduces overhead because there are not system calls for each byte and that fewer calls are performed for a whole block than for each byte in the block. One thing that really confused me from the text is a claim that buffered IO is good for text files, while unbuffered IO is good for text files, while binary data is bettered IOed without buffering.I checked online and couldn't find definitive answers to anything about buffering and often some conflicting "opinions", the most confusing of which was that buffering might be bad because we are doing [double buffering](https://www.quora.com/What-is-a-good-explanation-of-buffered-I-O). Even when reading the C programming language book, I was stomped at one of the later chapters that was about Unix IO. Probably, I might have to come back to this subject in the future.*
118 |
119 | ## Reading File Metadata:
120 | - Information about a file or **metadata** can be gotten by a call to **`stat`** or **`fstat`**:
121 | ```c
122 | #include
123 | #include
124 |
125 | int stat(const char *filename, struct stat *buf);
126 | int fstat(int fd, struct stat *buf);
127 | ```
128 | - `stat` takes a file name and a struct of type `stat` as arguments, while `fstat` takes a file descriptor instead of a file name. Both function fills the `stat` struct with the file's metadata. This struct has several information about the file such as its owner and group IDs, its size in bytes, the time it was created, modified and accessed and also about its protection and file type. The following code prints the time when the file was last accessed (seconds that had elapsed since January 1, 1970!):
129 | ```c
130 | #include
131 | #include
132 | #include
133 |
134 | int main(int argc, char **argv){
135 | struct stat ztat;
136 |
137 | stat(argv[1], &ztat);
138 |
139 | printf("%ld\n", ztat.st_atime);
140 |
141 | return 0;
142 | }
143 | ```
144 | - Some of the more important file metadata include its type which is denoted by the `st_mode` element of the `stat` struct. A file can be either a *regular file*, a *directory* which contains information about other files, or a *socket* which is a file used to communicate with other processes across a network.
145 | - File size is denoted by the `st_size` element of the `stat` struct. It is in bytes.
146 |
147 | ## Sharing Files:
148 | - Unix files can be shared (between what and what) in different ways. To understand file sharing, we need to first understand how the kernel represents open files. Open files are represented by the kernel in 3 related data structures:
149 | - **Descriptor table**: Each process has its own descriptor table with entries indexed by the process's open file descriptors. Each open descriptor entry points to an entry in the *file table*.
150 | - **File table**: is the set of open files in the whole system. It is shared by all processes. Each entry in the table contains information such as the file current position, a *reference count* of the number of open file descriptor point to it, and a pointer to the *v-node table*.
151 | - **v-node table:** is also shared by all processes. Each entry contains most of the information in the `stat` struct of the file.
152 | - The following image shows a processor with two descriptors referencing two distinct files through two different file descriptors. These files are not shared and each descriptor references a distinct file. This is the normal non-problematic case:
153 | 
154 | - The weird part is that multiple descriptors from the same process can reference the same file through different file table entries. The main differentiator is that each file descriptor has its own file position as the following image shows:
155 | [Kernel data structures for open files (2 descriptors per file)](img/process2files.png)
156 | - When a processes creates child process with `fork`, the child process inherits exact copies of the file descriptors of the parent. They share the same file positions. Both parent and child must close these shared file descriptors before the file table entry of the file can be deleted:
157 | [Kernel data structures for open files (Parent and child sharing files)](img/parentChildFileDescs.png)
158 |
159 | ## IO Redirection:
160 | - Unix's **IO redirection** means allowing the user to associate standard output and input with disk files. When you run the shell command **`ls > somefile.txt`**, you are printing the results of `ls` to the disk file `somefile.txt`, meaning redirecting in from standard output. "A Web server performs a similar kind of redirection when it runs a CGI program on behalf of the client."
161 | [IO redirection using dup2](img/ioRedirectionDup2.png)
162 | - One way to do IO redirection is with the **`dup2`** function:
163 | ```c
164 | #include
165 |
166 | // Returns: nonnegative descriptor if OK, −1 on error
167 | int dup2(int oldfd, int newfd);
168 | ```
169 | - `dup2` copies descriptor table entry `oldfd` to descriptor table entry `newfd`. If `newfd` is already open, then `dup2` closes it before copying to it.
170 | - Imagine we have a process with two descriptors and the same file position. We then redirect one of the two files to the other. Now both descriptors will point the second file through its file table entry. The first file is closed and its file table entry is deleted. Everything written to the first will be directed to the second one.
171 |
172 | ## Standard I/O:
173 | - We might not have to dip or hands deep in the muddied waters of low level Unix IO, as C provides us with the convenient **standard IO** (``). It provides `fopen` and `fclose` for opening and closing a file, `fread` and `fwrite` for reading and writing bytes, `fgets` and `fputs` for writing and reading strings, and `printf` and `scanf` for sophisticated formatted IO.
174 | - An open file in stdio is abstracted as a **stream**, which isa basically a pointer to structure of type `FILE`.
175 | - Each C program starts with 3 open streams: `stdin` (standard input), `stdout` (standard output), and `stderr` (standard error):
176 | ```c
177 | #include
178 |
179 | extern FILE *stdin; // 0
180 | extern FILE *stdout; // 1
181 | extern FILE *stderr; // 2
182 | ```
183 | - A stream of type `FILE` is an abstraction for a descriptor and a *stream buffer*. Streams are basically buffered IO structures, which are more efficient because they minimize IO system calls. Even for IO calls that read a single byte at a time such as `getc`, a stream buffer gets filled for each call, and the next bytes are retrieved from this buffer instead of from disk.
184 |
185 | ## Putting It Together: Which I/O Functions Should I Use?
186 | - When it comes to IO, you can directly use IO functions implemented in the OS kernel itself, such as the Unix `open`, `close`, `read`, `write`, `lseek` and `stat` functions. You can also write your own packages where you tweak things to serve your specific needs. There is also an amazing battle tested stdio library that has been used by generations of programs.
187 | - You might never have to bother with the low Unix IO functions or develop your own packages, but deal exclusively with the standard IO utilities offered by the standard library. There are situations, though, where stdio is not ideal, namely when dealing with network socket files, mainly because standard IO streams have their own restrictions which interfere with restrictions imposed on socket files.
188 | - stdio streams are *full duplex*, meaning both input and output can be performed on the same stream. What follows from that are the following two restrictions:
189 | - When an *input function follows an output function,* the function `fflush` (for emptying the stream buffer), `fseek`, `fsetpos`, or `rewind` (these 3 functions set file position) must be called between the two calls.
190 | - When an *output function follows an input function,* `fseek`, `fsetpos`, or `rewind` must be called between the two, unless the input function encounters an EOF.
191 | - Such restrictions are problematic for network applications because it's illegal to call `lseek` in sockets. The first restriction can be mitigated by flushing the the stream buffer before every call to input. To get around the second restriction, we open 2 streams on the same open socket descriptor, one for input and the second for output:
192 | ```c
193 | FILE *fpin, *fpout;
194 |
195 | fpin = fdopen(sockfd, "r");
196 | fpout = fdopen(sockfd, "w");
197 | ```
198 | - To free the resources associated with this socket, both streams need to be closed with:
199 | ```c
200 | fclose(fpin);
201 | fclose(fpout);
202 | ```
203 | - One of these of these calls will close the open file, but the second will fail because it is called on a closed file. This is fine for sequential programs but a big problem for multi-threaded programs.
204 | - The book recommends using their own RIO package or something robust when dealing with networks.
205 |
--------------------------------------------------------------------------------