<commit_before>## Chapter 1


### Compilation

1) Give an example of a feature common in interpreted languages that is rare in compiled languages.
Platform independance - since compiled languages are compiled into machine specific assembly, they are specific to that machine whereas interpreted languages work under the same interface regardless of platform. Another big one would be that the use of dynamic types is almost exclusively reserved for interpreted languages

2) Name two advantages of static typing over dynamic typing.
In static typing, many errors can be caught earlier in the development process (for instance, if an integer maps to a string, that would be caught compile-time in static typing, but not until run-time in dynamic typing.  Also since everything is pre-assigned compile-time in static typing, the run speed would probably be faster for static typing.

3) Give an example of a static semantic error.
Failure to declare a variable.  (quick note to self, a semantic error is an error that is different from syntactic errors...they are dynamic if not caught until run-time and static if the compiler can detect it)

4) What are two reasons you might want to turn off code optimization?
Debugging your code in assembly - turning off optimization might make it more readable. Another reason might be if you want to try to optimize your code manually or in a different way.

5) When you run `gcc` with `-S`, why might the results look different on different computers?
Since -S generates assembly code - could look different on different computers since assembly code is machine specific.  A different machine architecture would mean that the assembly code would be different.

6) If you spell a variable name wrong, or if you spell a function name wrong, 
the error messages you get might look very different.  Why?
Misspelled variables will be caught during compilation whereas a misspelled function would be caught during linking, hence the different error messages.

7) What is a segmentation fault?
Segmentation fault occurs when a program tries to read or write to the wrong type of memory (for instance trying to grab a global variable out of the stack).

## Chapter 2


### Processes

1) Give a real-world example of virtualization (ideally not one of the ones in the book).
Classrooms - each class (usually) feels like they 'own' all the space, but really it is a shared space where each class virtually owns the space when no other class is using it

2) What is the difference between a program and a process?
Put simply, a process is a running program...a program is a set of instructions.

3) What is the primary purpose of the process abstraction?  What illusion does the process abstraction create?
Process abstraction is a way of allowing users and developers to more easily work with complicated systems, a specific example is virtualization by which the process 'thinks' it has exclusive access to all of the resources on the computer.
4) What is the kernel?
The kernel is the part of the operating system responsible for core capabilities like starting threads

5) What is a daemon?
A daemon is a process that runs in the background to provide operating system services 

## Chapter 3


### Virtual memory

1) The Georgian alphabet has 33 letters.  How many bit are needed to specify a letter?
You would need 6 bits (2^5 only equals 32, 2^6 is 64.)

2) In the UTF-16 character encoding, the binary representation of a character can take up to 32 bits.  
Ignoring the details of the encoding scheme, how many different characters can be represented?
2^32 characters, or about 4.2 Billion characters

3) What is the difference between "memory" and "storage" as defined in Think OS?
If it is volatile then it is (typically) memory, if non-volatile then it is (typically) storage - i.e. if its contents are lost when the computer is powered down then memory, otherwise storage.

4) What is the difference between a GiB and a GB?  What is the percentage difference in their sizes?
GiB is a power of 2 (2^30) whereas GB is a power of 10 (10^9). The percentage difference is ~7%.

5) How does the virtual memory system help isolate processes from each other?
It helps isolate processes by using virtual memory addresses that are then mapped to physical address - such that there is NO virtual address that will map to the physical address that another process is using (unless specifically told to do so?)

6) Why do you think the stack and the heap are usually located at opposite ends of the address space?
The heap and stack are probably located at opposite ends because they are the memory segments that vary most in size...it gives room for both of them to 'grow' or 'shrink' without running into each other or bumping things around.
7) What Python data structure would you use to represent a sparse array?
I personally would probably use a dictionary, but I also think that there are libraries that allow you to create sparse arrays and sparce matrices directly (though under the hood, do they just use dictionaries?)
8) What is a context switch?
A context switch is when the CPU switches from one process to another

In this directory, you should find a subdirectory named `aspace` that contains `aspace.c`.  Run it on your computer and compare your results to mine.
  
1) Add a second call to `malloc` and check whether the heap on your system grows up (toward larger addresses).  

2) Add a function that prints the address of a local variable, and check whether the stack grows down.  

3) Choose a random number between 1 and 32, and allocate two chunks with that size.  
How much space is there between them?  Hint: Google knows how to subtract hexadecimal numbers.


## Chapter 4


### Files and file systems

1) What abstractions do file systems provide?  Give an example of something that is logically 
true about files systems but not true of their implementations.

2) What information do you imagine is stored in an `OpenFileTableEntry`?

3) What are some of the ways operating systems deal with the relatively slow performance of persistent storage?
Block transfers, Prefetching, Buffering, and Caching - essentially the time it takes to retreive an 8 KiB block is about the same as it takes to load a single byte, sometimes the program can just load the whole block (making the assumption that it will probably need other parts of the block?). Prefetching is basically what it sounds like - the operating system predicts that it will need something and loads it ahead of time. Buffering is that after you write something, it is only stored in memory not storage - if you change the block several times before it is written to the disk then you only have to write to the disk once.  Caching is that if a process used a block of memory recently, the operating system keeps a copy of the block in its cache so it can handle future requests with greater speed.


4) Suppose your program writes a file and prints a message indicating that it is done writing.  
Then a power cut crashes your computer.  After you restore power and reboot the computer, you find that the <commit_msg>Update thinkos.md<commit_after>## Chapter 1


### Compilation

1) Give an example of a feature common in interpreted languages that is rare in compiled languages.
Platform independance - since compiled languages are compiled into machine specific assembly, they are specific to that machine whereas interpreted languages work under the same interface regardless of platform. Another big one would be that the use of dynamic types is almost exclusively reserved for interpreted languages

2) Name two advantages of static typing over dynamic typing.
In static typing, many errors can be caught earlier in the development process (for instance, if an integer maps to a string, that would be caught compile-time in static typing, but not until run-time in dynamic typing.  Also since everything is pre-assigned compile-time in static typing, the run speed would probably be faster for static typing.

3) Give an example of a static semantic error.
Failure to declare a variable.  (quick note to self, a semantic error is an error that is different from syntactic errors...they are dynamic if not caught until run-time and static if the compiler can detect it)

4) What are two reasons you might want to turn off code optimization?
Debugging your code in assembly - turning off optimization might make it more readable. Another reason might be if you want to try to optimize your code manually or in a different way.

5) When you run `gcc` with `-S`, why might the results look different on different computers?
Since -S generates assembly code - could look different on different computers since assembly code is machine specific.  A different machine architecture would mean that the assembly code would be different.

6) If you spell a variable name wrong, or if you spell a function name wrong, 
the error messages you get might look very different.  Why?
Misspelled variables will be caught during compilation whereas a misspelled function would be caught during linking, hence the different error messages.

7) What is a segmentation fault?
Segmentation fault occurs when a program tries to read or write to the wrong type of memory (for instance trying to grab a global variable out of the stack).

## Chapter 2


### Processes

1) Give a real-world example of virtualization (ideally not one of the ones in the book).
Classrooms - each class (usually) feels like they 'own' all the space, but really it is a shared space where each class virtually owns the space when no other class is using it

2) What is the difference between a program and a process?
Put simply, a process is a running program...a program is a set of instructions.

3) What is the primary purpose of the process abstraction?  What illusion does the process abstraction create?
Process abstraction is a way of allowing users and developers to more easily work with complicated systems, a specific example is virtualization by which the process 'thinks' it has exclusive access to all of the resources on the computer.
4) What is the kernel?
The kernel is the part of the operating system responsible for core capabilities like starting threads

5) What is a daemon?
A daemon is a process that runs in the background to provide operating system services 

## Chapter 3


### Virtual memory

1) The Georgian alphabet has 33 letters.  How many bit are needed to specify a letter?
You would need 6 bits (2^5 only equals 32, 2^6 is 64.)

2) In the UTF-16 character encoding, the binary representation of a character can take up to 32 bits.  
Ignoring the details of the encoding scheme, how many different characters can be represented?
2^32 characters, or about 4.2 Billion characters

3) What is the difference between "memory" and "storage" as defined in Think OS?
If it is volatile then it is (typically) memory, if non-volatile then it is (typically) storage - i.e. if its contents are lost when the computer is powered down then memory, otherwise storage.

4) What is the difference between a GiB and a GB?  What is the percentage difference in their sizes?
GiB is a power of 2 (2^30) whereas GB is a power of 10 (10^9). The percentage difference is ~7%.

5) How does the virtual memory system help isolate processes from each other?
It helps isolate processes by using virtual memory addresses that are then mapped to physical address - such that there is NO virtual address that will map to the physical address that another process is using (unless specifically told to do so?)

6) Why do you think the stack and the heap are usually located at opposite ends of the address space?
The heap and stack are probably located at opposite ends because they are the memory segments that vary most in size...it gives room for both of them to 'grow' or 'shrink' without running into each other or bumping things around.
7) What Python data structure would you use to represent a sparse array?
I personally would probably use a dictionary, but I also think that there are libraries that allow you to create sparse arrays and sparce matrices directly (though under the hood, do they just use dictionaries?)
8) What is a context switch?
A context switch is when the CPU switches from one process to another

In this directory, you should find a subdirectory named `aspace` that contains `aspace.c`.  Run it on your computer and compare your results to mine.
  
1) Add a second call to `malloc` and check whether the heap on your system grows up (toward larger addresses).  

2) Add a function that prints the address of a local variable, and check whether the stack grows down.  

3) Choose a random number between 1 and 32, and allocate two chunks with that size.  
How much space is there between them?  Hint: Google knows how to subtract hexadecimal numbers.


## Chapter 4


### Files and file systems

1) What abstractions do file systems provide?  Give an example of something that is logically 
true about files systems but not true of their implementations.
File systems abstract everything as a stream of bytes rather than interfacing directly with the blocks on the hard drive.

2) What information do you imagine is stored in an `OpenFileTableEntry`?
I would imagine that it is similar to a page table, except instead of mapping virtual memory addresses to physical memory addresses it maps a table entry to the actual hard drive block location.

3) What are some of the ways operating systems deal with the relatively slow performance of persistent storage?
Block transfers, Prefetching, Buffering, and Caching - essentially the time it takes to retreive an 8 KiB block is about the same as it takes to load a single byte, sometimes the program can just load the whole block (making the assumption that it will probably need other parts of the block?). Prefetching is basically what it sounds like - the operating system predicts that it will need something and loads it ahead of time. Buffering is that after you write something, it is only stored in memory not storage - if you change the block several times before it is written to the disk then you only have to write to the disk once.  Caching is that if a process used a block of memory recently, the operating system keeps a copy of the block in its cache so it can handle future requests with greater speed.


4) Suppose your program writes a file and prints a message indicating that it is done writing.  
Then a power cut crashes your computer.  After you restore power and reboot the computer, you find that the 
{'fraction_non_alphanumeric': 0.0325080584322063, 'fraction_numerical': 0.008915712228242233, 'mean_word_length': 4.300617957106507, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2734204', 'n_tokens_mistral': 3389, 'n_tokens_neox': 3241, 'n_words': 2447}