stuff
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
soln/
|
||||
320
00-WSLSetup/LinuxVMSetup.md
Normal file
320
00-WSLSetup/LinuxVMSetup.md
Normal file
@@ -0,0 +1,320 @@
|
||||
## Introduction
|
||||
|
||||
The purpose of this assignment is to set up the Windows Subsystem for Linux (WSL). WSL acts as a virtual machine that will allow you to develop code on a Linux based operating system while working in your Windows environment. By completing this exercise, you will have the ability to install Linux within WSL, create a program, and start learning about operating systems based on Linux.
|
||||
|
||||
For more information on WSL see the documentation on Microsoft's web page: [https://docs.microsoft.com/en-us/windows/wsl/](https://docs.microsoft.com/en-us/windows/wsl/)
|
||||
|
||||
## Objectives
|
||||
|
||||
By the end of this assignment you will be able to:
|
||||
|
||||
- Create a fresh installation of Linux
|
||||
- Understand the concepts of the Windows Subsystem for Linux (WSL)
|
||||
- Demonstrate an ability to use a Linux shell.
|
||||
- Use the 'man' command to obtain documentation about Linux commands
|
||||
- Explain how to list the contents of a directory in multiple forms.
|
||||
- Navigate the Linux file system by changing directories.
|
||||
- Manage the creation and deletion of new files and directories from within the command shell.
|
||||
- Capture the output of a Linux program executing to a file.
|
||||
|
||||
## Install Windows Subsystem for Linux (WSL)
|
||||
|
||||
The following procedure is documented in Microsoft's WSL install weg page: [https://docs.microsoft.com/en-us/windows/wsl/install](https://docs.microsoft.com/en-us/windows/wsl/install)
|
||||
|
||||
While often you hear of Linux described as an operating system, Linux itself is not an operating system, but a kernel. Many operating systems have been built using the linux kernel. These operating systems are often called 'distributions'. To install a Linux distribution in WSL, you need to perform 2 things:
|
||||
|
||||
1. Install the WSL version of the Linux kernel
|
||||
2. Install the distribution for the Linux operating system
|
||||
|
||||
Microsoft makes this easy by doing both in a single step. By default, the WSL installer installs the Ubuntu Linux distribution, which is sufficient for the work we'll be doing. If you want to look into installing other distributions, you can find information on the Microsoft WSL install web site: [https://docs.microsoft.com/en-us/windows/wsl/install#ways-to-run-multiple-linux-distributions-with-wsl](https://docs.microsoft.com/en-us/windows/wsl/install#ways-to-run-multiple-linux-distributions-with-wsl)
|
||||
|
||||
To install WSL and Ubuntu:
|
||||
|
||||
1. Open a command window as Administrator
|
||||
1. Open the start menu and type ```cmd.exe```
|
||||
2. In the menu on the right, click: Run as Administrator
|
||||
2. When the command prompt opens run ```wsl --install```
|
||||
|
||||
This might take a while as WSL installs the kernel and the Linux distribution. You'll see status messages printed to the command prompt as it goes.
|
||||
|
||||
Once it has completed installation, you will be asked to create a username and password for your Linux distribution. This does not need to be the same as your Windows login, but it might be easier to remember if you do set it to the same. The choice is yours.
|
||||
|
||||
## File System Setup
|
||||
|
||||
Once the installation completes, and you create a username and password you will see a slightly different command prompt. You are now running in the Ubuntu Linux environment. Any command you type will default to a Linux command.
|
||||
|
||||
### Accessing Windows Files from Linux
|
||||
|
||||
On Windows, the file system is typically NTFS and is organized by drive (e.g. C:\ or D:\ etc.). The file system works slightly different on Linux. Directories (i.e Folders) are 'mounted' inside each other. You can think of it like a book on a bookshelf. Each disk drive on your system is like a book and the file system as a whole is like the shelf. In Windows, each book is given a drive letter, while in Linux each book is given a directory name.
|
||||
|
||||
For example, to access your Windows file system from Linux you have to go where it is mounted (e.g. what shelf it is on). In WSL, the mount point for each drive is in ```/mnt```.
|
||||
|
||||
NOTE: that Linux uses forward slash '/' to delimit a directory while Windows uses the backslash '\'.
|
||||
|
||||
The ```cd``` command allows you to change directories while the ```ls``` command allows you to list the contents of a directory from the command line.
|
||||
|
||||
```text
|
||||
user@machine:~$ ls /mnt
|
||||
c wsl
|
||||
user@machine:~$
|
||||
```
|
||||
|
||||
This lists the contents of the ```/mnt``` directory. In this example, there are two things ```c``` which represents the C: 'drive' on Windows and another directory ```wsl``` which WSL uses for device mapping.
|
||||
|
||||
You can access any file in your Windows C: drive from Linux though ```/mnt/c/```.
|
||||
|
||||
For example, to list the contents of your Windows desktop you'd type:
|
||||
|
||||
```
|
||||
user@machine:~$ ls /mnt/c/Users/WINDOWSUSERID/Desktop/
|
||||
```
|
||||
|
||||
Replacing ```WINDOWSUSERID``` with your actual Windows username.
|
||||
|
||||
### Accessing Linux Files from Windows
|
||||
|
||||
On Windows, files are typically accessed through the File Explorer. WSL makes it easy to get to the Linux file system through the File Explorer. You can actually open the Windows File Explorer directly from your Linux command line.
|
||||
|
||||
```text
|
||||
user@machine:~$ explorer.exe .
|
||||
```
|
||||
|
||||
NOTE: it is important to use the add the dot (.) after the command. The dot tells the Windows File Explorer to open the current directory (e.g. your Linux directory) instead of the default directory on Windows.
|
||||
|
||||
When the File Explorer opens you'll notice that your Linux file system is actually mapped to a network device in Windows, most likely: ```\\wsl$\Ubuntu```. If you installed a different Linux distribution, the name might be different.
|
||||
|
||||
On Windows, the folder for all of your user files (desktop, document, etc.) is located in ```C:\Users\WINDOWSUSERID```. On most Linux distributions, your Linux user files are located in ```/home/LINUXUSERID```. Using the File Explorer that is equivalent to ```\\wsl$\Ubuntu\home\LINUXUSERID```.
|
||||
|
||||
Find this folder on your Windows File Explorer and add it to your quick access bar. It will be very helpful to do this for accessioning your Linux file later.
|
||||
|
||||
## Installing Software
|
||||
|
||||
We'll need to use several Linux applications in this class. Installing software in Linux is pretty easy. Ubuntu provides a command called ```apt``` which stands for Application Package Tool. It utilizes a central repository for commands that can be installed directly from the command line.
|
||||
|
||||
To install the software we'll need for this course run the following. You'll have to enter your password to grant ```apt``` administrator authority on your Linux installation.
|
||||
|
||||
```text
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc make
|
||||
```
|
||||
|
||||
You'll be asked to confirm before ```apt``` starts downloading and installing the software.
|
||||
|
||||
- ```gcc```: is the [GNU](https://www.gnu.org/) C compiler - we'll be using that to build programs
|
||||
- ```make``` is a build tool that can be used to automate builds for projects.
|
||||
|
||||
## Editing a Text File
|
||||
|
||||
Using the Windows File Explorer, create a text file in your Linux home directory. Add some text to the file, use your favorite text editor.
|
||||
|
||||
From the Linux command window, change to your home directory by typing ```cd``` without any arguments. You'll know you're in your home directory when you see a tilde (~) symbol at your command prompt.
|
||||
|
||||
Now, display the contents of the file with the ```cat``` command on Linux. For example, from the command prompt try this:
|
||||
|
||||
```text
|
||||
user@machine:~$ ls
|
||||
text.txt
|
||||
user@machine:~$ cat text.txt
|
||||
this is some text
|
||||
```
|
||||
|
||||
The ```cat``` command is short for "concatenate". It will print out the contents of a file to the command prompt.
|
||||
|
||||
## Exploring Linux
|
||||
|
||||
Now that you have WSL and Ubuntu Linux set up and installed, you will explore your Linux environment. This exploration will involve experimenting with some other command. There are some interesting and powerful things you can accomplish with relative ease.
|
||||
|
||||
From your Linux command window and experiment with the commands below. You can get help on commands with the ```man``` command (which is short for "manual"). For example, try running ```man ls```.
|
||||
|
||||
You can search for appropriate commands with the ```apropos``` command. For example, try running ```apropos zip```.
|
||||
|
||||
Some commands you should experiment with (these are all typed via the command line, or terminal):
|
||||
|
||||
1. view a man page: man < command > e.g. man ls
|
||||
2. list a directory: ls
|
||||
3. list a directory, long: ls -l
|
||||
4. list a directory, long, all: ls -al
|
||||
5. search for a file in the file system: find -name .profile
|
||||
6. Search through a file or a through a program output: grep
|
||||
7. change directory: cd < dir >
|
||||
8. change directory up one level: cd ..
|
||||
9. change to last directory: cd –
|
||||
10. make directory: mkdir < dir >
|
||||
11. remove file: rm < file >
|
||||
12. remove directory: rmdir < dir >
|
||||
13. copy files: cp < source > < dest >
|
||||
14. display contents of a file: cat output.txt
|
||||
15. zip some files into a .zip file: zip lab1 hello.cpp output.txt
|
||||
16. Create a tarball: tar -cf new tar file.tar *
|
||||
17. Extract a tarball: tar -xvf new tar file.tar
|
||||
18. Create an empty file touch empty.txt
|
||||
|
||||
Some of these commands may not be installed yet, if you need to install them use ```apt``` as we did before. For example, to install ```zip``` you'd use: ```sudo apt-get install zip```.
|
||||
|
||||
As you are experimenting write a description (in your own words) of what each command (ls, find, cd, mkdir, rmdir, cp, cat, zip, tar, touch) is used for. Include the command description in your report (see "Deliverables" below).
|
||||
|
||||
## Creating a Development Environment
|
||||
|
||||
### Create a Development Directory
|
||||
|
||||
Next you will want to create a development directory to hold the projects you will complete. To do this, create a directory (folder) in your Linux home directory for this class. Feel free to do this from the Linux command line or the Window File Explorer.
|
||||
|
||||
### Setting up your Development Editor
|
||||
|
||||
**WINDOWS**:
|
||||
|
||||
For this class, it will be easiest to edit files from Windows and then build and execute them from your Linux command line. With that, feel free to use any Windows editor that you like. Here are a couple recommendations
|
||||
|
||||
- Notepad++ [https://notepad-plus-plus.org/](https://notepad-plus-plus.org/) is a simple text editor with text highlighting and has project file management as well
|
||||
- Eclipse is a Java based editor that has a C/C++ plugin. It can be installed by going to [https://www.eclipse.org/cdt/](https://www.eclipse.org/cdt/).
|
||||
- CLion - This is a C/C++ editor created by JetBrains and is similar in look and feel to IntelliJ.
|
||||
- You can download CLion from JetBrains web site: [https://www.jetbrains.com/clion/](https://www.jetbrains.com/clion/)
|
||||
- There is no community version, but you can get a free license if you register with JetBrains as a student: [https://www.jetbrains.com/community/education/#students](https://www.jetbrains.com/community/education/#students)
|
||||
- VSCode [https://code.visualstudio.com/](https://code.visualstudio.com/) is an IDE created by Microsoft with lots of configuration and plugin options.
|
||||
|
||||
Choose the editor that you like best. Feel free to experiment with multiple if you'd like.
|
||||
|
||||
**LINUX**:
|
||||
|
||||
While for this class, it will be easiest to edit files from Windows and then build and execute them from your Linux command line, if you want to experiment with editors on Linux there are many out there:
|
||||
|
||||
- Notepad++ doesn't exist for Linux there is a similar one called notepadqq which has similar features. It can be installed by running: ```sudo apt install notepadqq```
|
||||
- gedit is simple text editor with tabbed editing and code highlighting but isn't an integrated development environment. It can be installed by running: ```sudo apt install gedit```
|
||||
- Codelite has a similar interface to notepadqq and does have compiler integration. It can be installed by running: ```sudo apt install codelite```
|
||||
- vim is a non-graphical text editor that you might have used if you use Git Bash on Windows. It is installed by default on your WSL Ubuntu installation. More information on vim can be found here: [https://www.vim.org/](https://www.vim.org/)
|
||||
- Emacs is another non-graphical text editor. It can be installed by running: ```sudo apt install emacs```. More information on emacs can be found here: [https://www.gnu.org/software/emacs/](https://www.gnu.org/software/emacs/)
|
||||
|
||||
NOTE: If you wish to enter the long-running debate of 'emacs' vs 'vim' ([https://en.wikipedia.org/wiki/Editor_war](https://en.wikipedia.org/wiki/Editor_war) feel free to try out one (or both) of those editors.
|
||||
|
||||
## Building and Running a Program
|
||||
|
||||
Try compiling the following program (copy/paste to a file named hello.c or [download it](hello.c)):
|
||||
|
||||
```c
|
||||
/**********************************
|
||||
* hello.c
|
||||
* Written by: H. Welch - 11/26/2006
|
||||
* Modified W. Schilling - 8/15/2009
|
||||
*
|
||||
* Demonstrate basic C-program along with
|
||||
* system call requiring struct and pointer
|
||||
* manipulation.
|
||||
***********************************/
|
||||
#include <stdio.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <stdlib.h>
|
||||
int main (int argc, char* argv[]) {
|
||||
/* Get system information using the uts system interface.*/
|
||||
/* Declare a buffer to store information about the system. */
|
||||
struct utsname buf;
|
||||
/* Declare a pointer to the user information. */
|
||||
char *usr;
|
||||
/* Populate the buffer with data from the system. */
|
||||
uname(&buf);
|
||||
/* Get information about the user from the system. */
|
||||
usr=getenv("USER");
|
||||
/* Print out system information to the console. */
|
||||
printf("Hello %s:%s:%s:%s:z%s\n", buf.sysname, buf.nodename,
|
||||
buf.release,buf.version,buf.machine);
|
||||
printf("The size of the UTS structure is %lu.\n", sizeof(buf));
|
||||
/* Print out the user information if the pointer is not NULL. */
|
||||
if (usr != NULL) {
|
||||
printf("%s\n",usr);
|
||||
} else {
|
||||
printf("User information not returned by the operating system.");
|
||||
}
|
||||
/* Return to O/S */
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Now try compiling the program. Answer the questions as you go.
|
||||
|
||||
At the command shell, issue the command:
|
||||
|
||||
```text
|
||||
gcc -E hello.c | less
|
||||
```
|
||||
|
||||
This command will preprocess the source code and pipe the results to the console.
|
||||
|
||||
Questions:
|
||||
|
||||
1. What is the length of the ```sysname``` element of the ```utsname``` structure?
|
||||
2. How did you determine the sizes?
|
||||
|
||||
Now issue the commands:
|
||||
|
||||
```text
|
||||
gcc -S hello.cpp
|
||||
```
|
||||
|
||||
This will compile the given code, resulting in the creation of a ".s" file containing the assembly code for the program. You can view the contents of the file through ```less``` which is a command to display a text file in the terminal (command window) allowing you to move up and down using the arrow keys
|
||||
|
||||
```text
|
||||
less hello.s
|
||||
```
|
||||
|
||||
Create a "screenshot" image of the output from less (you don't have to include all the output, just one "page" is enough) and include this in your report.
|
||||
|
||||
Questions:
|
||||
|
||||
3. Notice the align command in the assembly output. This aligns the start of the definition on an 8-byte boundary. Why does the compiler add this?
|
||||
4. Do a Google search to find out more information on compiler memory alignment. Document your resources in your answer.
|
||||
5. Of the assembly code, which seems to be the most common instructions? Why do you think this is the case?
|
||||
6. Do a Google search for the most common instructions that you see in the .s file. What do they do? Make sure you document your resources in your answer.
|
||||
|
||||
Now issue the commands:
|
||||
```text
|
||||
gcc -c hello.c
|
||||
ls -al
|
||||
```
|
||||
The first command creates an object file for the hello.c source code. This is code which contains assembled instructions that can later be linked by the linker.
|
||||
|
||||
Questions:
|
||||
|
||||
7. What extension is given to this file?
|
||||
8. Research object files and give a short description in your own words. Make sure you document your resources in your answer.
|
||||
|
||||
Lastly, issue the command:
|
||||
```text
|
||||
gcc -o hello hello.c
|
||||
ls -al
|
||||
```
|
||||
This will perform all stages of compilation, writing the given file to the program hello. .
|
||||
|
||||
Questions:
|
||||
|
||||
9. Viewing the output from ls what is the difference in size between the object file (.o) and the complete executable?
|
||||
10. Do some research on Linux executables to see if you can figure out why there is a difference in size. Write a short description in your report. Make sure you document your resources in your answer.
|
||||
|
||||
Now issue the command:
|
||||
```text
|
||||
./hello
|
||||
```
|
||||
This will run the program. Follow the instructions in the program and create a screenshot of your output to include in your report.
|
||||
|
||||
## Deliverables
|
||||
|
||||
Once you've completed all the activities and have answers to all the questions, create a report (text, doc, or pdf file) including the following:
|
||||
|
||||
- Your name, date, and title
|
||||
- Introduction – a description the assignment in your own words
|
||||
- Resources – a description of any external resources you used to complete the assignment
|
||||
- Analysis – a description of your experience working with Linux
|
||||
- A reflection on your experience working with command line tools in Linux and the descriptions of the commands you used in your own words.
|
||||
- Include all required screenshots.
|
||||
- Answers to the questions from the "Building and Running a Program" section.
|
||||
- Conclusion
|
||||
- Summary of what you learned
|
||||
- What specifically was challenging?
|
||||
- What did you like about it?
|
||||
- What could we do to improve it for others?
|
||||
|
||||
Submit your report to per your instructor's instructions.
|
||||
|
||||
## Grading Criteria (100 Points)
|
||||
|
||||
- (20 Points) Report introduction- Thorough description of the assignment in your own words.
|
||||
- (60 Points) Analysis - Answers to the analysis questions
|
||||
- (20 Points) Report Conclusion - Thorough conclusion with description of what you learned, what you liked, and suggestions for improvements.
|
||||
35
00-WSLSetup/hello.c
Normal file
35
00-WSLSetup/hello.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/**********************************
|
||||
* hello.c
|
||||
* Written by: H. Welch - 11/26/2006
|
||||
* Modified W. Schilling - 8/15/2009
|
||||
*
|
||||
* Demonstrate basic C-program along with
|
||||
* system call requiring struct and pointer
|
||||
* manipulation.
|
||||
***********************************/
|
||||
#include <stdio.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <stdlib.h>
|
||||
int main (int argc, char* argv[]) {
|
||||
/* Get system information using the uts system interface.*/
|
||||
/* Declare a buffer to store information about the system. */
|
||||
struct utsname buf;
|
||||
/* Declare a pointer to the user information. */
|
||||
char *usr;
|
||||
/* Populate the buffer with data from the system. */
|
||||
uname(&buf);
|
||||
/* Get information about the user from the system. */
|
||||
usr=getenv("USER");
|
||||
/* Print out system information to the console. */
|
||||
printf("Hello %s:%s:%s:%s:z%s\n", buf.sysname, buf.nodename,
|
||||
buf.release,buf.version,buf.machine);
|
||||
printf("The size of the UTS structure is %lu.\n", sizeof(buf));
|
||||
/* Print out the user information if the pointer is not NULL. */
|
||||
if (usr != NULL) {
|
||||
printf("%s\n",usr);
|
||||
} else {
|
||||
printf("User information not returned by the operating system.");
|
||||
}
|
||||
/* Return to O/S */
|
||||
return 0;
|
||||
}
|
||||
BIN
01-StackMachine/.DS_Store
vendored
Normal file
BIN
01-StackMachine/.DS_Store
vendored
Normal file
Binary file not shown.
13
01-StackMachine/Makefile
Normal file
13
01-StackMachine/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g
|
||||
|
||||
all: smTester
|
||||
|
||||
smTester: stackm.o smTester.o
|
||||
$(CC) -o smTester $^
|
||||
|
||||
%: %.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f smTester *.o
|
||||
253
01-StackMachine/StackMachine.md
Normal file
253
01-StackMachine/StackMachine.md
Normal file
@@ -0,0 +1,253 @@
|
||||
## Introduction
|
||||
|
||||
The purpose of this lab is to design, code, and test a machine within the confines of the C programming language. The machine will consist of a data structure for storing data and operations that can be done against the data structure to perform calculations. While not strictly and "operating systems" exercise, it is intended to familiarize you with the development process on Linux and provide additional practice with dynamic memory.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Your VM should be operational, and you should have a development environment (programmer's editor or IDE) setup and tested (i.e. you have written a hello world program). This assignment will also make use of the program 'valgrind' which may need to be installed. You can do this at the command line with the commands:
|
||||
|
||||
```text
|
||||
sudo apt update
|
||||
sudo apt install valgrind
|
||||
```
|
||||
|
||||
## Background
|
||||
|
||||
A stack machine is a type of computer architecture in which values are stored on a stack rather than in general purpose registers. Values can be pushed from memory onto the stack and/or popped from the stack and stored into memory. Numerical operations are performed on items currently on the stack. For example, to execute an 'add' operation, the two operands are first pushed onto the stack. Then the 'add' instruction is executed which pops the values off the stack, adds them, and the result is pushed back on top of the stack.
|
||||
|
||||
While it might seem that using general purpose registers makes for a more flexible processor architecture, there are advantages of the simplicity of a stack machine. For example, there is no need for hardware to decode and access the register file, all operations are performed against the top of the stack. In fact, the Java Virtual Machine (JVM) is implemented in part as a stack machine.
|
||||
|
||||
## The Exercise
|
||||
|
||||
For this exercise you will be creating a program that can perform operations using a stack machine. The machine has no memory so all values for computation are stored entirely on the stack. Typically, a stack machine interprets instructions through machine code that has been compiled for the architecture, however, our stack machine will use function calls to perform operations.
|
||||
|
||||
The stack is a first-in-last-out data structure. Items are pushed (inserted) onto the top of the stack and popped (removed) from the top of the stack. The first thing pushed into the stack is therefore the last thing that can be removed. Think of it like stacking blocks on top of each other. You can't move the bottom block without first removing all the blocks on top of it.
|
||||
|
||||
Beyond push and pop, our stack machine can perform mathematical operations add, subtract, and multiply as well as a special operation called rotate which rotates elements on the stack.
|
||||
The size (number of elements it can hold) of the stack is unbounded, so you must be able to dynamically allocate and free elements as needed.
|
||||
|
||||
## Development
|
||||
|
||||
Start by downloading the [starter files](stackm.zip) which include the header file with the stack machine definition along with all required stack functions. The starter code also contains a sample smTester.c file with some test cases and a Makefile.
|
||||
|
||||
A header file is supplied that represents the "public" interface that you must implement. Each function is documented within the head file. You are ***NOT*** allowed to change this header file in any way. You should supply ***ONE*** source file with the implementation for all functions (stackm.c).
|
||||
|
||||
Upon reviewing the header file, you may have some impressions. First, the stack is rather crude. The functions in this "public" interface only manage the stack's memory and organization. The user has full access to the internals. Of course, some of this is an artifact of the C language that does not include the protections provided by languages such as Java and C++. Also note that the user must pass a pointer to every stack management function. Again, a necessity due to the lack of object-oriented language features.
|
||||
|
||||
In addition to the stack machine implementation, supply a "driver" that will completely test your stack machine implementation. Here is an example test driver, however it is not all-inclusive.
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
|
||||
smPush(&mystack, 2);
|
||||
smPush(&mystack, 3);
|
||||
smPush(&mystack, 4);
|
||||
smPrint(&mystack);
|
||||
|
||||
smPop(&mystack);
|
||||
smPrint(&mystack);
|
||||
smAdd(&mystack);
|
||||
smPrint(&mystack);
|
||||
|
||||
int value = 0;
|
||||
smTop(&mystack, &value);
|
||||
printf("%d\n", value);
|
||||
|
||||
smPush(&mystack, 10);
|
||||
smPush(&mystack, 11);
|
||||
smPrint(&mystack);
|
||||
smMult(&mystack);
|
||||
smPrint(&mystack);
|
||||
|
||||
smPush(&mystack, 10);
|
||||
smPush(&mystack, 11);
|
||||
smPrint(&mystack);
|
||||
smRotate(&mystack, 5);
|
||||
smPrint(&mystack);
|
||||
|
||||
smClear(&mystack);
|
||||
smPrint(&mystack);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
You should have already picked an editor or IDE to use. Compiling at the command line is sometimes easier than using an IDE as IDEs sometimes hide error messages. Edit, compile, and run your program entirely from the Linux VM. Using Windows to edit the file and then transferring to Linux can cause formatting problems with the code and might introduce unexpected errors.
|
||||
|
||||
You can invoke the compiler at the command line directly:
|
||||
|
||||
```text
|
||||
gcc hello.c
|
||||
```
|
||||
|
||||
This command will build hello.c and product an executable name a.out in the same directory. Errors and warning will be reported to the console. You can run a.out by issuing the command:
|
||||
|
||||
```text
|
||||
./a.out
|
||||
```
|
||||
|
||||
Here, the '.' refers to the current directory.
|
||||
|
||||
We can get fancier. Instead of the default output name, we can specify the name of the executable:
|
||||
|
||||
```text
|
||||
gcc -o hello hello.c
|
||||
```
|
||||
|
||||
If we have more than one source file, just list them all:
|
||||
|
||||
```text
|
||||
gcc -o hello hello.c goodbye.c
|
||||
```
|
||||
|
||||
By default, gcc doesn't report all possible warnings. If you want more warnings (hint, you do), do this:
|
||||
|
||||
```text
|
||||
gcc -Wall -o hello hello.c goodbye.c
|
||||
```
|
||||
|
||||
Another option for compiling your program is to use a Makefile. Doing so is completely optional for this lab but can be very helpful for building your programs. Dr. Schilling has an excellent tutorial on Makefiles that you can watch here: [https://www.youtube.com/watch?v=gT2roSrSYfo&feature=youtu.be](https://www.youtube.com/watch?v=gT2roSrSYfo&feature=youtu.be)
|
||||
|
||||
Here is a skeleton Makefile that you can use to get you started.
|
||||
|
||||
```text
|
||||
CC=gcc
|
||||
CFLAGS=-c -Wall
|
||||
LDFLAGS=
|
||||
SOURCES=source1.c source2.c
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
EXECUTABLE=exename
|
||||
|
||||
all: $(SOURCES) $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJECTS) $(EXECUTABLE)
|
||||
```
|
||||
|
||||
## Testing and Debugging
|
||||
|
||||
As stated above, you must write a driver that completely tests your stack machine. So what is complete testing? How do you go about this? You will have to put some thought into this and use your experience to guide you. It would make sense that you will have to call every method at least once, probably many times under different conditions. Look for boundary cases. For example, be sure to test ```smPop()``` with an empty stack as well as a non-empty stack.
|
||||
|
||||
Given that we are using C and not Java, there are few protections we can build in to prevent misuse of the stack. For example, there is no perfect way to make sure ```smInit()``` is called before adding items to the stack.
|
||||
|
||||
So, you are calling all the methods, and your program crashes. What now? Well, you must track down where it is crashing. An IDE with debugging will be helpful, but you can also do this with gdb from the command.
|
||||
|
||||
NOTE: The gdb program requires additional debug symbols to be included in your program in order to correctly display information about variable names and function names in call stacks. To compile your program with additional debugging information, use the -g flag. For example:
|
||||
|
||||
```text
|
||||
gcc -g -Wall -o hello hello.c goodbye.c
|
||||
```
|
||||
|
||||
The following shows a sample session using gdb to debug a segmentation fault:
|
||||
|
||||
```text
|
||||
~/dev/labs/stack$ ./a.out
|
||||
Segmentation fault
|
||||
~/dev/labs/stack$ gdb ./a.out
|
||||
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
|
||||
|
||||
== chopped out copyright stuff ==
|
||||
|
||||
Reading symbols from ./a.out...done.
|
||||
(gdb) run
|
||||
Starting program: ~/dev/labs/stack/a.out
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0x0000555555554b3b in smPush (myStack=0x7fffffffe120, toStore=4) at stackm.c:123
|
||||
123 myStack->top->next = newNode;
|
||||
(gdb) bt
|
||||
#0 0x0000555555554b3b in smPush (myStack=0x7fffffffe120, toStore=4) at stackm.c:123
|
||||
#1 0x00005555555548a4 in main () at smTester.c:30
|
||||
(gdb)
|
||||
```
|
||||
|
||||
- Running the program directly with ```./a.out``` from the command line produces a Segmentation fault output. This is not particularly helpful.
|
||||
- Running ```gdb``` with the program as a command line argument runs the GNU debugger. Notice the ```(gdb)``` prompt.
|
||||
- Using the ```run``` command will execute the program in the debugger
|
||||
- When the program hits the Segmentation fault, using the backtrace (```bt```) command prints a trace similar to the stack trace received from a ```NullPointerException``` in Java outlining exactly where the problem happened.
|
||||
|
||||
Another, highly recommended, tool for you to use is valgrind. Valgrind will monitor the heap and report memory leaks. The program must run to completion for this to be useful. Sample output is below:
|
||||
|
||||
```text
|
||||
==10565== Memcheck, a memory error detector
|
||||
==10565== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
|
||||
==10565== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
|
||||
==10565== Command: ./a.out
|
||||
==10565==
|
||||
==10565==
|
||||
==10565== HEAP SUMMARY:
|
||||
==10565== in use at exit: 100 bytes in 10 blocks
|
||||
==10565== total heap usage: 10 allocs, 0 frees, 100 bytes allocated
|
||||
==10565==
|
||||
==10565== LEAK SUMMARY:
|
||||
==10565== definitely lost: 100 bytes in 10 blocks
|
||||
==10565== indirectly lost: 0 bytes in 0 blocks
|
||||
==10565== possibly lost: 0 bytes in 0 blocks
|
||||
==10565== still reachable: 0 bytes in 0 blocks
|
||||
==10565== suppressed: 0 bytes in 0 blocks
|
||||
==10565== Rerun with --leak-check=full to see details of leaked memory
|
||||
==10565==
|
||||
==10565== For lists of detected and suppressed errors, rerun with: -s
|
||||
==10565== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
|
||||
```
|
||||
|
||||
## Deliverables
|
||||
|
||||
You should have at least three source files in your project:
|
||||
|
||||
1. smTester.c – The test driver for your stack machine and should contain the 'main' function. Make sure your implemented test driver tests more than just the sample
|
||||
2. stackm.c – the implementation file for your stack machine operations
|
||||
3. stackm.h – the header file that defines the stack machine operations
|
||||
|
||||
A makefile is useful, but optional for this assignment. If you created a makefile, include it in your submission.
|
||||
|
||||
All files should be well documented with function comment blocks and inline comments that explain complicated code routines. While no explicit style guidelines are set for programming in this course, code should be documented and readable. Include your name, section, and lab name in a comment block at the top of each file, including the given header file.
|
||||
|
||||
NOTE: do ***NOT*** submit any IDE configuration files (.idea, project files, etc.). Only submit your source files and report.
|
||||
|
||||
Prepare a lab report and submit it along with your source code. The report should include the following:
|
||||
|
||||
- Your name, date, and lab title
|
||||
- Introduction – a description of the lab in your own words
|
||||
- Design and Testing Methodology – a description of your design decisions and the process you took to create your test driver
|
||||
- Resources – a description of any external resources you used to complete the lab
|
||||
- Build – instructions on how to build and run your program. Include the exact commands that are necessary
|
||||
- Analysis – Discuss the key concepts from the lab and answers to the following questions
|
||||
- All the stack machine functions need a "reference" to the stack structure, and according to this design, that stack reference is passed as a pointer. Why is this necessary? Do all the stack functions need this to be passed as a pointer? Any exceptions? Be specific in your answer.
|
||||
- Unlike a Java or C++ implementation, this implementation cannot "hide" any of the internal structure of the stack. That is, users of the stack could mess up the next pointers if they are careless. Can you think of any way we could hide the structure of the stack to lessen the chances a user will mess up the stack? Describe in brief detail.
|
||||
- What if all smClear() did was assign NULL to top in the stack structure and nothing else. Would the program crash? Would there be any side effects? Try it and report results.
|
||||
- Give an example of why it might be helpful to provide an iterator or random access to elements stored in the stack (rather than always accessing the top) and outline how you could implement such a feature.
|
||||
- Conclusion
|
||||
- Summary of what you learned in the lab
|
||||
- What specifically was challenging about this lab?
|
||||
- What did you like about it?
|
||||
- What could we do to improve it for others?
|
||||
|
||||
NOTE: You should ensure that this program compiles without warning (-Wall and -Wextra) prior to submitting.
|
||||
|
||||
Create a zip file containing your source files and your report and submit the zip file per your instructor's instructions.
|
||||
|
||||
## Grading Criteria (100 Points)
|
||||
|
||||
- (35 Points) Report
|
||||
- (5 Points) Report Introduction - Thorough description of the lab in your own words.
|
||||
- (5 Points) Design and Testing Methodology - Detailed description of design and method for testing your implementation.
|
||||
- (20 Points) Analysis - Answers to the analysis questions
|
||||
- (5 Points) Conclusion - Thorough conclusion with description of what you learned, what you liked, and suggestions for lab improvements.
|
||||
- (5 Points) Documented Resources - Description of external resources used to complete the lab
|
||||
- (5 Points) Correct Submission - Followed submission instructions (e.g. IDE project files are not submitted)
|
||||
- (5 Points) Build - Code compiles without warnings or errors
|
||||
- (10 Points) Test Cases - Thoroughness of submitted test driver
|
||||
- (35 Points) Instructor Tests - Implementation passes all instructor test cases
|
||||
- (5 Points) Memory Management - Program execution is free from memory leaks
|
||||
37
01-StackMachine/smTester.c
Normal file
37
01-StackMachine/smTester.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
|
||||
smPush(&mystack, 2);
|
||||
smPush(&mystack, 3);
|
||||
smPush(&mystack, 4);
|
||||
smPrint(&mystack);
|
||||
|
||||
smPop(&mystack);
|
||||
smPrint(&mystack);
|
||||
smAdd(&mystack);
|
||||
smPrint(&mystack);
|
||||
|
||||
int value = 0;
|
||||
smTop(&mystack, &value);
|
||||
printf("%d\n", value);
|
||||
|
||||
smPush(&mystack, 10);
|
||||
smPush(&mystack, 11);
|
||||
smPrint(&mystack);
|
||||
smMult(&mystack);
|
||||
smPrint(&mystack);
|
||||
|
||||
smPush(&mystack, 10);
|
||||
smPush(&mystack, 11);
|
||||
smPrint(&mystack);
|
||||
smRotate(&mystack, 5);
|
||||
smPrint(&mystack);
|
||||
|
||||
smClear(&mystack);
|
||||
smPrint(&mystack);
|
||||
return 0;
|
||||
}
|
||||
195
01-StackMachine/stackm.h
Normal file
195
01-StackMachine/stackm.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* stackm.h
|
||||
*
|
||||
* External (public) declarations for stack machine in C.
|
||||
*
|
||||
* This stack will know about the top. Each element must point
|
||||
* to the one below it in the stack.
|
||||
*
|
||||
* Note that the pop operations do not return a reference to the
|
||||
* popped node. This would require storage for the node to be
|
||||
* released by the user, which could lead to memory mishandling.
|
||||
* The stack size is unbounded so memory must be allocated and
|
||||
* freed as appropriate when operations are performed.
|
||||
*
|
||||
* This stack will only hold integers. Mathematical operations are
|
||||
* performed on elements on the top of the stack as described in the
|
||||
* function definitions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STACKM_H
|
||||
#define STACKM_H
|
||||
|
||||
/* Structures */
|
||||
|
||||
/* a stack node */
|
||||
typedef struct node {
|
||||
int value;
|
||||
struct node* next;
|
||||
} node;
|
||||
|
||||
/* The stack itself */
|
||||
typedef struct stackm {
|
||||
struct node *top;
|
||||
} stackm;
|
||||
|
||||
/* Stack Machine methods
|
||||
*
|
||||
* These methods are used to create and operate on the stack machine as a whole.
|
||||
*/
|
||||
|
||||
/* smInit()
|
||||
* Initialize a stack machine structure. An empty stack will
|
||||
* be characterized by top being NULL.
|
||||
* Parameters: myStack - a pointer to the structure to be init
|
||||
* Returns: void
|
||||
*/
|
||||
void smInit(struct stackm *myStack);
|
||||
|
||||
/* smSize()
|
||||
* Reports the current size of the stack. Will need to iterate
|
||||
* the stack to get this data size there is no size property, nor
|
||||
* can there really be one given that users can access nodes.
|
||||
* Parameters: myStack - the stack
|
||||
* Returns: int, size of stack
|
||||
*/
|
||||
int smSize(struct stackm *myStack);
|
||||
|
||||
/* smPush()
|
||||
* Add a new node with provided data to the top of the stack.
|
||||
* This method should allocate memory as needed and check to
|
||||
* make sure that the memory was allocated successfully.
|
||||
* Parameters: myStack - the stack
|
||||
* toStore - the value to store
|
||||
* Returns: int - 0 if no push could be performed
|
||||
* (failed to allocate memory) or non-zero
|
||||
* if push was successful
|
||||
*/
|
||||
int smPush(struct stackm *myStack, int toStore);
|
||||
|
||||
/* smPop()
|
||||
* Removes top item in stack. Note, this does not return
|
||||
* any data from the stack. If the data in the node is needed
|
||||
* it should be accessed prior to the pop (smTop).
|
||||
* Parameters: myStack - the stack
|
||||
* Returns: int - 0 if no pop (stack was empty) or non-zero
|
||||
* if pop successful
|
||||
*/
|
||||
int smPop(struct stackm *myStack);
|
||||
|
||||
/* smTop()
|
||||
* return the value at the top of the stack. NOTE: the value
|
||||
* must be returned by dereferencing the passed in pointer.
|
||||
* The function must make sure the pointer is not NULL prior to
|
||||
* dereferencing to avoid memory violations.
|
||||
* Parameters: myStack - the stack
|
||||
* toStore - a point to store the stack top value
|
||||
* Returns: int - 0 if top could not be retrieved
|
||||
* (toStore was NULL or stack is empty) or
|
||||
* non-zero retrieval was successful
|
||||
*/
|
||||
int smTop(struct stackm *myStack, int* toStore);
|
||||
|
||||
/* smClear()
|
||||
* Clears all nodes and releases all dynamic memory. Stack
|
||||
* structure should be NULLed and can be reused.
|
||||
* Parameters: myStack - the stack
|
||||
* Returns: nothing
|
||||
*/
|
||||
void smClear(struct stackm *myStack);
|
||||
|
||||
/* smPrint()
|
||||
* Prints the contents of the stack machine to standard output.
|
||||
* When printing it should be clear what value contains the top
|
||||
* as well which which values are stacked on top of other values
|
||||
* Parameters: myStack - the stack
|
||||
* Returns: nothing
|
||||
*/
|
||||
void smPrint(struct stackm *myStack);
|
||||
|
||||
/* Stack Machine manipulation methods
|
||||
*
|
||||
* These methods perform operations that manipulate the stack
|
||||
* (math or element ordering).
|
||||
*/
|
||||
|
||||
/* smAdd()
|
||||
* Add together the top two elements of the stack and push
|
||||
* the result.
|
||||
* The stack must contain at least 2 elements for this
|
||||
* operation to be successful.
|
||||
* Any removed element must be freed (no memory leaks)
|
||||
* Parameters: myStack - the stack
|
||||
* Returns: int - 0 if operation could not be performed
|
||||
* (not enough elements on the stack)
|
||||
* non-zero if successful
|
||||
*/
|
||||
int smAdd(struct stackm* myStack);
|
||||
|
||||
/* smSub()
|
||||
* Subtract the top two elements of the stack and push
|
||||
* the result.
|
||||
* The stack must contain at least 2 elements for this
|
||||
* operation to be successful.
|
||||
* Operation is TOS (top of stack) - 2nd from TOS
|
||||
* if the stack contained the values:
|
||||
* top -> 6
|
||||
* 5
|
||||
* 4
|
||||
* bottom -> 3
|
||||
* The result after a smSub operation would be:
|
||||
* top -> 1
|
||||
* 4
|
||||
* bottom -> 3
|
||||
* 6 - 5 = 1
|
||||
* Any removed element must be freed (no memory leaks)
|
||||
* Parameters: myStack - the stack
|
||||
* Returns: int - 0 if operation could not be performed
|
||||
* (not enough elements on the stack)
|
||||
* non-zero if successful
|
||||
*/
|
||||
int smSub(struct stackm* myStack);
|
||||
|
||||
/* smMult()
|
||||
* Multiply the top two elements of the stack and push
|
||||
* the result.
|
||||
* The stack must contain at least 2 elements for this
|
||||
* operation to be successful.
|
||||
* Any removed element must be freed (no memory leaks)
|
||||
* Parameters: myStack - the stack
|
||||
* Returns: int - 0 if operation could not be performed
|
||||
* (not enough elements on the stack)
|
||||
* non-zero if successful
|
||||
*/
|
||||
int smMult(struct stackm* myStack);
|
||||
|
||||
/* smRotate()
|
||||
* Rotate the top 'n' elements of the stack. For example,
|
||||
* if the stack contained the values:
|
||||
* top -> 6
|
||||
* 5
|
||||
* 4
|
||||
* bottom -> 3
|
||||
* The result after a rotate 3 operation would be:
|
||||
* top -> 5
|
||||
* 4
|
||||
* 6
|
||||
* bottom -> 3
|
||||
* NOTE: the top element on the stack goes to the 'nth'
|
||||
* location and every element above the 'nth' location
|
||||
* gets moved up one
|
||||
* The stack must contain at least 'n' elements for this
|
||||
* operation to be successful.
|
||||
* 'n' must be greater than or equal to 1. A value of 1
|
||||
* does nothing, but is still successfull.
|
||||
* Any removed element must be freed (no memory leaks)
|
||||
* Parameters: myStack - the stack
|
||||
* depth - the depth of the rotation
|
||||
* Returns: int - 0 if operation could not be performed
|
||||
* (not enough elements on the stack
|
||||
* or depth is too small)
|
||||
* non-zero if successful
|
||||
*/
|
||||
int smRotate(struct stackm* myStack, int depth);
|
||||
|
||||
#endif
|
||||
8
01-StackMachine/testcases/tc1.c
Normal file
8
01-StackMachine/testcases/tc1.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
return 0;
|
||||
}
|
||||
30
01-StackMachine/testcases/tc10.c
Normal file
30
01-StackMachine/testcases/tc10.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
smPrint(&mystack);
|
||||
doPush(&mystack, 2);
|
||||
smPrint(&mystack);
|
||||
doPush(&mystack, 3);
|
||||
smPrint(&mystack);
|
||||
doPop(&mystack);
|
||||
smPrint(&mystack);
|
||||
doPop(&mystack);
|
||||
smPrint(&mystack);
|
||||
doPop(&mystack);
|
||||
smPrint(&mystack);
|
||||
return 0;
|
||||
}
|
||||
27
01-StackMachine/testcases/tc11.c
Normal file
27
01-StackMachine/testcases/tc11.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doAdd(stackm* s)
|
||||
{
|
||||
printf("Add Ret: %d\n", smAdd(s));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doPush(&mystack, 2);
|
||||
doAdd(&mystack);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
39
01-StackMachine/testcases/tc12.c
Normal file
39
01-StackMachine/testcases/tc12.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doAdd(stackm* s)
|
||||
{
|
||||
printf("Add Ret: %d\n", smAdd(s));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
void doTop(stackm* s, int* v)
|
||||
{
|
||||
printf("Top Ret: %d\n", smTop(s, v));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int val = 0;
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
for(int i = 0 ; i < 10; i++) {
|
||||
doPush(&mystack, i);
|
||||
}
|
||||
for(int i = 0; i < 9; i++) {
|
||||
doAdd(&mystack);
|
||||
}
|
||||
doTop(&mystack, &val);
|
||||
printf("Final Val: %d\n", val);
|
||||
doPop(&mystack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
27
01-StackMachine/testcases/tc13.c
Normal file
27
01-StackMachine/testcases/tc13.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doSub(stackm* s)
|
||||
{
|
||||
printf("Sub Ret: %d\n", smSub(s));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doPush(&mystack, 2);
|
||||
doSub(&mystack);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
39
01-StackMachine/testcases/tc14.c
Normal file
39
01-StackMachine/testcases/tc14.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doSub(stackm* s)
|
||||
{
|
||||
printf("Sub Ret: %d\n", smSub(s));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
void doTop(stackm* s, int* v)
|
||||
{
|
||||
printf("Top Ret: %d\n", smTop(s, v));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int val = 0;
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
for(int i = 0 ; i < 10; i++) {
|
||||
doPush(&mystack, i);
|
||||
}
|
||||
for(int i = 0; i < 9; i++) {
|
||||
doSub(&mystack);
|
||||
}
|
||||
doTop(&mystack, &val);
|
||||
printf("Final Val: %d\n", val);
|
||||
doPop(&mystack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
27
01-StackMachine/testcases/tc15.c
Normal file
27
01-StackMachine/testcases/tc15.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doMult(stackm* s)
|
||||
{
|
||||
printf("Mult Ret: %d\n", smMult(s));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doPush(&mystack, 2);
|
||||
doMult(&mystack);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
39
01-StackMachine/testcases/tc16.c
Normal file
39
01-StackMachine/testcases/tc16.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doMult(stackm* s)
|
||||
{
|
||||
printf("Mult Ret: %d\n", smMult(s));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
void doTop(stackm* s, int* v)
|
||||
{
|
||||
printf("Top Ret: %d\n", smTop(s, v));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int val = 0;
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
for(int i = 1 ; i < 11; i++) {
|
||||
doPush(&mystack, i);
|
||||
}
|
||||
for(int i = 0; i < 9; i++) {
|
||||
doMult(&mystack);
|
||||
}
|
||||
doTop(&mystack, &val);
|
||||
printf("Final Val: %d\n", val);
|
||||
doPop(&mystack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
21
01-StackMachine/testcases/tc17.c
Normal file
21
01-StackMachine/testcases/tc17.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doAdd(stackm* s)
|
||||
{
|
||||
printf("Add Ret: %d\n", smAdd(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doAdd(&mystack);
|
||||
doPush(&mystack, 10);
|
||||
doAdd(&mystack);
|
||||
return 0;
|
||||
}
|
||||
21
01-StackMachine/testcases/tc18.c
Normal file
21
01-StackMachine/testcases/tc18.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doSub(stackm* s)
|
||||
{
|
||||
printf("Sub Ret: %d\n", smSub(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doSub(&mystack);
|
||||
doPush(&mystack, 10);
|
||||
doSub(&mystack);
|
||||
return 0;
|
||||
}
|
||||
26
01-StackMachine/testcases/tc19.c
Normal file
26
01-StackMachine/testcases/tc19.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doMult(stackm* s)
|
||||
{
|
||||
printf("Mult Ret: %d\n", smMult(s));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doMult(&mystack);
|
||||
doPush(&mystack, 10);
|
||||
doMult(&mystack);
|
||||
return 0;
|
||||
}
|
||||
20
01-StackMachine/testcases/tc2.c
Normal file
20
01-StackMachine/testcases/tc2.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
30
01-StackMachine/testcases/tc20.c
Normal file
30
01-StackMachine/testcases/tc20.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
void doRotate(stackm *s, int d)
|
||||
{
|
||||
printf("Rotate Ret: %d\n", smRotate(s, d));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doPush(&mystack, 2);
|
||||
smPrint(&mystack);
|
||||
doRotate(&mystack, 2);
|
||||
smPrint(&mystack);
|
||||
doPop(&mystack);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
34
01-StackMachine/testcases/tc21.c
Normal file
34
01-StackMachine/testcases/tc21.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
void doRotate(stackm *s, int d)
|
||||
{
|
||||
printf("Rotate Ret: %d\n", smRotate(s, d));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
for(int i = 0 ; i < 10; i++) {
|
||||
doPush(&mystack, i);
|
||||
}
|
||||
smPrint(&mystack);
|
||||
for(int i = 0; i < 10; i++) {
|
||||
doRotate(&mystack, i+1);
|
||||
smPrint(&mystack);
|
||||
}
|
||||
for(int i = 0; i < 10; i++) {
|
||||
doPop(&mystack);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
31
01-StackMachine/testcases/tc22.c
Normal file
31
01-StackMachine/testcases/tc22.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
void doRotate(stackm *s, int d)
|
||||
{
|
||||
printf("Rotate Ret: %d\n", smRotate(s, d));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
for(int i = 0 ; i < 10; i++) {
|
||||
doPush(&mystack, i);
|
||||
}
|
||||
smPrint(&mystack);
|
||||
doRotate(&mystack, 100);
|
||||
for(int i = 0; i < 10; i++) {
|
||||
doPop(&mystack);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
31
01-StackMachine/testcases/tc23.c
Normal file
31
01-StackMachine/testcases/tc23.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
void doRotate(stackm *s, int d)
|
||||
{
|
||||
printf("Rotate Ret: %d\n", smRotate(s, d));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
for(int i = 0 ; i < 10; i++) {
|
||||
doPush(&mystack, i);
|
||||
}
|
||||
smPrint(&mystack);
|
||||
doRotate(&mystack, 0);
|
||||
for(int i = 0; i < 10; i++) {
|
||||
doPop(&mystack);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
42
01-StackMachine/testcases/tc24.c
Normal file
42
01-StackMachine/testcases/tc24.c
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doMult(stackm* s)
|
||||
{
|
||||
printf("Mult Ret: %d\n", smMult(s));
|
||||
}
|
||||
|
||||
void doRotate(stackm *s, int d)
|
||||
{
|
||||
printf("Rotate Ret: %d\n", smRotate(s, d));
|
||||
}
|
||||
|
||||
void doTop(stackm* s, int* v)
|
||||
{
|
||||
printf("Top Ret: %d\n", smTop(s, v));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int val = 0;
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
for(int i = 1 ; i <= 10; i++) {
|
||||
doPush(&mystack, i);
|
||||
doPush(&mystack, i);
|
||||
doMult(&mystack);
|
||||
}
|
||||
smPrint(&mystack);
|
||||
doTop(&mystack, &val);
|
||||
while(val > 25) {
|
||||
doRotate(&mystack, 10);
|
||||
doTop(&mystack, &val);
|
||||
}
|
||||
smPrint(&mystack);
|
||||
smClear(&mystack);
|
||||
return 0;
|
||||
}
|
||||
16
01-StackMachine/testcases/tc25.c
Normal file
16
01-StackMachine/testcases/tc25.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
for(int i = 0 ; i < 1000; i++) {
|
||||
smPush(&mystack, i);
|
||||
}
|
||||
smPrint(&mystack);
|
||||
for(int i = 0 ; i < 1000; i++) {
|
||||
smPop(&mystack);
|
||||
}
|
||||
smPrint(&mystack);
|
||||
return 0;
|
||||
}
|
||||
24
01-StackMachine/testcases/tc3.c
Normal file
24
01-StackMachine/testcases/tc3.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doPush(&mystack, 2);
|
||||
doPush(&mystack, 3);
|
||||
doPop(&mystack);
|
||||
doPop(&mystack);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
14
01-StackMachine/testcases/tc4.c
Normal file
14
01-StackMachine/testcases/tc4.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
9
01-StackMachine/testcases/tc5.c
Normal file
9
01-StackMachine/testcases/tc5.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
printf("SIZE: %d\n", smSize(&mystack));
|
||||
return 0;
|
||||
}
|
||||
25
01-StackMachine/testcases/tc6.c
Normal file
25
01-StackMachine/testcases/tc6.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doPush(&mystack, 2);
|
||||
doPush(&mystack, 3);
|
||||
printf("SIZE: %d\n", smSize(&mystack));
|
||||
doPop(&mystack);
|
||||
doPop(&mystack);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
36
01-StackMachine/testcases/tc7.c
Normal file
36
01-StackMachine/testcases/tc7.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
void doPop(stackm* s)
|
||||
{
|
||||
printf("Pop Ret: %d\n", smPop(s));
|
||||
}
|
||||
|
||||
void doTop(stackm* s, int* v)
|
||||
{
|
||||
printf("Top Ret: %d\n", smTop(s, v));
|
||||
}
|
||||
|
||||
int main() {
|
||||
int val = 0;
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doTop(&mystack, &val);
|
||||
printf("TOP: %d\n", val);
|
||||
doPush(&mystack, 2);
|
||||
doTop(&mystack, &val);
|
||||
printf("TOP: %d\n", val);
|
||||
doPush(&mystack, 3);
|
||||
doTop(&mystack, &val);
|
||||
printf("TOP: %d\n", val);
|
||||
doPop(&mystack);
|
||||
doPop(&mystack);
|
||||
doPop(&mystack);
|
||||
return 0;
|
||||
}
|
||||
9
01-StackMachine/testcases/tc8.c
Normal file
9
01-StackMachine/testcases/tc8.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
smClear(&mystack);
|
||||
return 0;
|
||||
}
|
||||
19
01-StackMachine/testcases/tc9.c
Normal file
19
01-StackMachine/testcases/tc9.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <stdio.h>
|
||||
#include "stackm.h"
|
||||
|
||||
void doPush(stackm* s, int v)
|
||||
{
|
||||
printf("Push Ret: %d\n", smPush(s, v));
|
||||
}
|
||||
|
||||
int main() {
|
||||
stackm mystack;
|
||||
smInit(&mystack);
|
||||
doPush(&mystack, 1);
|
||||
doPush(&mystack, 2);
|
||||
doPush(&mystack, 3);
|
||||
printf("SIZE: %d\n", smSize(&mystack));
|
||||
smClear(&mystack);
|
||||
printf("SIZE: %d\n", smSize(&mystack));
|
||||
return 0;
|
||||
}
|
||||
BIN
02-TeenyTinyShell/.DS_Store
vendored
Normal file
BIN
02-TeenyTinyShell/.DS_Store
vendored
Normal file
Binary file not shown.
17
02-TeenyTinyShell/Makefile
Normal file
17
02-TeenyTinyShell/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -Wextra -c -g
|
||||
LDFLAGS=
|
||||
SOURCES=ttsh.c
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
EXECUTABLE=ttsh
|
||||
|
||||
all: $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(OBJECTS)
|
||||
$(CC) -o $(EXECUTABLE) $(LDFLAGS) $^
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(EXECUTABLE) $(OBJECTS)
|
||||
203
02-TeenyTinyShell/TeenyTinyShell.md
Normal file
203
02-TeenyTinyShell/TeenyTinyShell.md
Normal file
@@ -0,0 +1,203 @@
|
||||
## Introduction
|
||||
|
||||
A shell is a program that provides a traditional text-based interface to an operating system. In Linux, a user types commands into the shell to be executed similar to the command prompt (cmd.exe) on Windows. The purpose of this lab is to design, code, and test a program that will create a command prompt allowing user to execute commands. It is intended to familiarize yourself with the system calls needed to create processes on Linux.
|
||||
|
||||
## References
|
||||
|
||||
There are many shells available for Linux, arguably the most popular is 'bash' which stands for the Bourne-Again SHell. The shell you will be developing for this lab will work similarly to 'bash' but will have fewer features. For more information about the 'bash' shell, you can check out the Wikipedia page: [https://en.wikipedia.org/wiki/Bash_(Unix_shell)](https://en.wikipedia.org/wiki/Bash_(Unix_shell))
|
||||
|
||||
For this lab, you will be using the ```fork()``` system call to create child processes, then running ```exec()``` to run the commands specified by the user, finally waiting for the commands to finish executing using the wait() system call. Before you start, it might be helpful to read the 'man' pages for these system calls.
|
||||
|
||||
- man 2 fork
|
||||
- man 2 exec
|
||||
- man 2 wait
|
||||
|
||||
## The Exercise
|
||||
|
||||
The steps for a typical shell are as follows:
|
||||
|
||||
1. Print out a prompt to the user – this may include the user's login name followed by their current working directory. Shells typically allow the user to configure this through a settings file. Our shell will use the same prompt every time.
|
||||
2. Read the command string from the user
|
||||
3. Invoke the ```fork()``` system call to create a child process to run the command
|
||||
4. Invoke the ```exec()``` system call in the child process to replace its address space with the command to run
|
||||
5. Invoke the ```wait()``` system call in the parent process to wait for the child process (running the command) to finish executing
|
||||
6. Go back to 1
|
||||
|
||||
Shells typically run in a loop executing commands and then waiting for more work to do. For this lab you will be developing a shell called Teeny Tiny Shell (ttsh), that will do the same.
|
||||
|
||||
Commands on Linux are pre-compiled programs that exist within the directory structure. For example, the 'ls' command that you used in previous labs is located at /usr/bin/ls. The Linux directory structure begins at the root directory. Each directory name is delimited by the slash (/) character. The 'ls' command can be executed by the shell using the absolute path (e.g. /usr/bin/ls), however this isn't required because Linux has a set of paths pre-set that it uses to search for commands. The directory /usr/bin is one of those paths. When a user just types 'ls' for the command to run, Linux searches the set of paths to find where 'ls' is located. If it finds it, it runs the command. If it can't find it, the shell prints out 'command not found'. Your shell will have to be able to handle this just like 'bash' does. Thankfully the search paths are built into the ```exec()``` system call for you.
|
||||
|
||||
NOTE: if at any time you want to find where a command is located, you can use the 'which' command.
|
||||
|
||||
In addition to the commands themselves, the execution of a command also may involve one or more command line arguments. For example, you can run 'ls' to get the directory listing, but you can run 'ls -l' to have the 'ls' command print out a long, more detailed directory listing. Command line arguments are separated by spaces in the user input. Most shells support an unlimited number of command line arguments; however, your shell is only required to support up to 10 command line arguments.
|
||||
|
||||
Teeny Tiny Shell supports an additional feature using the semicolon. Commands separated by a semicolon are run sequentially after each other. For example:
|
||||
|
||||
```text
|
||||
echo hi ; ls -a ; echo bye
|
||||
```
|
||||
|
||||
will run the 3 commands:
|
||||
|
||||
1. 'echo hi' will print 'hi' to the terminal
|
||||
2. 'ls -a' will print all files in the current directory
|
||||
3. 'echo bye' will print 'bye' to the terminal
|
||||
|
||||
Commands will be executed sequentially: the first command will run to completion (the other two will not run), then the second command will run to completion, finally the third command will run.
|
||||
|
||||
While the user might not specify any command line arguments (e.g. if they just execute 'ls' to get the directory listing), any call to exec requires at least one command line argument. The first argument is ALWAYS the command that is being executed. For example, if the user types the following command:
|
||||
|
||||
```text
|
||||
$> ls -l
|
||||
```
|
||||
|
||||
This is translated to an execution of the 'ls' command with command line arguments: 'ls' and '-l'
|
||||
|
||||
## Development Requirements
|
||||
|
||||
1. While most shells allow the user to customize the prompt, you shell will always use the following prompt string:
|
||||
|
||||
```text
|
||||
$>
|
||||
```
|
||||
|
||||
A dollar sign ($), followed by a greater than (>), followed by a space ( )
|
||||
3. Your 'ttsh' must support up to 10 command line arguments for each command (separated by spaces)
|
||||
4. Your 'ttsh' must support up to 5 commands run sequentially (separated by semicolon)
|
||||
5. While there many 'flavors' of the exec() system call, for this lab you are required to use execvp(). See the man page for the specifics of how execvp() works.
|
||||
6. Your shell must support a single internal command called 'quit' which stops the execution loop
|
||||
7. You must use fork() and execvp() to create child processes and execute commands. The use of the system() function is not allowed for this lab.
|
||||
8. Your 'ttsh' must be free of memory leaks and segmentation faults.
|
||||
9. Your 'ttsh' only needs to support a max user input of 256 characters.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Parsing the user's input can be kind of complicated. Using the string tokenizer function (strtok) can be helpful. For help on how to use strtok see the man page:
|
||||
|
||||
- man strtok
|
||||
|
||||
Start by downloading the [starter files](ttsh.zip) which includes a source file (ttsh.c) with some code to help you parse the command line. The starter code also contains a Makefile to help you build your shell.
|
||||
|
||||
## Sample Execution
|
||||
|
||||
Here is a sample output for an execution of 'ttsh'. Note the first line and last line shows the prompt presented from 'bash' prior to running 'ttsh'.
|
||||
|
||||
```text
|
||||
user@pc:~/Desktop/cs3840/labs$ ./ttsh
|
||||
$> ls
|
||||
ttsh ttsh.c
|
||||
$> ls -l
|
||||
total 500
|
||||
-rwxrwxr-x 1 user user 17240 Sep 17 12:59 ttsh
|
||||
-rw-rw-r-- 1 user user 7053 Sep 17 12:47 ttsh.c
|
||||
$> echo hello world
|
||||
hello world
|
||||
$> ps -f -l
|
||||
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
|
||||
0 S user 43181 43170 0 80 0 - 5173 do_wai 08:59 pts/0 00:00:00 bash
|
||||
0 R user 46683 43181 0 80 0 - 5029 - 11:59 pts/0 00:00:00 ps -f -l
|
||||
$> which ls
|
||||
/usr/bin/ls
|
||||
$> mkdir testdir
|
||||
$> ls -l
|
||||
total 504
|
||||
-rwxrwxr-x 1 user user 17240 Sep 17 12:59 ttsh
|
||||
-rw-rw-r-- 1 user user 7053 Sep 17 12:47 ttsh.c
|
||||
drwxrwxr-x 2 user user 4096 Sep 18 12:02 testdir
|
||||
$> rmdir testdir
|
||||
$> ls -l
|
||||
total 500
|
||||
-rwxrwxr-x 1 user user 17240 Sep 17 12:59 ttsh
|
||||
-rw-rw-r-- 1 user user 7053 Sep 17 12:47 ttsh.c
|
||||
$> asdfasdfasdfasdf
|
||||
asdfasdfasdfasdf: failed to execute command
|
||||
$> quit
|
||||
user@pc:~/Desktop/cs3840/labs$
|
||||
```
|
||||
|
||||
## Development Tips
|
||||
|
||||
Consider breaking the lab up into pieces:
|
||||
|
||||
1. Create your shell input/execute loop
|
||||
2. Implement the 'quit' command
|
||||
3. Read and parse user input for commands
|
||||
1. Break apart commands by semicolon
|
||||
2. Break apart command line arguments by spaces
|
||||
4. Get fork() and execvp() working to create a child process
|
||||
1. Build the array of command line arguments
|
||||
1. A single command with no command line arguments (remember that even without command line arguments explicitly specified there is always 1 passed to the new process)
|
||||
2. A single command with multiple command line arguments (remember that this includes the command name AND the actual command line arguments)
|
||||
3. Make sure you end your array of command line arguments with a NULL pointer
|
||||
2. Run multiple commands in sequence with or without command line arguments
|
||||
5. Handle command not found
|
||||
|
||||
Additional tips:
|
||||
|
||||
- Your shell has limitations on string length requirements. Use this to your advantage
|
||||
- A max of 256 characters of user input
|
||||
- A max of 10 command line arguments (this max includes the first argument for the command name itself, effectively making the number that the user can specify to be 9 arguments)
|
||||
- A max of 5 commands executed in sequence
|
||||
- Don't forget about using gdb to help with debugging (compile with -g to get additional debug symbols)
|
||||
|
||||
NOTE: when using gdb it is helpful to compile your program with additional debug symbols included. These allow gdb to show you more information when running commands like backtrace (bt). To compile with additional debug symbols use the -g flag on gcc. For example:
|
||||
|
||||
```text
|
||||
gcc -Wall -g -o myprog mysourcefile1.c mysourcefile2.c mysourcefile3.c
|
||||
```
|
||||
|
||||
- Using valgrind will be helpful in this lab to ensure you do not have any memory leaks.
|
||||
|
||||
## Testing and Debugging
|
||||
|
||||
Make sure your shell supports all the features listed in the "Development Requirements". Make sure you test boundary cases and print appropriate error messages to the user as needed. For example, if the user attempts to execute a command with more than 10 command line arguments, print an error message to the user and wait for a new command (without executing the command).
|
||||
|
||||
## Deliverables
|
||||
|
||||
You will need to include all your source files and any other resources you used to complete lab. Please don't just google search for a solution, but if you do use Google for any help, include a description and URL of what you used to help you.
|
||||
|
||||
A makefile is useful, but optional for this assignment. If you created a makefile, include it in your submission.
|
||||
|
||||
All files should be well documented with function comment blocks and inline comments that explain complicated code routines. While no explicit style guidelines are set for programming in this course, code should be documented and readable. Include your name, section, and lab name in a comment block at the top of each file.
|
||||
|
||||
NOTE: do ***NOT*** submit any IDE configuration files (.idea, project files, etc.). Only submit your source files and report.
|
||||
|
||||
Prepare a lab report and submit it along with your source code. The report should include the following:
|
||||
|
||||
- Your name, section, date, and lab title
|
||||
- Introduction – a description the lab in your own words
|
||||
- Design – a description of your design decisions in creating your solution
|
||||
- Resources – a description of any external resources you used to complete the lab
|
||||
- Build – instructions on how to build and run your program. Include the exact commands that are necessary
|
||||
- Analysis – Discuss the key concepts from the lab and answers to the following questions
|
||||
- Commands in TTSH are executed by a call to ```fork()``` followed by a call to ```exec()```. What would bee the behavior of teeny tiny shell if the calls were reversed?
|
||||
- There are many 'flavors' of ```exec()```. For this lab you used ```execvp```, research the other 'flavors' of ```exec()```. What is each used for? Be sure to site your sources:
|
||||
- execl
|
||||
- execlp
|
||||
- execle
|
||||
- execv
|
||||
- execvp
|
||||
- execvpe
|
||||
- For this lab you used the ```fork()``` system call to create a child process to execute the command. There is another version of fork called ```vfork()```. Research this system call and describe how it works. Be sure to site your sources. When would you choose to use ```vfork()``` instead of ```fork()```.
|
||||
- Conclusion
|
||||
- Summary of what you learned in the lab
|
||||
- What specifically was challenging about this lab?
|
||||
- What did you like about it?
|
||||
- What could we do to improve it for others?
|
||||
|
||||
NOTE: You should ensure that this program compiles without warning (-Wall and -Wextra) prior to submitting.
|
||||
|
||||
Prepare a zip file with all submitted files and upload the file to Canvas per your instructor's instructions.
|
||||
|
||||
## Grading Criteria
|
||||
|
||||
- (35 Points) Report
|
||||
- (5 Points) Report Introduction - Thorough description of the lab in your own words.
|
||||
- (5 Points) Design and Testing Methodology - Detailed description of design and method for testing your implementation.
|
||||
- (20 Points) Analysis - Answers to the analysis questions
|
||||
- (5 Points) Conclusion - Thorough conclusion with description of what you learned, what you liked, and suggestions for lab improvements.
|
||||
- (5 Points) Documented Resources - Description of external resources used to complete the lab
|
||||
- (5 Points) Correct Submission - Followed submission instructions (e.g. IDE project files are not submitted)
|
||||
- (5 Points) Build - Code compiles without warnings or errors
|
||||
- (45 Points) Instructor Tests - Implementation passes all instructor test cases
|
||||
- (5 Points) Memory Management - Program execution is free from memory leaks
|
||||
2
02-TeenyTinyShell/testcases/tc1
Normal file
2
02-TeenyTinyShell/testcases/tc1
Normal file
@@ -0,0 +1,2 @@
|
||||
quit
|
||||
|
||||
3
02-TeenyTinyShell/testcases/tc10
Normal file
3
02-TeenyTinyShell/testcases/tc10
Normal file
@@ -0,0 +1,3 @@
|
||||
ls; ls; ls; ls; ls; ls; ls; ls; ls; ls; ls;
|
||||
quit
|
||||
|
||||
3
02-TeenyTinyShell/testcases/tc2
Normal file
3
02-TeenyTinyShell/testcases/tc2
Normal file
@@ -0,0 +1,3 @@
|
||||
ls
|
||||
quit
|
||||
|
||||
3
02-TeenyTinyShell/testcases/tc3
Normal file
3
02-TeenyTinyShell/testcases/tc3
Normal file
@@ -0,0 +1,3 @@
|
||||
ls -l
|
||||
quit
|
||||
|
||||
5
02-TeenyTinyShell/testcases/tc4
Normal file
5
02-TeenyTinyShell/testcases/tc4
Normal file
@@ -0,0 +1,5 @@
|
||||
ls -l -a
|
||||
echo hi
|
||||
echo bye
|
||||
quit
|
||||
|
||||
4
02-TeenyTinyShell/testcases/tc5
Normal file
4
02-TeenyTinyShell/testcases/tc5
Normal file
@@ -0,0 +1,4 @@
|
||||
ps aux
|
||||
ls -l
|
||||
quit
|
||||
|
||||
3
02-TeenyTinyShell/testcases/tc6
Normal file
3
02-TeenyTinyShell/testcases/tc6
Normal file
@@ -0,0 +1,3 @@
|
||||
slkjlkjfslkjslkjfskj
|
||||
quit
|
||||
|
||||
3
02-TeenyTinyShell/testcases/tc7
Normal file
3
02-TeenyTinyShell/testcases/tc7
Normal file
@@ -0,0 +1,3 @@
|
||||
ls -l -l -l -l -l -l -l -l -l -l -l -l -l -l -l
|
||||
quit
|
||||
|
||||
3
02-TeenyTinyShell/testcases/tc8
Normal file
3
02-TeenyTinyShell/testcases/tc8
Normal file
@@ -0,0 +1,3 @@
|
||||
echo hi; ls; echo bye
|
||||
quit
|
||||
|
||||
3
02-TeenyTinyShell/testcases/tc9
Normal file
3
02-TeenyTinyShell/testcases/tc9
Normal file
@@ -0,0 +1,3 @@
|
||||
echo hi; ls -l; ps aux; echo bye
|
||||
quit
|
||||
|
||||
102
02-TeenyTinyShell/ttsh.c
Normal file
102
02-TeenyTinyShell/ttsh.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/*************************************
|
||||
*
|
||||
* Class: CS3840 - YOUR SECTION HERE
|
||||
*
|
||||
* Name(s): YOUR NAME(S) HERE
|
||||
*
|
||||
* Lab: Teeny Tiny Shell
|
||||
*
|
||||
*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define INPUT_MAX 256
|
||||
#define CMD_MAX 5
|
||||
|
||||
/* read_cmd_string()
|
||||
* Reads a line of text from the user
|
||||
* Parameters: dest - target location for the input
|
||||
* Returns: int - 0 on success or
|
||||
* -1 on error
|
||||
*/
|
||||
int read_cmd_string(char dest[INPUT_MAX])
|
||||
{
|
||||
// Read user input
|
||||
if(fgets(dest, INPUT_MAX, stdin) == NULL) {
|
||||
fprintf(stderr, "Unable to read user input\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Remove trailing return character
|
||||
int len = strlen(dest);
|
||||
if(dest[len-1] == '\n') {
|
||||
dest[len - 1] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* parse_commands()
|
||||
* Reads a line of text from the user
|
||||
* Parameters: input - string containing user input
|
||||
* cmd_strs - the target array for command strings
|
||||
* Returns: int - The number of commands found or
|
||||
* -1 on error
|
||||
*/
|
||||
int parse_commands(char input[INPUT_MAX], char cmd_strs[CMD_MAX][INPUT_MAX])
|
||||
{
|
||||
// Chop the input into command strings
|
||||
int cmd_count = 0;
|
||||
char* cmd_ptr = strtok(input, ";");
|
||||
while(cmd_ptr) {
|
||||
if(cmd_count >= CMD_MAX) {
|
||||
fprintf(stderr, "Too many commands\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(cmd_strs[cmd_count], cmd_ptr, INPUT_MAX);
|
||||
cmd_count++;
|
||||
cmd_ptr = strtok(NULL, ";");
|
||||
}
|
||||
|
||||
return cmd_count;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char user_input[INPUT_MAX];
|
||||
char cmd_strs[CMD_MAX][INPUT_MAX];
|
||||
|
||||
// TODO need to be able to get input from
|
||||
// the user in a loop
|
||||
|
||||
// Print the input prompt
|
||||
printf("$> ");
|
||||
|
||||
// Read user input
|
||||
if(read_cmd_string(user_input) == -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: Figure out how to handle the 'quit' command
|
||||
|
||||
// Chop the input into command strings
|
||||
int cmd_count = parse_commands(user_input, cmd_strs);
|
||||
if(cmd_count == -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Chop the commands into arguments and execute one at a time
|
||||
for(int i = 0; i < cmd_count; i++) {
|
||||
|
||||
// TODO:
|
||||
// 1) Chop the command into command line arguments
|
||||
// need to handle up to 10 arguments
|
||||
// NOTE: the command name is always the first argument
|
||||
// 2) fork a process
|
||||
// 3) execute the command with execvp
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
03-MatrixAddition/.DS_Store
vendored
Normal file
BIN
03-MatrixAddition/.DS_Store
vendored
Normal file
Binary file not shown.
284
03-MatrixAddition/MatrixAddition.md
Normal file
284
03-MatrixAddition/MatrixAddition.md
Normal file
@@ -0,0 +1,284 @@
|
||||
## Introduction
|
||||
|
||||
The purpose of this lab is to design, code, and test programs to add two matrices together using both a single process and multiprocess program. It is intended to familiarize yourself with the system calls needed to create processes and share memory on Linux.
|
||||
|
||||
The first program will perform matrix addition with a single process storing the result in a matrix allocated on the heap (via malloc). In the second program, child processes will be created with ```fork()``` to perform the addition for each row in the matrix storing their result in a matrix created in shared memory.
|
||||
|
||||
The matrices will be read from a file. The format for the file is given later.
|
||||
|
||||
## References
|
||||
|
||||
You will be using the ```fork()``` system call to create child processes to compute a portion of matrix addition. The children will then write their result to the correct position in a matrix stored in shared memory. You will also be timing your code's executing using the ```clock_gettime()``` system call. Before you start, it might be helpful to read the 'man' pages for these system calls.
|
||||
|
||||
1. You will be using the ```fork()``` system call to create child processes
|
||||
2. You will also be timing your code's executing using the ```clock_gettime()``` system call
|
||||
3. You will have to allocate a share memory segment using ```shm_open()```
|
||||
4. You will have to initialize the segment to the correct size using ```ftruncate()```
|
||||
5. You will have to map the shared memory into the process address space using ```mmap()```
|
||||
6. You will have to release the space at the end of your program using ```munmap()```
|
||||
7. You will have to delete the shared memory segment using ```shm_unlink()```
|
||||
|
||||
## The Exercise
|
||||
|
||||
Recall from linear algebra you can add two matrices using the following:
|
||||
|
||||
If A = [a<sub>ij</sub>] is an m x n matrix and B = [b<sub>ij</sub>] is an m x n matrix, the sum of A + B is an m x n matrix.
|
||||
A + B = [c<sub>ij</sub>], where c<sub>ij</sub> = a<sub>ij</sub> + b<sub>ij</sub>
|
||||
|
||||
The definition of matrix addition indicates a cell by cell addition. For each cell in A, the value is added to the value in the corresponding cell of B. To add A and B they must be the same dimensions.
|
||||
|
||||
For example:
|
||||
|
||||
$$
|
||||
A = \begin{bmatrix}
|
||||
1 & 10 & 0 \\
|
||||
3 & -2 & 6
|
||||
\end{bmatrix}
|
||||
B = \begin{bmatrix}
|
||||
1 & 4 & 0\\
|
||||
1 & 2 & 3
|
||||
\end{bmatrix}
|
||||
$$
|
||||
$$
|
||||
A + B = \begin{bmatrix}
|
||||
1 + 1 & 10 + 4 & 0 + 0 \\
|
||||
3 + 1 & -2 + 2 & 6 + 3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
2 & 14 & 0 \\
|
||||
4 & 0 & 9
|
||||
\end{bmatrix}
|
||||
$$
|
||||
|
||||
Matrix addition is commutative. So, A + B does is always equal B + A.
|
||||
|
||||
Your task is to create two programs that will perform matrix addition for two matrices given to you as two files and print the result. Each program must also record the amount of time it took to perform the matrix addition.
|
||||
|
||||
- The first program will perform the matrix addition with a single process.
|
||||
- The second program will perform the matrix addition with multiple processes – one process for each row.
|
||||
|
||||
The format for each matrix file is:
|
||||
|
||||
- The first line will contain two numbers: the number of rows in the matrix followed by the number of columns
|
||||
- The rest of the file will contain rows of numbers representing the numbers in the matrix
|
||||
|
||||
For the example given above the file for A would be:
|
||||
|
||||
```text
|
||||
2 3
|
||||
1 10 0
|
||||
3 -2 6
|
||||
```
|
||||
|
||||
And the file for B would be:
|
||||
```text
|
||||
2 3
|
||||
1 4 0
|
||||
1 2 3
|
||||
```
|
||||
|
||||
All numbers in the file will be separated by spaces.
|
||||
|
||||
## Development: Single Process
|
||||
|
||||
It's simplest to break down the development into pieces:
|
||||
|
||||
1. Read the matrices
|
||||
2. Perform the matrix addition
|
||||
3. Print the result
|
||||
|
||||
### 4.1 Read the Matrix Files
|
||||
|
||||
A simple way to read integers from a file is to use the ```fscanf``` function. This function allows you to do formatted reading from a file. We'll use this to read numbers. To use ```fscanf``` you first must open a FILE* with ```fopen``` (take a look at 'man fopen' for more information). Then, like printf for printing a number you use the “%d” format as a parameter to ```fscanf``` to read a number. Here is an example:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int value;
|
||||
FILE* input = fopen(argv[1], "r");
|
||||
fscanf(input, "%d", &value);
|
||||
fclose(input);
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: the matrix file names will be given on the command line as arguments. For example: ./a.out matA matB
|
||||
Command line arguments are passed to main through the argc and argv values (see example above). The argc value tells the program the number of command line arguments, and argv is an array of character pointers for the argument strings. There is always 1 argument passed to your program (argv[0]) which contains the name of your program. So your matrix input files will be in argv[1] and argv[2]. If the user didn't provide enough arguments (e.g. argc != 3) then print an error and exit.
|
||||
|
||||
You can use this ```fscanf``` to read in all the numbers you need from the file. It takes care of all the white space for you. So, to read your matrix file you can start with:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int rows, columns;
|
||||
FILE* input = fopen(argv[1], "r");
|
||||
fscanf(input, "%d", &rows);
|
||||
fscanf(input, "%d", &columns);
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < columns; j++) {
|
||||
int value;
|
||||
fscanf(input, "%d", &value);
|
||||
}
|
||||
}
|
||||
fclose(input);
|
||||
}
|
||||
```
|
||||
|
||||
Obviously, you'll need to store the row and column values somewhere. Since the matrix can be any size (within reason), you'll need to store the matrix in memory on the heap allocating a space for it using malloc. Remember that malloc creates a contiguous space in memory on the heap for the given size. Think about how much memory you'll need to malloc to store each matrix. When storing the values in the malloc'ed space you'll also have to do some math to make sure the indexing is correct.
|
||||
|
||||
### Adding the Matrices
|
||||
|
||||
When you store the matrices in the space created by malloc they are in one contiguous space in memory. So, to perform the matrix math, you'll also need to correctly compute the correct memory offset. Thankfully to access the memory at an index you can just reference it like an array:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// malloc a space
|
||||
int* space = malloc(sizeof(int) * 100);
|
||||
|
||||
// Store data in the space
|
||||
for(int i = 0; i < 100; i++) {
|
||||
space[i] = i + 10;
|
||||
}
|
||||
|
||||
// Read data from the space
|
||||
for(int i = 0; i < 100; i++) {
|
||||
printf("%d\n", space[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
For this assignment, you'll just need to do the index calculation for the correct index based on the value's row and column. From there the calculation is just based on the matrix addition formula.
|
||||
|
||||
### Print the Result
|
||||
|
||||
It's probably easiest to store the matrix for the addition result in its own malloc'ed space. Once you have the result, you'll need to perform the index math to print out the matrix elements to the screen. For our example, that would be:
|
||||
|
||||
```text
|
||||
2 14 0
|
||||
4 0 9
|
||||
```
|
||||
|
||||
Print out each element in the rows and columns separated by a space. Don't worry about making sure they line up. You will also need to print out the amount of time it took to perform the matrix addition. For that you will use the ```clock_gettime``` function to get the ```CLOCK_REALTIME``` for the system before and after you do the matrix addition. You only need to record the time for the addition, don't include the time it took to read the matrix files or to print the result.
|
||||
|
||||
## Development: Multi-Process
|
||||
|
||||
Once you get your single process program working you'll follow the same steps for the multiprocess version, except that now you have use ```fork()``` to create a process for each row in the matrix element. Breaking this down into pieces:
|
||||
|
||||
1. Read the matrices
|
||||
2. ```fork()``` child processes to perform the matrix addition (one per row in the result matrix)
|
||||
3. Child processes perform the matrix addition for their given row
|
||||
4. The child processes write their results to the result matrix stored in shared memory
|
||||
5. The parent waits for all child process to finish
|
||||
6. Parent prints the result
|
||||
|
||||
NOTE: Recall that heap space is not shared between parent and child processes. So the result matrix is to be created in shared memory. Do this by creating a named share memory segment using ```shm_open``` and ```mmap```. Choose an appropriate name for the segment.
|
||||
|
||||
It is up to you to decide how the matrix is organized in the shared memory space. You can organize it as a one-dimensional array and use index calculation to find the row and column or as a two-dimensional array. However, remember that a shared memory segment is a single contiguous address range.
|
||||
|
||||
NOTE: Use only a single shared memory segment. Do ***NOT*** use a separate shared memory segment for each row.
|
||||
|
||||
### Read the Matrix Files
|
||||
|
||||
This is the same as the single process version
|
||||
|
||||
### Create child processes to perform the matrix addition
|
||||
|
||||
You will need to ```fork()``` a process for each row in the matrices. For our example above A + B has 2 rows so that requires 2 child processes. You'll need to ```fork()``` in a loop, make sure you keep track of the pid for each child process because the parent will need to wait for them to finish. Since you won't know how many processes you need when the program starts, you'll need to malloc a space to store the child process identifiers (pids).
|
||||
|
||||
### Child processes perform the matrix addition for their given row
|
||||
|
||||
Once you ```fork()``` the child processes you'll need to figure out how to make sure that each child process performs the matrix addition calculation each element in their given row. The formula for the calculation is the same as the single process version.
|
||||
|
||||
### Child processes write their computation to the shared result matrix
|
||||
|
||||
Allocated and mapped shared memory persists after a ```fork()``` system call so all child processes have access to a result matrix created in shared memory. The child processes can write their result directly to the shared memory space for the result matrix. The parent does not need to collect results.
|
||||
|
||||
### The parent waits for all child process to finish
|
||||
|
||||
The parent needs to keep track of all the process identifiers (pids) for all child processes and perform a waitpid for each one. This will require a loop and call to ```waitpid()```. See the man page for ``waitpid()``` for additional information.
|
||||
|
||||
### Parent prints the result
|
||||
|
||||
Once the child processes have finished, printing the result is the same as the single process program. Make sure the parent waits for the children to finish otherwise the result matrix won't be correct.
|
||||
|
||||
## Development Tips
|
||||
|
||||
- Remember that to successfully add two matrices the dimensions must match. So an m x n matrix can be added to an m x n matrix, but an m x n matrix cannot be added to a m x p matrix unless n == p. If the input matrices are not the correct size, print an error message to the user and quit.
|
||||
- Don't forget to free your mallocs! Remember that when a parent malloc's space on the heap, the child will get an EXACT COPY of that data. The child also inherits the responsibility to free the storage. Don't forget to free your mallocs!
|
||||
- Don't forget to ```munmap``` your ```mmap``` spaces! Remember that when a parent maps an address space, the children processes also gets that ```mmap```. The child must therefore ```munmap``` the address space AND close any used file descriptors when it is done. Don't forget to do this in your code!
|
||||
- Don't forget to close your file descriptors! When you call shm_open you get back a file descriptor. The children inherit file descriptors after a ```fork()```. All opened file descriptors must be closed by all processes when they are done using them (the parent too).
|
||||
- Don't forget to ```shm_unlink``` your named shared memory segments! Named shared memory segments are persistent (they live beyond the life of your process). Make sure you ```shm_unlink()``` your named shared memory segments. BUT make sure you don't ```shm_unlink``` before you need to. Don't remove a shared memory segment until you are absolutely sure that nobody else is using it!
|
||||
- Don't forget about using gdb to help with debugging (compile with -g to get additional debug symbols)
|
||||
|
||||
NOTE: when using gdb it is helpful to compile your program with additional debug symbols included. These allow gdb to show you more information when running commands like backtrace (bt). To compile with additional debug symbols use the -g flag on gcc. For example:
|
||||
|
||||
```text
|
||||
gcc -Wall -g -o myprog mysourcefile1.c mysourcefile2.c mysourcefile3.c
|
||||
```
|
||||
|
||||
- Using valgrind will be helpful in this lab to ensure you do not have any memory leaks.
|
||||
- When compiling your shared memory program you will need to include an additional compiler flag: -lrt. This tells the compiler to use the real-time c library where the wrapper function calls for the shared memory system calls. The examples use this in the Makefile, so you can see how to use it there as well. For example:
|
||||
|
||||
```text
|
||||
gcc -Wall -g -o myprog mysourcefile1.c mysourcefile2.c mysourcefile3.c -lrt
|
||||
```
|
||||
|
||||
NOTE: the -lrt flag must be the LAST thing on the command line. If it is not, your program will not compile.
|
||||
|
||||
## Testing and Debugging
|
||||
|
||||
There are [several matrix files](matrices.zip) located provided along with this specification. You can use those to help get your programs working. You are also required to create some of your own and include those in your submission. Don't forget to test large matrices.
|
||||
|
||||
## Deliverables
|
||||
|
||||
You will need to include all your source files, test case matrix files, and any other resources you used to complete lab. Please don't just google search for a solution, but if you do use Google for any help, include a description and URL of what you used to help you.
|
||||
|
||||
A makefile is useful, but optional for this assignment. If you created a makefile, include it in your submission.
|
||||
|
||||
All files should be well documented with function comment blocks and inline comments that explain complicated code routines. While no explicit style guidelines are set for programming in this course, code should be documented and readable. Include your name, section, and lab name in a comment block at the top of each file.
|
||||
|
||||
NOTE: do ***NOT*** submit any IDE configuration files (.idea, project files, etc.). Only submit your source files and report.
|
||||
|
||||
Prepare a lab report and submit it along with your source code. The report should include the following:
|
||||
|
||||
- Your name, section, date, and lab title
|
||||
- Introduction – a description of the lab in your own words
|
||||
- Design – a description of your design decisions in creating your solution
|
||||
- Resources – a description of any external resources you used to complete the lab
|
||||
- Build – instructions on how to build and run your programs. Include the exact commands that are necessary
|
||||
- Analysis – Your two programs (single process and multiprocess) need to print out the time to perform the matrix addition. Use this information to evaluate the usefulness of multiprocess programming. Is there an advantage to using multiprocessing for matrix addition? Be thorough.
|
||||
<br/>In addition, answer the following in your analysis
|
||||
- How does the runtime of the single process compare to the multiple process version? Faster? Slower? Why do you think this is the case? Think in terms of operating system overhead.
|
||||
- How could identifying patterns in the source matrices be used to speed up the computation?
|
||||
- How does shared memory affect the overall heap needed by the process? If you run your program using valgrind, it will print out a summary of the total heap used. What conclusions can you draw from this?
|
||||
- Conclusion
|
||||
- Summary of what you learned in the lab
|
||||
- What specifically was challenging about this lab?
|
||||
- What did you like about it?
|
||||
- What could we do to improve it for others?
|
||||
|
||||
NOTE: You should ensure that this program compiles without warning (-Wall and -Wextra) prior to submitting.
|
||||
|
||||
Prepare a zip file with all submitted files and upload the file to Canvas per your instructor's instructions.
|
||||
|
||||
## Grading Criteria
|
||||
|
||||
- (35 Points) Report
|
||||
- (5 Points) Report Introduction - Thorough description of the lab in your own words.
|
||||
- (5 Points) Design and Testing Methodology - Detailed description of design and method for testing your implementation.
|
||||
- (20 Points) Analysis - Answers to the analysis questions
|
||||
- (5 Points) Conclusion - Thorough conclusion with description of what you learned, what you liked, and suggestions for lab improvements.
|
||||
- (5 Points) Documented Resources - Description of external resources used to complete the lab
|
||||
- (5 Points) Correct Submission - Followed submission instructions (e.g. IDE project files are not submitted)
|
||||
- (5 Points) Build - Code compiles without warnings or errors
|
||||
- (10 Points) Test Cases - Thoroughness of submitted test cases
|
||||
- (35 Points) Instructor Tests - Implementation passes all instructor test cases
|
||||
- (5 Points) Memory Management - Program execution is free from memory leaks. All shared memory segments are cleaned up.
|
||||
3
03-MatrixAddition/matrices/matA
Normal file
3
03-MatrixAddition/matrices/matA
Normal file
@@ -0,0 +1,3 @@
|
||||
2 3
|
||||
1 10 0
|
||||
3 -2 6
|
||||
3
03-MatrixAddition/matrices/matB
Normal file
3
03-MatrixAddition/matrices/matB
Normal file
@@ -0,0 +1,3 @@
|
||||
2 3
|
||||
1 4 0
|
||||
1 2 3
|
||||
11
03-MatrixAddition/matrices/matC
Normal file
11
03-MatrixAddition/matrices/matC
Normal file
@@ -0,0 +1,11 @@
|
||||
10 10
|
||||
0 0 3 2 2 3 3 2 3 1
|
||||
0 2 3 1 2 2 2 3 2 0
|
||||
3 1 3 0 2 2 0 1 0 3
|
||||
2 0 1 3 0 2 2 1 0 0
|
||||
2 2 2 1 3 0 0 3 0 0
|
||||
3 1 2 2 3 1 1 0 0 3
|
||||
1 1 1 2 1 2 0 0 0 3
|
||||
3 1 2 0 2 0 0 2 3 1
|
||||
1 2 1 3 3 2 3 1 1 3
|
||||
3 1 0 2 3 2 3 1 1 0
|
||||
11
03-MatrixAddition/matrices/matD
Normal file
11
03-MatrixAddition/matrices/matD
Normal file
@@ -0,0 +1,11 @@
|
||||
10 10
|
||||
3 3 3 3 1 2 3 0 0 2
|
||||
1 2 0 2 4 1 4 2 2 2
|
||||
4 0 0 0 4 1 3 4 3 1
|
||||
2 1 3 1 2 3 1 2 3 4
|
||||
0 3 2 2 3 2 1 2 2 0
|
||||
2 2 1 2 1 1 1 4 1 4
|
||||
4 0 2 2 4 1 0 1 0 2
|
||||
4 4 3 0 2 3 3 4 0 4
|
||||
2 4 0 1 0 4 3 2 0 4
|
||||
3 2 4 4 0 1 3 3 4 4
|
||||
101
03-MatrixAddition/matrices/matE
Normal file
101
03-MatrixAddition/matrices/matE
Normal file
@@ -0,0 +1,101 @@
|
||||
100 100
|
||||
7 8 6 5 5 6 5 4 8 9 9 1 4 5 9 9 3 5 3 2 3 1 1 1 8 0 7 0 7 6 3 7 5 3 0 9 3 7 4 7 7 1 8 1 3 0 4 8 0 1 1 9 1 5 7 7 2 5 4 7 3 4 1 6 5 6 9 1 6 7 7 6 1 5 1 6 3 0 5 6 4 9 1 2 5 4 2 9 3 6 9 8 0 0 4 5 2 9 3 7
|
||||
8 6 5 4 3 1 7 2 7 7 8 1 9 7 8 6 3 1 0 5 1 4 7 3 7 8 6 7 8 5 7 1 0 0 1 2 5 6 9 1 1 6 7 1 7 5 0 6 3 5 6 0 0 7 8 0 3 4 0 3 1 1 3 8 6 6 9 6 0 6 7 4 2 3 2 6 7 8 9 6 3 2 2 9 0 8 2 1 9 1 2 7 2 9 6 9 2 1 0 7
|
||||
6 6 8 6 4 1 1 0 9 4 9 5 9 0 4 1 1 8 5 9 5 8 2 2 0 9 6 1 5 1 4 2 6 1 5 9 9 6 6 0 0 8 7 8 1 2 6 8 0 8 1 0 5 0 8 1 4 9 4 2 0 2 5 6 3 9 7 3 6 7 8 8 1 5 4 0 5 3 4 1 5 6 4 3 5 4 4 1 6 1 8 3 6 0 0 0 6 2 4 8
|
||||
4 7 1 4 9 6 6 2 7 2 3 1 5 5 1 4 6 8 5 9 8 3 6 8 5 4 6 1 7 9 9 7 7 5 6 8 6 7 3 1 1 6 9 3 7 9 0 9 4 3 7 1 2 0 3 9 5 6 4 7 1 3 0 0 4 6 2 9 7 5 0 6 0 6 0 8 8 8 5 9 9 6 0 4 2 1 9 3 2 7 0 4 1 5 3 1 3 4 3 2
|
||||
1 7 4 7 9 0 9 1 5 4 1 3 3 2 7 7 3 8 4 9 3 9 5 3 9 5 0 1 3 0 8 5 0 1 2 6 2 6 4 9 3 8 5 2 5 0 0 0 8 0 1 6 7 3 9 1 1 5 9 5 1 8 8 6 0 7 1 8 6 2 8 6 2 6 3 5 8 4 6 4 4 8 1 3 3 4 2 7 9 1 5 2 1 7 4 2 1 3 3 8
|
||||
2 6 9 2 4 7 0 3 7 8 9 5 3 5 2 0 2 3 8 4 2 5 9 2 2 8 9 3 8 5 2 2 8 0 1 6 8 6 6 6 1 4 1 7 0 2 4 5 0 4 7 0 5 2 1 7 2 4 4 0 4 9 2 1 8 3 5 6 8 4 4 7 5 6 2 7 9 9 6 0 0 4 1 3 4 0 6 4 0 5 5 1 2 0 9 8 0 6 5 5
|
||||
6 2 3 2 1 8 4 9 2 7 6 2 9 9 5 1 6 0 6 1 2 6 2 9 8 7 9 4 8 6 2 4 8 2 5 2 1 0 0 3 0 4 0 8 9 0 8 3 0 7 0 7 0 2 2 7 4 8 9 1 0 3 6 7 1 5 3 5 3 0 5 5 2 5 0 4 8 9 5 0 3 4 2 0 3 2 0 4 3 9 7 6 4 0 3 5 2 8 4 8
|
||||
5 3 1 1 6 3 6 0 0 8 8 3 1 8 9 1 8 0 4 6 5 0 1 5 8 8 2 1 0 0 2 8 3 3 9 4 6 1 3 9 2 1 6 7 9 4 8 6 6 6 7 1 1 3 4 4 3 8 3 6 3 4 8 4 5 3 1 8 4 7 6 3 0 3 6 5 8 0 7 4 9 2 9 3 2 1 3 6 2 5 6 1 4 5 2 9 7 4 2 7
|
||||
3 2 7 2 4 0 7 2 0 3 0 4 2 5 5 6 7 0 7 8 2 7 0 1 8 3 6 6 2 3 5 8 5 9 9 2 3 4 6 0 9 7 8 2 2 2 9 2 5 3 1 1 5 1 6 1 8 3 9 1 4 5 7 7 1 6 0 5 4 3 1 8 5 4 9 0 0 7 4 3 8 9 5 3 0 9 5 9 1 3 8 5 7 0 0 1 1 0 9 9
|
||||
6 4 4 5 8 0 9 2 4 5 7 9 0 8 7 0 3 2 5 6 4 7 5 7 6 0 4 8 0 0 3 1 5 8 1 2 4 1 3 6 4 0 2 8 9 3 3 3 0 3 7 9 2 2 2 1 1 8 0 8 1 6 7 6 5 7 3 7 9 0 8 1 4 8 7 9 9 4 3 2 6 8 8 5 8 7 2 7 9 6 9 8 6 6 9 9 5 6 5 6
|
||||
7 3 2 2 3 2 9 4 0 7 0 5 9 8 7 5 5 4 6 4 1 1 7 4 9 0 5 5 1 1 4 3 0 4 0 5 3 9 8 6 1 5 7 2 1 2 7 1 1 5 7 9 2 9 2 0 4 3 0 3 4 0 7 4 1 8 3 0 4 6 7 4 6 9 8 4 0 7 9 6 4 0 0 2 7 9 8 0 2 1 3 1 7 8 2 9 4 7 4 6
|
||||
9 0 4 2 5 4 7 3 3 0 4 7 8 4 1 0 8 0 4 7 4 6 4 4 2 2 7 4 2 9 2 8 8 2 3 2 6 7 2 0 0 6 4 4 0 7 6 3 3 7 2 4 8 2 0 8 1 1 7 1 3 3 1 7 6 2 0 1 9 5 3 1 1 4 8 1 7 1 5 1 1 3 3 0 5 0 4 9 5 8 5 7 8 6 6 5 4 1 6 7
|
||||
8 1 3 5 6 0 5 9 2 9 8 1 9 6 0 8 4 1 1 6 5 0 6 8 3 1 0 6 2 3 3 9 5 4 7 7 9 7 1 7 4 5 0 2 0 2 4 0 5 3 6 3 5 8 0 2 0 1 4 4 6 1 2 9 2 5 9 1 6 9 7 6 1 6 1 9 6 1 8 6 9 7 6 8 1 7 4 9 2 9 9 5 7 5 1 0 4 5 4 7
|
||||
1 2 1 6 2 6 5 9 3 9 8 3 2 2 7 4 6 2 9 2 7 6 6 3 1 4 4 9 0 8 1 0 1 0 0 0 9 5 4 6 6 5 7 4 0 9 7 6 9 1 8 3 7 2 2 5 3 1 0 9 3 0 6 8 4 3 0 0 3 9 4 7 0 5 1 8 7 4 6 6 8 8 6 4 6 4 8 1 9 9 8 4 0 3 5 0 1 3 9 4
|
||||
7 2 0 1 4 2 2 9 9 2 8 9 0 2 5 5 7 0 1 0 6 3 9 4 4 6 5 3 0 4 8 5 2 0 8 1 2 7 5 8 3 1 3 3 3 9 7 1 5 8 6 4 3 1 3 3 6 9 8 3 1 5 2 2 5 0 5 7 8 1 6 0 5 4 6 8 8 0 0 1 2 2 4 2 7 6 1 9 7 5 8 6 9 7 8 6 2 8 0 0
|
||||
6 0 3 5 8 2 0 6 8 7 6 5 8 9 0 1 2 9 9 8 5 4 7 2 0 0 5 0 8 0 9 1 0 5 5 3 9 6 3 9 0 4 7 2 5 7 3 4 0 3 0 2 7 2 2 9 3 6 8 5 6 2 7 7 1 3 6 2 0 1 2 0 7 4 6 0 4 8 0 6 5 6 3 3 8 6 0 4 6 9 5 8 3 2 4 1 2 2 7 5
|
||||
6 4 1 8 6 5 8 0 3 5 5 4 8 7 6 5 0 4 9 0 2 3 1 1 6 2 6 1 0 2 7 6 9 7 9 1 3 1 2 5 8 9 6 9 3 1 1 1 1 6 6 8 9 6 1 5 3 8 0 4 7 3 1 7 8 3 8 6 8 5 3 4 1 3 1 5 4 3 7 1 4 4 9 9 8 4 6 2 3 8 6 6 3 5 0 9 1 4 5 4
|
||||
6 9 8 9 7 7 1 5 0 5 6 5 9 4 9 8 5 2 9 0 5 0 4 3 6 7 7 6 9 7 2 7 3 1 2 6 3 1 6 1 9 8 2 8 5 5 4 4 3 6 1 4 4 9 7 6 8 0 4 9 8 7 1 7 6 3 1 1 2 9 5 8 6 5 2 4 7 4 7 1 8 9 7 9 6 7 4 0 8 3 8 1 3 3 7 8 7 1 7 7
|
||||
4 4 5 9 4 5 1 6 8 8 1 6 9 5 9 1 7 7 3 8 2 3 6 7 0 4 1 0 0 4 7 9 7 9 0 5 6 3 4 5 8 8 7 5 4 2 4 4 2 6 7 6 3 6 5 4 7 2 3 1 9 4 8 8 5 6 9 1 7 6 7 3 9 3 1 7 5 8 2 7 9 7 0 0 1 1 2 2 3 4 2 6 2 0 1 6 3 6 5 0
|
||||
5 9 8 4 7 4 3 5 9 5 3 2 4 1 5 1 7 6 6 1 1 9 9 3 8 3 4 6 6 6 1 0 6 9 8 1 9 6 7 5 5 0 9 5 0 3 6 1 2 9 2 3 3 0 7 2 0 2 9 6 9 8 7 9 4 2 1 7 4 7 0 6 9 3 5 6 7 7 2 4 4 6 6 4 4 9 3 4 6 6 3 7 7 5 0 0 1 7 0 5
|
||||
7 8 9 1 8 6 8 0 2 3 9 8 7 1 8 2 4 2 1 3 4 1 0 7 6 5 7 6 0 0 8 2 3 2 0 0 3 2 8 2 4 4 6 7 7 4 4 5 5 1 0 0 8 4 3 4 7 9 1 7 5 8 3 0 9 1 5 7 2 3 9 0 6 3 5 6 4 9 4 9 2 8 9 9 2 7 2 2 0 1 1 8 5 7 1 1 3 6 9 9
|
||||
8 6 6 7 0 1 1 3 3 8 4 6 4 4 4 7 1 4 3 0 8 3 5 3 9 7 7 3 2 2 4 1 6 5 7 2 2 3 0 3 2 2 5 9 4 6 5 7 6 9 3 7 6 2 5 5 3 7 2 0 9 0 1 1 4 6 4 6 4 0 1 7 8 9 5 3 6 9 0 5 5 2 5 4 5 6 4 2 6 6 2 0 9 7 0 0 6 4 6 7
|
||||
7 0 4 0 4 0 9 2 0 6 7 2 3 2 1 9 3 4 0 2 2 2 9 6 3 7 6 1 3 6 3 8 6 6 1 1 5 4 9 6 4 0 3 9 4 7 6 0 2 1 5 5 7 6 0 6 4 4 9 8 8 4 6 7 4 9 5 7 3 8 3 3 7 8 0 5 2 0 5 1 4 8 9 2 7 6 5 7 7 0 3 9 3 0 4 7 7 5 6 7
|
||||
7 6 3 6 7 3 0 0 1 2 9 2 6 8 9 5 0 0 9 4 9 9 9 6 8 2 5 0 3 7 6 0 0 2 2 7 7 3 2 6 7 4 6 6 6 2 5 9 2 7 4 9 9 0 0 7 9 0 2 3 1 0 5 4 9 8 6 3 1 9 5 1 8 1 4 3 7 6 0 8 9 8 6 8 2 7 0 2 9 3 7 3 5 5 4 3 7 4 7 3
|
||||
2 7 4 5 9 4 6 9 2 2 4 1 3 4 1 2 2 0 3 3 5 2 9 6 3 8 1 0 9 4 4 4 5 1 8 9 1 8 9 8 0 8 9 2 3 5 1 4 0 0 9 5 4 7 7 6 6 9 4 5 4 1 7 0 9 9 4 4 0 4 9 4 7 4 6 0 9 1 2 9 2 4 1 4 8 8 0 0 9 5 5 2 0 5 9 4 0 1 0 7
|
||||
1 9 7 0 3 6 8 0 2 4 2 0 7 2 2 0 4 3 2 1 8 7 7 9 1 0 8 9 9 5 7 1 6 6 6 2 7 8 2 5 1 3 8 6 8 7 8 1 2 3 3 6 5 6 4 2 6 0 3 2 3 5 9 3 5 2 2 9 1 1 8 2 7 3 8 3 8 4 3 9 6 2 2 7 4 7 2 7 5 7 8 0 3 5 8 4 0 9 0 6
|
||||
9 9 7 1 3 5 9 7 1 2 0 3 7 2 3 0 9 9 0 3 8 4 5 9 6 3 5 4 6 0 2 0 2 1 9 6 0 1 2 3 4 7 6 1 4 8 5 4 0 0 7 4 2 1 4 1 1 2 4 9 7 0 3 5 8 9 1 0 7 2 3 8 9 6 3 9 8 7 7 3 6 8 0 7 9 3 6 8 7 8 1 3 0 4 4 2 7 9 4 6
|
||||
9 0 9 9 5 7 9 6 9 7 2 6 7 8 3 9 1 7 1 3 6 8 3 8 1 1 3 3 4 7 6 0 6 3 3 1 5 3 4 2 6 2 1 3 9 2 3 4 2 8 1 7 4 6 7 3 9 6 5 3 8 5 3 7 9 9 5 8 5 6 2 3 0 8 5 8 6 3 8 3 8 7 3 6 3 2 1 7 3 9 7 4 4 5 4 6 1 5 2 6
|
||||
3 1 6 0 8 9 6 0 5 1 9 7 7 3 6 9 8 8 8 7 6 0 1 5 9 5 7 6 7 5 2 3 5 5 4 7 7 2 7 4 7 6 4 5 9 0 6 9 7 4 1 8 2 0 0 9 2 1 4 8 0 1 8 4 9 1 1 9 0 8 3 8 8 2 0 5 7 6 3 9 3 3 9 5 8 3 1 3 7 6 9 7 4 4 8 7 2 4 1 1
|
||||
6 0 2 3 7 6 3 3 5 4 5 9 0 0 7 7 5 2 5 9 9 4 4 1 6 7 2 9 7 2 0 6 4 1 0 4 8 3 1 8 4 7 1 3 0 8 2 5 3 2 4 6 4 9 2 8 6 3 1 5 2 3 8 5 9 5 8 6 1 3 0 6 5 5 9 8 6 5 2 8 7 8 5 4 7 1 1 1 6 4 5 2 0 7 2 7 5 5 7 3
|
||||
4 5 2 6 5 8 9 1 7 2 5 1 6 1 5 5 4 1 8 1 4 8 1 7 7 5 3 1 5 9 5 1 1 3 1 2 8 1 8 3 0 9 4 9 8 1 6 7 6 8 2 9 3 0 1 3 9 1 6 0 7 4 1 3 3 8 8 8 4 0 0 9 6 5 9 2 2 6 7 3 8 3 2 0 7 5 2 3 2 5 7 8 3 8 1 7 4 7 5 8
|
||||
1 8 3 0 5 1 6 0 7 1 2 8 2 4 2 6 3 2 5 0 1 5 1 1 2 6 8 6 4 8 3 8 0 8 6 1 3 6 2 4 0 8 2 4 9 3 4 7 8 9 1 1 9 5 6 2 1 7 4 6 9 3 9 2 8 1 5 4 2 9 9 0 3 8 4 8 1 7 0 3 9 1 6 1 6 8 4 2 8 9 5 2 1 9 3 7 9 8 5 9
|
||||
7 2 7 0 2 3 6 4 3 7 2 7 7 6 4 7 0 3 8 6 8 4 8 5 0 9 4 5 1 6 4 8 5 2 6 1 3 6 1 5 2 6 7 6 0 5 8 3 4 5 8 5 3 6 9 8 4 2 5 1 1 9 5 0 4 8 5 7 4 6 5 8 1 5 1 5 1 0 3 0 6 2 9 8 9 9 6 1 4 3 1 5 4 5 0 2 9 4 2 1
|
||||
4 6 3 2 5 8 1 2 2 0 5 6 3 3 5 2 5 8 2 2 8 0 7 8 4 6 0 5 3 6 9 8 9 7 4 9 3 1 9 9 8 9 6 2 1 8 4 3 1 3 1 6 5 3 6 6 0 5 1 3 8 2 0 1 1 0 5 7 0 4 7 5 7 5 1 2 6 9 0 3 3 1 4 1 4 8 1 0 6 1 1 4 5 4 0 0 2 9 1 9
|
||||
8 2 2 5 0 7 7 8 2 0 7 0 6 8 0 7 2 6 4 3 3 9 9 8 7 2 3 0 4 4 7 3 4 4 8 1 5 7 2 7 1 0 9 3 9 9 4 4 9 2 8 1 7 2 4 7 3 9 6 1 4 9 9 1 6 5 6 7 2 6 0 4 9 9 1 6 2 8 1 5 6 1 8 4 5 3 0 9 2 8 8 1 8 1 7 0 9 5 5 2
|
||||
9 1 2 8 2 0 8 0 6 2 9 2 3 1 6 2 6 0 2 7 4 0 6 4 9 5 9 1 2 1 3 5 6 6 6 6 9 8 4 0 9 0 0 9 7 5 7 0 9 9 6 1 5 5 5 7 2 9 3 5 2 8 6 7 1 4 9 5 7 9 0 6 2 2 9 9 2 6 2 7 9 6 1 5 5 7 2 9 3 8 8 0 9 7 4 0 9 3 8 8
|
||||
5 9 9 1 0 4 9 7 0 0 9 2 6 3 8 4 1 7 2 4 7 8 9 6 3 8 3 5 7 1 6 7 5 2 2 7 0 2 4 6 0 1 1 0 0 4 7 5 8 3 2 4 9 5 9 5 7 5 0 8 3 4 3 6 9 9 2 8 8 1 7 5 4 2 9 4 3 7 6 4 5 3 2 5 5 2 9 2 7 4 1 3 4 3 1 6 6 2 3 7
|
||||
0 8 2 0 6 7 6 4 4 6 2 9 2 9 5 7 4 4 7 0 7 5 3 8 9 7 6 0 2 2 1 4 7 6 6 1 1 0 6 3 0 6 9 6 9 9 9 5 6 4 1 0 1 2 6 7 4 4 1 4 2 7 6 8 0 5 5 7 0 1 8 1 9 5 6 7 5 4 0 1 8 0 0 7 0 5 9 4 9 1 6 0 1 3 5 1 3 6 7 4
|
||||
4 3 9 2 7 7 5 9 0 4 5 9 7 1 1 7 5 3 8 2 8 6 3 8 0 2 1 8 1 5 5 5 3 9 5 3 2 2 2 9 1 2 7 4 5 0 5 5 8 0 7 8 5 7 3 7 6 4 9 2 0 5 7 1 6 6 8 4 2 8 9 6 4 4 6 7 9 1 9 8 6 0 5 3 3 8 3 8 4 7 5 8 2 5 9 9 2 5 5 7
|
||||
3 1 3 8 2 6 7 2 0 1 0 5 6 2 2 2 5 9 3 7 9 4 2 6 3 5 6 2 3 2 6 2 2 9 7 6 3 6 7 8 8 9 5 8 8 0 9 1 1 4 4 0 8 3 7 3 1 0 9 6 7 9 4 8 9 3 3 3 6 1 3 0 3 3 9 5 3 3 7 5 8 3 5 4 5 5 7 5 8 3 9 3 0 6 0 7 0 6 5 2
|
||||
7 1 9 7 0 8 8 0 2 6 4 8 5 5 2 7 3 6 9 8 8 2 6 4 9 1 1 2 5 9 1 9 9 9 5 7 2 8 0 0 1 6 5 1 2 3 2 5 2 9 6 7 5 1 4 0 8 2 6 7 8 1 0 0 3 3 8 0 4 4 2 3 1 2 3 3 0 1 8 6 2 3 2 9 5 0 3 7 5 9 9 5 9 6 9 5 7 6 7 4
|
||||
7 8 0 0 6 0 0 4 6 3 6 6 1 6 5 2 4 8 9 8 1 0 4 7 1 4 9 8 5 3 2 4 9 0 2 2 3 9 3 8 2 3 7 6 1 9 4 3 5 2 0 7 7 0 5 7 9 7 6 6 2 6 7 3 5 2 5 2 7 5 1 7 4 0 3 0 7 5 2 9 7 6 3 8 0 2 5 6 9 6 4 4 8 1 7 0 0 2 6 8
|
||||
5 9 6 9 3 1 8 8 7 7 5 9 8 6 1 2 2 5 7 6 9 2 4 8 6 2 1 4 7 5 3 1 1 6 0 9 5 0 2 6 8 3 5 7 3 9 6 3 7 9 1 8 4 0 4 7 5 0 1 0 2 7 8 2 8 4 9 9 7 2 8 3 8 8 0 7 4 1 6 1 3 5 3 9 8 9 2 1 2 5 9 3 8 4 3 8 5 8 0 8
|
||||
2 8 6 2 9 9 1 5 9 4 3 8 5 3 0 3 8 0 1 8 9 0 5 6 2 5 4 5 9 6 8 6 0 4 4 2 7 5 6 3 8 6 8 8 9 5 8 9 9 2 4 8 5 5 7 4 5 1 2 5 5 7 0 1 2 8 8 6 3 9 4 7 6 6 1 7 7 7 7 7 6 3 6 3 7 1 1 1 6 7 2 8 5 4 6 6 8 9 0 8
|
||||
2 6 5 5 5 7 5 6 8 3 0 2 3 5 1 2 0 8 1 7 2 1 6 5 5 6 2 6 9 9 3 7 6 5 1 6 8 5 6 6 0 1 9 6 0 7 9 4 9 4 7 0 7 8 3 6 0 1 1 3 9 7 2 1 9 6 0 2 1 6 4 2 1 1 4 7 5 5 0 2 2 3 8 4 6 0 2 2 2 8 7 4 8 2 9 5 9 3 6 0
|
||||
9 5 2 6 8 5 8 7 9 1 4 5 0 7 3 2 9 6 5 4 1 5 9 1 8 3 5 7 3 4 2 5 1 1 4 6 6 6 4 2 5 5 4 9 2 9 3 0 4 0 3 0 1 2 4 8 8 8 4 9 0 7 0 3 0 1 2 6 6 7 9 3 8 0 1 7 2 4 3 1 3 4 7 3 1 8 8 1 0 3 2 9 2 5 9 7 9 6 0 2
|
||||
3 9 8 4 7 5 2 8 5 6 0 3 4 3 0 1 0 4 3 7 2 5 4 6 2 6 6 4 1 9 3 6 9 4 6 2 9 3 1 2 8 6 0 2 5 1 1 8 7 3 4 1 7 5 7 2 7 7 0 6 8 0 2 9 7 3 4 4 5 0 3 2 7 6 3 0 8 0 0 7 6 4 8 3 1 1 5 0 4 3 9 4 3 6 0 6 0 4 2 8
|
||||
9 8 9 8 8 6 5 7 6 1 6 7 3 1 3 9 5 6 6 4 8 8 0 9 0 8 9 9 4 4 6 7 0 0 2 2 3 0 6 9 3 9 2 3 2 8 3 3 8 0 8 7 1 3 4 7 6 8 8 7 9 2 7 2 5 7 1 7 8 7 1 1 8 5 0 9 2 6 2 5 2 1 4 6 5 8 7 7 2 8 1 0 4 4 3 8 8 0 7 7
|
||||
4 6 9 1 6 8 4 7 7 6 5 0 5 8 3 3 6 5 9 3 4 1 9 7 6 4 0 2 4 9 2 8 3 1 9 5 6 7 0 8 2 9 8 8 9 7 5 2 0 0 3 2 4 5 6 2 6 5 9 3 3 8 5 1 1 9 1 0 6 0 8 3 7 2 0 9 9 6 6 3 2 9 7 5 4 6 0 7 9 6 5 3 6 5 9 4 0 6 3 7
|
||||
4 2 2 8 9 5 4 0 4 1 3 9 1 9 5 4 7 4 0 1 9 7 1 1 1 5 5 4 5 9 2 8 6 8 2 3 3 1 7 7 4 5 8 4 2 8 6 7 1 1 6 4 1 8 9 5 0 8 0 2 0 6 7 2 8 1 3 8 1 2 9 9 4 6 6 1 4 4 0 4 9 8 7 7 2 5 4 8 4 7 9 0 0 0 8 1 0 2 1 9
|
||||
2 0 3 0 8 5 5 2 8 6 2 7 9 6 5 1 0 8 9 5 3 2 9 0 5 2 4 0 1 5 2 7 4 7 9 9 8 0 0 6 4 1 6 5 2 4 8 4 2 7 3 4 2 3 4 7 5 6 8 8 4 6 1 5 4 6 8 8 4 4 2 2 1 4 5 0 0 9 7 6 4 1 8 6 0 1 6 8 3 1 8 3 1 7 1 1 1 9 3 8
|
||||
4 7 3 1 3 1 5 2 0 1 8 9 2 0 3 5 6 7 7 1 9 5 8 0 6 0 5 6 6 2 9 9 2 5 6 2 5 7 1 4 4 2 6 6 9 6 3 8 8 5 6 3 4 6 4 8 1 9 0 3 8 7 6 3 9 0 7 0 2 2 9 8 1 3 8 6 2 9 6 7 7 5 0 6 9 8 9 2 8 8 4 3 1 4 2 9 5 2 8 9
|
||||
3 6 8 7 2 6 1 7 6 8 1 0 7 9 8 4 3 4 1 5 9 0 6 6 4 7 1 6 8 7 5 0 6 1 1 0 5 6 5 3 1 9 7 8 1 8 1 3 1 3 0 3 5 6 5 1 1 9 5 5 7 0 1 9 6 3 4 1 5 9 0 9 2 7 3 3 6 2 4 2 8 7 9 6 3 4 9 0 9 5 1 8 5 0 1 4 0 3 6 1
|
||||
0 3 5 5 8 7 3 2 4 5 8 3 8 3 8 1 4 8 1 9 4 8 8 5 2 9 8 8 9 8 7 4 3 1 7 8 3 6 2 5 8 9 2 7 5 1 4 4 3 6 7 0 7 1 0 5 2 2 1 6 4 1 1 0 2 5 5 3 8 9 5 0 5 4 8 6 4 6 1 1 9 4 7 4 2 8 9 0 6 9 3 0 6 4 1 5 2 3 7 9
|
||||
5 9 4 5 1 0 9 9 8 4 8 7 2 5 2 3 8 0 1 4 0 3 6 4 6 5 1 6 9 2 4 1 6 0 7 9 6 6 1 3 5 1 1 7 6 6 5 0 8 8 3 8 7 6 5 6 7 1 3 3 4 3 2 2 0 1 8 6 4 8 6 8 3 8 8 5 6 5 6 3 6 7 5 9 7 4 5 9 5 0 5 0 4 6 8 1 6 7 2 5
|
||||
4 0 2 0 8 8 6 5 2 0 7 9 9 4 0 6 6 9 9 7 8 7 1 6 7 7 6 8 0 6 4 2 9 5 9 1 6 6 0 0 9 2 3 7 4 6 2 4 0 8 2 8 3 8 5 6 7 0 6 4 8 1 6 9 7 6 6 7 1 1 3 3 9 3 6 3 0 3 9 3 6 1 1 5 4 9 5 2 0 0 4 1 8 9 7 2 1 7 3 2
|
||||
3 7 0 5 1 9 9 0 5 8 1 7 2 9 0 2 0 6 9 3 6 0 6 6 3 8 9 9 3 6 6 6 8 6 4 9 3 3 6 7 9 0 2 2 3 1 0 1 5 2 4 0 6 9 1 2 1 4 1 9 9 0 4 3 7 9 4 9 2 7 8 9 1 7 0 2 2 6 7 4 8 9 3 4 1 2 5 3 8 7 8 3 2 0 6 1 7 4 3 9
|
||||
6 4 0 5 5 0 3 4 1 8 2 4 2 8 0 8 5 9 1 9 4 1 8 2 4 9 8 9 7 0 1 9 8 0 9 7 3 7 5 5 2 8 3 7 9 7 1 1 8 9 3 7 4 6 2 9 4 7 7 6 5 1 7 3 1 8 2 8 2 4 0 1 6 4 2 6 2 7 0 8 8 2 1 0 7 4 1 3 8 6 4 5 0 3 6 3 9 2 1 2
|
||||
0 1 7 5 2 0 8 3 4 7 9 1 8 3 0 4 4 2 0 5 7 9 3 6 8 6 4 4 5 5 6 1 4 4 0 4 8 2 7 3 3 0 4 9 8 8 4 1 9 8 4 0 9 4 3 3 4 1 3 1 2 0 7 1 9 6 1 9 5 0 4 1 4 6 0 7 6 3 3 5 8 8 9 5 9 0 4 6 4 5 7 8 3 0 0 4 0 1 6 2
|
||||
4 6 6 9 5 1 9 6 8 0 3 1 4 4 1 7 0 5 3 7 0 6 4 3 3 5 2 6 0 9 0 5 1 7 1 3 4 7 5 0 7 3 1 0 7 0 8 8 1 4 1 8 6 4 9 1 4 7 7 1 5 1 2 6 9 1 5 1 9 0 5 8 7 4 2 6 3 7 3 1 3 7 2 7 3 9 4 8 5 6 5 4 3 7 9 1 1 4 8 3
|
||||
8 2 5 8 7 2 9 8 9 7 2 0 8 0 6 2 9 3 1 0 1 9 1 8 1 6 6 2 0 0 8 1 6 8 3 8 0 6 3 3 1 4 8 8 8 2 0 0 0 9 4 7 5 2 5 1 0 8 0 9 0 6 3 4 6 2 3 3 8 5 9 0 7 3 7 2 2 3 5 3 8 0 6 6 9 6 4 4 3 5 4 3 2 5 3 0 5 9 2 5
|
||||
9 7 2 9 7 0 4 5 4 3 1 4 2 5 7 8 3 0 0 1 7 5 7 5 4 4 5 4 0 7 6 7 7 3 2 7 1 0 8 5 0 3 7 8 8 2 1 3 9 5 0 4 6 2 4 8 5 0 7 4 4 9 0 4 5 6 6 4 4 5 9 0 5 0 6 4 8 9 8 7 1 7 5 5 5 7 0 5 7 5 9 8 0 3 9 9 7 9 4 2
|
||||
5 1 9 3 3 5 8 7 6 2 9 9 6 0 1 5 0 0 7 0 2 8 7 1 3 2 4 8 2 2 4 9 4 0 6 3 9 4 1 8 1 7 4 0 2 8 0 0 0 8 2 7 2 9 6 6 3 9 8 0 5 6 5 9 3 8 1 1 3 9 1 8 8 6 9 2 2 9 6 3 8 1 9 0 4 3 4 7 8 2 3 9 7 3 1 4 4 5 4 3
|
||||
4 3 6 4 7 7 1 3 8 3 5 2 6 3 2 5 6 0 4 2 1 8 2 6 5 0 0 5 3 6 7 4 2 2 4 5 1 4 3 6 3 7 7 5 7 6 8 3 6 0 9 8 1 6 1 2 9 0 4 7 9 1 6 1 4 3 6 6 9 1 2 0 6 5 3 1 6 3 9 9 0 5 0 3 2 0 5 0 0 5 7 2 7 9 2 4 0 0 2 9
|
||||
1 5 1 0 1 2 0 5 0 6 2 2 7 2 7 0 5 1 2 4 4 7 7 2 4 2 4 5 1 5 3 4 7 1 4 1 2 1 6 8 4 5 6 5 0 2 6 2 2 3 9 6 6 4 3 2 7 7 1 1 3 9 3 4 5 6 0 0 1 8 2 2 8 7 7 7 8 0 7 1 5 7 6 8 9 6 1 5 0 1 9 4 4 5 7 0 5 2 6 7
|
||||
5 1 4 5 3 7 7 6 0 7 0 1 7 5 7 6 0 1 4 8 4 2 4 2 1 3 7 7 5 2 3 8 9 0 7 1 0 2 4 4 3 7 0 1 8 8 2 6 5 6 1 8 8 0 3 1 6 5 4 9 4 8 0 7 0 6 5 2 7 1 2 5 1 6 4 9 2 4 9 6 4 8 0 0 1 1 3 4 6 8 4 8 9 8 4 2 0 0 0 6
|
||||
7 8 6 3 2 7 3 5 3 7 4 4 8 9 5 9 1 2 8 7 2 0 6 7 4 8 9 5 4 6 0 9 1 0 4 9 7 4 9 3 6 9 7 1 8 9 0 7 7 1 9 6 5 1 2 1 0 6 1 4 7 0 4 8 6 1 4 4 5 4 3 0 5 6 9 9 9 4 4 3 4 3 2 5 2 1 0 0 1 0 7 7 4 4 5 9 1 0 3 9
|
||||
3 4 6 6 1 3 1 4 1 9 4 4 0 2 1 4 5 2 3 9 9 2 3 8 9 8 7 1 3 5 8 4 7 8 2 5 8 2 8 3 4 0 0 0 0 1 0 0 5 2 9 8 0 4 1 0 3 1 3 2 9 4 6 8 5 4 9 7 9 0 6 7 8 9 2 6 7 1 8 4 2 7 1 9 4 8 4 3 4 3 4 4 0 8 7 2 6 0 8 2
|
||||
4 7 6 6 7 3 8 4 5 3 0 1 3 1 0 0 4 7 8 9 4 5 2 3 5 9 7 0 0 3 9 3 8 2 8 9 2 0 8 7 3 0 8 8 3 5 1 7 3 2 6 6 1 0 8 3 9 4 4 1 8 0 9 4 1 3 8 7 8 2 2 8 6 4 7 8 5 8 7 5 1 9 5 2 1 0 1 5 5 7 7 1 1 3 9 7 6 1 7 9
|
||||
8 6 3 8 8 9 9 6 1 7 7 3 3 4 4 6 4 8 9 1 7 1 2 4 7 6 3 6 5 7 6 3 1 0 1 5 3 8 1 0 5 7 0 6 9 7 7 3 1 0 3 0 4 6 6 3 5 2 5 2 8 6 4 0 2 7 0 2 1 7 0 9 5 4 3 2 9 8 1 2 4 7 8 8 0 1 2 6 2 7 6 5 8 7 8 1 4 8 9 7
|
||||
3 9 6 6 0 0 9 2 5 7 9 5 5 8 4 6 3 5 1 7 3 4 8 2 9 7 8 5 1 1 8 7 1 0 8 7 3 9 4 7 3 9 3 9 6 0 2 3 3 3 1 1 9 8 7 8 2 8 6 9 4 9 0 0 3 8 4 3 6 7 9 8 9 1 0 9 2 7 7 8 3 3 7 5 8 5 1 3 9 7 3 4 3 9 0 2 6 8 3 6
|
||||
7 6 0 4 3 9 4 0 3 3 2 8 6 8 4 8 5 7 5 7 1 3 1 9 3 0 5 7 4 9 0 2 3 3 6 3 4 5 3 5 2 4 9 8 9 9 5 1 9 4 9 7 8 5 3 6 3 1 0 0 3 0 0 8 3 7 6 2 9 8 0 8 8 8 7 2 8 9 2 9 9 3 5 2 7 7 7 7 6 6 4 7 2 7 3 7 5 3 4 6
|
||||
1 9 8 3 4 4 4 7 6 3 6 6 7 9 1 9 9 2 3 0 7 0 4 0 6 2 6 8 9 7 8 8 7 4 4 7 8 8 1 5 0 1 1 1 2 2 7 5 6 6 3 8 3 6 8 7 7 6 2 9 2 5 3 3 7 9 9 1 2 4 6 4 4 8 2 5 9 4 3 4 5 2 4 6 4 0 8 9 4 3 7 5 5 1 6 4 4 1 1 4
|
||||
8 5 9 6 8 4 8 4 7 0 2 8 9 9 0 8 0 9 0 9 8 0 4 6 7 7 3 9 2 9 5 0 3 6 5 8 7 8 8 1 0 3 4 8 8 2 7 4 9 2 7 1 7 6 4 5 2 7 9 9 0 1 2 8 2 8 9 2 1 2 7 3 9 5 8 7 0 2 6 8 0 6 2 5 9 3 3 7 0 2 6 4 5 5 2 0 8 2 2 7
|
||||
9 6 6 2 9 5 3 8 7 3 2 6 9 6 1 2 1 7 9 3 1 7 8 1 1 9 3 5 4 6 5 2 2 6 4 0 5 0 1 6 8 0 1 4 0 4 1 2 7 0 2 4 7 6 7 9 1 5 6 1 9 0 0 5 1 5 3 8 2 3 9 8 6 6 3 0 6 0 2 3 6 7 0 9 1 6 9 2 9 5 5 0 4 3 0 5 0 4 6 3
|
||||
4 1 4 9 7 1 9 8 9 7 2 0 7 6 1 3 9 1 8 0 2 4 6 3 0 9 5 2 9 1 7 9 8 1 6 9 4 3 7 4 0 3 7 9 4 2 1 3 9 7 1 0 7 6 7 2 1 8 1 2 9 4 5 8 9 2 9 7 1 9 5 2 6 9 9 2 2 1 2 4 7 5 5 0 6 6 4 0 7 7 6 4 7 1 9 7 7 9 9 2
|
||||
1 2 3 9 9 8 6 9 6 0 5 5 3 8 5 8 2 3 4 2 3 7 2 8 4 0 0 7 8 8 3 3 6 9 5 8 9 1 0 6 0 1 7 5 9 6 8 9 5 8 2 7 1 6 7 2 3 5 7 9 8 7 3 3 1 7 7 1 3 4 8 0 2 1 4 3 3 0 3 5 1 4 5 5 1 9 2 7 3 8 5 1 6 3 0 3 5 3 9 5
|
||||
4 1 7 3 9 8 3 5 8 4 1 0 2 8 0 8 4 4 4 0 8 5 9 8 0 1 2 9 1 5 5 6 2 7 5 7 7 1 9 2 8 7 9 5 4 2 3 3 9 2 5 2 8 7 6 4 5 8 5 8 6 8 6 0 9 3 6 7 9 0 5 5 5 9 7 3 7 3 4 3 3 3 1 7 1 4 1 6 3 9 9 0 2 1 3 8 3 5 7 5
|
||||
3 4 9 7 4 3 6 3 7 6 6 1 8 0 7 9 3 7 3 8 6 2 0 7 9 0 5 6 7 2 3 9 2 3 8 4 0 5 4 3 5 6 5 2 6 7 5 6 1 4 9 9 0 0 2 7 4 3 9 4 7 1 2 6 0 1 9 2 2 1 9 2 0 6 7 2 7 8 8 2 5 0 8 6 1 9 6 5 7 5 5 3 5 7 1 6 8 9 2 9
|
||||
3 6 3 6 8 8 0 9 9 0 7 6 3 3 0 4 8 0 8 6 8 1 8 4 4 7 8 7 6 7 2 3 1 6 4 3 9 4 2 1 1 0 4 5 9 4 5 6 1 8 6 0 6 7 9 7 3 4 4 7 8 7 1 6 1 6 8 3 6 6 3 1 6 7 2 3 8 4 4 9 3 4 0 0 1 4 9 0 4 8 6 5 1 2 2 0 6 8 6 2
|
||||
3 0 5 3 9 1 6 5 2 6 4 4 8 5 0 7 0 7 0 1 7 2 6 7 3 7 1 0 1 8 1 2 2 5 3 8 0 8 2 0 6 4 5 0 9 8 8 5 2 4 2 9 7 5 9 0 0 3 7 2 4 7 5 8 3 2 4 7 6 5 8 7 0 4 5 0 2 6 8 5 5 2 9 1 7 4 8 1 8 7 9 2 7 5 0 2 9 3 0 8
|
||||
2 2 8 5 8 4 9 9 0 7 1 9 5 3 4 6 7 0 6 8 7 3 8 8 6 1 2 0 0 3 4 0 2 0 3 8 3 1 1 6 4 3 9 5 3 6 8 9 7 8 6 2 5 7 8 3 6 2 0 7 5 9 5 9 6 7 2 2 0 7 5 9 3 2 1 7 1 8 9 6 8 2 3 7 1 5 8 3 7 7 9 4 0 0 7 0 5 3 0 4
|
||||
6 0 1 7 5 9 7 1 4 9 8 3 8 5 1 8 5 5 0 1 8 2 4 7 3 2 1 4 6 6 8 2 7 0 5 3 8 7 1 7 6 9 4 0 3 9 2 1 0 7 9 0 0 8 0 8 5 5 8 6 4 0 4 8 0 1 0 7 1 2 5 6 5 3 5 3 8 8 1 2 7 9 2 3 9 5 6 5 9 5 6 0 7 3 6 4 3 1 6 7
|
||||
4 8 9 5 9 4 8 4 1 6 5 8 7 1 0 0 5 9 6 9 4 0 4 1 2 9 2 2 9 4 5 7 6 9 5 5 6 8 8 7 0 2 5 3 7 4 2 5 0 6 8 9 9 6 1 1 3 0 1 0 6 1 1 1 9 2 2 8 6 6 1 3 9 8 7 6 2 7 4 9 5 5 6 3 9 2 3 9 3 9 2 4 8 3 0 2 5 2 8 2
|
||||
8 1 1 6 1 9 8 2 5 0 7 0 4 8 1 3 7 8 3 3 6 9 3 6 5 5 5 3 6 1 4 8 7 7 2 6 8 2 0 7 0 4 4 9 3 2 3 9 1 5 9 1 1 3 4 9 1 7 7 4 7 7 9 1 3 7 8 1 5 0 0 0 2 2 2 7 1 1 9 9 7 7 0 4 8 7 1 2 2 2 1 3 8 6 5 3 0 7 5 3
|
||||
7 2 5 0 9 6 6 1 6 7 8 5 5 6 5 8 5 0 7 6 9 4 1 9 8 3 2 2 9 2 8 9 0 8 2 8 1 9 6 9 1 1 9 2 0 4 1 0 2 2 6 4 7 5 6 3 7 2 8 1 8 8 4 6 3 2 1 2 3 7 7 0 5 8 0 7 3 8 3 0 9 7 9 1 8 2 7 4 0 2 6 0 1 6 1 7 2 0 0 0
|
||||
7 3 0 2 2 0 5 1 0 0 1 5 6 9 0 3 4 8 9 1 6 8 3 0 6 5 2 6 7 5 2 3 5 5 3 6 2 4 0 7 1 9 2 3 7 8 4 8 1 1 5 6 9 4 1 5 4 6 5 5 6 2 0 1 6 8 3 8 1 8 8 9 8 6 9 9 3 2 4 9 5 5 3 3 7 6 8 0 3 8 0 4 9 1 8 5 8 0 0 8
|
||||
7 3 1 1 9 9 5 8 9 2 2 3 9 6 4 6 8 6 8 1 8 5 1 7 4 5 5 8 4 4 3 1 9 2 1 1 7 3 9 4 6 4 6 6 3 4 0 3 4 3 2 4 2 0 2 4 4 9 5 0 6 8 6 6 0 8 4 1 5 4 6 5 5 9 7 8 2 9 2 0 1 2 3 0 6 8 3 5 0 4 4 3 3 5 9 2 3 7 5 9
|
||||
6 8 5 2 4 7 2 4 7 5 8 1 2 4 4 1 6 9 5 9 4 5 5 8 3 1 8 1 3 7 6 8 3 1 3 0 1 0 1 5 0 7 0 9 8 1 7 5 6 2 9 5 0 3 5 5 9 9 7 2 5 1 2 7 7 6 5 3 1 4 1 5 0 8 1 3 7 3 9 4 2 0 3 8 8 4 6 4 7 5 1 5 4 0 2 7 2 0 4 1
|
||||
2 8 6 9 2 4 1 6 5 4 4 4 2 4 2 8 9 4 5 4 8 2 2 9 9 3 2 5 5 7 1 2 9 1 8 0 0 0 6 2 0 5 8 0 5 5 9 3 3 2 0 6 7 5 4 7 7 8 8 9 5 0 7 5 5 7 9 0 4 3 7 3 7 1 6 3 1 1 1 0 3 1 9 7 6 4 7 7 9 6 8 4 8 6 9 3 4 0 9 0
|
||||
8 5 3 2 1 7 2 0 6 2 4 2 5 6 6 1 6 4 4 1 2 7 7 2 1 6 9 1 7 2 7 2 0 1 2 3 5 2 9 6 2 5 5 8 0 0 9 9 9 7 4 3 3 9 8 2 5 0 6 6 0 0 3 5 0 2 3 1 4 3 4 5 8 3 9 0 1 1 3 3 4 7 9 8 2 8 5 2 3 4 7 4 0 9 0 5 9 5 9 9
|
||||
2 8 8 1 0 8 3 1 3 9 5 3 3 6 4 9 8 8 9 0 3 6 1 9 3 8 8 8 4 0 2 0 2 1 5 1 4 5 6 6 4 0 2 6 2 5 6 7 0 5 9 0 3 6 5 4 8 6 7 0 9 3 5 6 7 9 8 5 0 2 3 2 1 4 4 6 1 0 3 4 8 3 7 5 4 4 5 0 1 5 8 5 5 0 6 2 9 3 0 1
|
||||
1 2 8 7 0 9 3 5 9 2 1 1 8 0 4 6 8 3 8 1 1 7 5 0 3 4 0 5 2 6 7 8 4 7 2 0 7 8 3 9 4 1 3 2 6 9 5 5 3 2 2 0 9 1 6 4 9 9 7 0 8 4 3 6 5 4 8 2 5 4 2 1 7 3 7 9 6 8 4 3 8 6 1 9 1 5 5 9 9 1 0 1 6 5 3 8 3 2 5 6
|
||||
9 9 5 4 0 3 4 7 9 9 0 7 8 7 2 8 5 6 4 9 6 4 5 5 8 7 7 0 1 3 3 1 6 6 6 8 7 0 8 9 0 9 0 6 1 0 5 5 3 9 3 5 2 1 8 0 4 6 1 1 8 5 4 8 8 4 0 9 3 2 2 9 1 0 8 2 6 7 7 7 3 7 3 1 9 5 9 8 6 7 8 0 1 8 2 5 1 1 9 5
|
||||
4 7 7 6 1 5 7 1 9 5 8 7 2 7 9 6 9 5 0 7 7 9 3 7 4 8 1 3 4 2 7 5 4 4 5 4 7 9 2 0 5 9 9 1 7 7 6 9 4 5 7 9 0 2 6 7 0 3 5 1 9 6 9 4 1 6 8 5 9 0 1 1 5 8 7 8 9 6 8 8 1 4 0 7 8 9 0 1 1 8 7 0 0 6 4 6 0 4 3 1
|
||||
7 2 3 5 3 9 6 8 6 0 8 1 8 1 9 1 6 1 8 9 6 6 9 7 3 0 1 6 4 9 1 6 3 3 7 7 0 8 0 6 1 7 4 3 5 7 4 7 1 3 3 0 4 0 0 2 4 8 6 0 9 8 6 0 6 9 5 9 4 4 5 8 2 1 4 0 2 8 3 6 3 3 1 1 9 8 1 8 7 7 6 2 5 8 3 6 4 1 1 4
|
||||
0 6 9 4 6 2 4 1 8 8 6 6 0 2 0 0 9 0 0 8 5 2 2 7 9 2 8 5 1 7 2 7 6 5 7 4 1 2 4 2 7 8 6 6 0 5 5 7 0 8 9 0 6 9 1 7 9 3 3 3 3 9 4 0 3 9 4 1 7 3 2 8 9 6 2 5 5 5 3 4 9 8 5 8 8 6 9 1 1 2 1 1 3 0 9 4 4 0 7 2
|
||||
4 9 8 9 2 7 5 2 2 0 3 7 5 5 1 6 1 2 8 2 4 9 9 7 0 4 6 4 6 1 0 2 7 7 5 1 4 7 9 1 4 9 3 2 2 8 4 2 7 9 9 5 3 1 3 6 4 2 1 1 4 9 6 9 6 1 6 5 5 8 3 9 9 6 9 7 9 7 0 5 3 7 3 5 3 3 2 2 9 9 6 0 9 1 8 5 6 9 9 2
|
||||
3 1 3 3 6 8 8 4 1 0 4 2 1 8 9 7 2 8 0 9 6 8 2 0 2 5 0 5 7 0 6 0 0 1 0 7 6 0 9 4 3 1 6 0 3 9 2 3 2 2 3 6 7 1 3 2 9 3 7 0 3 7 0 2 2 1 6 4 2 3 6 0 9 7 8 4 9 1 9 2 4 7 9 6 6 8 5 4 8 6 3 6 3 2 9 0 5 3 9 1
|
||||
7 4 3 2 2 6 5 6 0 3 0 5 6 7 9 3 0 9 7 3 9 5 6 8 1 9 2 3 1 2 9 2 3 7 7 4 0 3 1 8 1 5 2 2 9 1 2 1 2 8 0 8 4 3 4 6 6 2 0 3 1 6 9 1 7 4 1 8 6 5 9 5 1 8 5 5 5 2 4 8 0 0 7 5 3 9 1 5 1 7 4 6 3 6 9 6 2 6 0 5
|
||||
101
03-MatrixAddition/matrices/matF
Normal file
101
03-MatrixAddition/matrices/matF
Normal file
@@ -0,0 +1,101 @@
|
||||
100 100
|
||||
5 5 3 7 1 8 3 5 2 6 6 8 3 9 8 3 5 1 2 9 0 1 2 5 2 4 4 7 0 0 9 0 8 2 7 2 1 1 4 8 6 7 2 8 1 7 0 3 6 3 3 4 2 5 6 1 0 6 5 8 2 5 1 0 2 6 4 2 8 5 9 4 8 2 2 2 8 6 2 7 1 2 1 7 1 4 7 4 6 4 3 8 1 5 7 6 0 7 7 7
|
||||
8 9 1 2 1 7 3 8 8 0 5 5 0 7 7 0 6 8 8 5 8 8 9 6 5 6 4 6 9 8 1 0 1 1 2 9 4 1 6 0 0 2 2 3 3 1 9 4 9 7 7 2 7 5 3 5 4 3 0 8 7 6 4 9 3 5 4 6 4 5 6 6 4 1 7 9 1 6 2 4 8 9 9 6 8 2 3 3 0 9 3 0 4 4 6 2 9 4 0 5
|
||||
0 9 5 6 6 1 9 6 5 7 9 2 0 3 1 2 6 4 3 8 6 1 7 6 3 6 4 9 0 0 4 0 5 3 7 3 1 9 0 1 2 3 1 4 5 3 7 9 7 0 0 0 6 4 5 9 2 2 6 5 3 1 7 8 4 9 5 4 6 0 8 8 1 7 2 9 7 2 6 5 7 8 0 1 1 3 5 2 8 6 1 9 4 2 4 9 4 7 6 1
|
||||
0 9 1 3 7 1 4 3 3 0 6 7 1 0 1 6 5 2 3 7 8 9 8 7 3 0 9 2 2 1 4 5 3 0 9 1 7 0 9 4 7 2 9 0 7 9 4 1 2 8 1 4 4 7 0 0 6 0 8 1 2 7 8 9 4 6 0 6 2 7 8 2 2 0 9 6 7 3 7 1 7 6 0 1 0 2 9 4 7 5 9 3 1 9 7 2 9 8 3 9
|
||||
3 2 2 6 4 4 1 9 2 3 9 3 7 8 3 8 8 6 1 6 1 0 2 0 6 1 0 2 7 5 3 8 4 6 0 9 5 2 5 5 2 7 4 9 1 2 1 0 7 1 5 4 3 5 0 6 4 5 0 3 7 9 4 3 5 8 8 3 7 3 7 8 8 1 4 1 2 1 4 5 5 4 2 3 0 9 5 8 9 9 2 7 0 0 3 9 8 4 7 6
|
||||
2 6 1 2 7 7 0 8 1 9 9 4 9 2 3 0 1 6 5 6 2 1 6 8 7 6 3 7 7 8 1 1 2 0 0 8 5 2 7 9 9 4 1 8 6 7 4 9 7 0 4 2 9 0 9 8 2 7 2 9 4 7 9 6 1 1 2 2 4 3 2 3 9 0 9 5 8 2 9 4 8 8 8 4 0 6 8 2 9 5 9 2 2 0 0 7 7 8 0 8
|
||||
9 9 6 7 3 0 1 1 5 4 1 0 0 6 5 7 6 9 7 1 7 7 1 0 7 6 1 8 7 8 5 9 3 8 8 0 0 8 1 6 0 4 0 9 6 4 5 4 1 8 4 6 6 3 5 0 1 5 5 9 1 0 4 9 5 4 1 1 2 9 5 4 0 4 6 8 4 9 7 0 9 9 9 8 0 6 7 3 2 7 7 6 9 0 4 7 2 1 8 6
|
||||
2 2 9 3 0 2 1 4 0 1 5 3 5 4 8 2 7 4 8 8 3 4 3 7 9 4 3 5 7 0 9 4 9 9 9 6 3 7 3 0 0 0 6 4 1 9 9 7 9 8 6 5 2 2 6 0 9 0 6 7 1 0 1 7 4 7 2 9 9 7 1 1 4 6 9 2 6 9 3 6 5 6 4 2 4 1 8 0 0 8 6 3 6 9 9 8 9 0 6 0
|
||||
5 0 6 5 2 8 6 0 8 8 0 6 0 0 7 4 9 9 8 0 9 7 7 2 8 8 3 4 8 4 1 1 4 4 7 9 8 0 3 5 6 9 3 7 5 2 6 9 5 6 0 1 9 9 4 7 2 0 6 7 8 1 5 8 1 6 4 5 7 0 6 6 3 6 6 7 7 0 8 9 1 8 5 9 1 0 1 3 6 5 5 1 1 6 8 2 1 4 9 0
|
||||
2 3 0 5 1 3 0 9 1 1 6 6 2 8 8 9 1 8 5 1 1 0 9 4 9 5 9 2 3 7 1 8 5 8 3 5 3 7 2 0 4 2 5 5 5 2 1 7 6 7 9 3 2 7 5 2 1 3 8 4 1 7 9 0 6 6 5 4 6 3 0 9 0 8 4 8 0 8 0 0 7 9 6 9 4 1 1 9 2 9 7 2 3 4 6 8 0 4 5 7
|
||||
3 0 9 8 2 7 3 3 4 4 4 8 3 4 9 4 3 5 3 2 4 1 0 1 0 4 9 2 6 9 8 4 8 3 7 4 3 8 0 4 9 5 4 2 1 2 7 8 1 1 5 7 2 7 0 4 4 6 9 5 0 6 7 6 7 6 4 3 9 7 6 4 4 9 0 2 7 2 5 8 3 5 0 4 2 5 0 5 6 9 3 2 7 3 9 1 2 5 0 0
|
||||
9 9 7 4 3 8 5 5 9 8 6 2 7 2 1 0 2 5 9 5 5 6 4 1 4 0 1 1 1 7 4 5 6 2 0 5 3 7 1 2 7 4 7 7 2 7 8 8 2 0 7 6 6 7 6 5 0 5 6 2 5 3 0 2 3 7 0 7 3 7 9 0 4 6 2 9 0 4 9 0 8 8 2 1 0 5 2 1 9 6 5 2 9 0 2 5 3 5 3 5
|
||||
3 5 3 2 2 9 3 2 9 4 9 1 2 8 9 3 1 8 9 0 7 3 5 5 9 5 3 3 0 1 2 0 4 8 7 3 3 3 6 7 6 7 5 8 4 8 0 4 6 8 9 7 3 4 3 0 6 4 2 8 0 5 2 0 8 9 1 2 1 1 1 0 1 5 4 6 5 5 4 9 9 9 9 2 2 3 8 6 4 7 8 8 9 2 4 1 3 1 9 0
|
||||
0 9 2 3 5 3 5 5 4 4 2 2 5 6 0 4 2 7 8 9 1 8 2 1 0 3 4 6 2 5 8 9 1 1 1 3 1 8 4 7 4 8 2 2 4 9 5 9 2 1 2 1 7 8 2 4 9 1 6 1 6 8 0 0 2 6 0 1 4 2 2 7 4 6 2 3 8 3 0 4 9 7 1 5 5 0 0 0 4 7 3 7 9 3 4 6 5 6 8 4
|
||||
1 2 2 9 2 4 3 0 9 7 4 3 1 3 0 1 2 9 7 5 9 8 8 1 7 1 9 6 3 1 2 8 7 0 0 5 5 6 1 6 6 8 8 9 2 8 6 5 7 0 7 1 0 9 6 1 1 7 8 6 6 7 4 6 5 1 4 0 6 0 8 9 7 6 4 6 8 4 1 0 5 2 5 5 3 7 9 8 6 2 1 7 5 3 2 5 0 5 4 5
|
||||
0 0 0 5 1 5 6 1 9 0 4 7 7 5 8 9 8 6 9 3 6 3 8 3 3 1 2 0 7 3 0 7 0 5 9 2 8 3 0 5 4 0 8 8 1 7 5 7 0 9 3 1 4 8 3 0 0 5 9 7 5 6 3 2 0 9 4 9 4 5 3 1 2 6 5 6 6 2 9 3 6 4 1 7 5 9 4 1 4 5 4 0 5 4 0 9 7 5 8 5
|
||||
5 1 0 9 9 7 0 7 9 6 8 7 2 8 4 0 5 0 7 3 9 8 0 0 1 9 3 5 8 7 4 8 8 2 4 6 4 6 0 9 4 5 2 2 5 7 9 6 1 1 3 2 9 9 2 9 7 7 7 6 9 6 4 5 7 3 0 1 8 7 6 5 4 4 4 3 1 2 1 1 9 2 2 6 5 1 2 3 5 2 6 3 0 5 1 1 4 1 3 0
|
||||
1 5 2 2 5 5 8 6 9 0 3 1 0 9 8 4 4 0 0 2 7 3 4 8 2 3 4 3 9 0 4 4 1 7 4 3 6 2 6 0 7 0 8 2 6 8 4 3 8 1 5 3 4 9 5 1 2 5 9 9 8 1 5 6 6 4 8 4 1 6 7 6 5 9 3 5 7 2 2 3 8 8 7 0 3 9 0 4 3 9 9 5 8 8 4 1 8 2 7 8
|
||||
2 1 4 2 8 1 4 6 2 7 1 6 2 6 2 9 4 3 4 3 6 1 1 5 2 2 1 2 8 0 1 8 4 2 5 3 1 3 8 8 6 3 7 4 0 6 9 9 1 0 4 6 9 7 6 8 1 9 4 9 7 4 9 2 9 9 3 7 9 7 2 8 7 8 5 0 1 5 6 3 1 2 2 5 3 9 9 8 7 3 6 1 7 4 5 3 3 1 8 6
|
||||
4 0 5 3 7 9 5 8 6 2 9 9 4 9 3 6 4 1 6 1 2 1 1 5 9 9 2 3 0 8 5 2 7 8 4 4 9 4 0 8 2 8 5 2 0 1 8 3 5 1 2 2 9 7 9 5 3 1 7 4 6 3 9 9 8 3 8 5 5 7 5 7 9 2 2 3 1 0 0 6 9 9 2 1 1 7 1 5 3 8 3 0 0 7 3 1 8 8 4 0
|
||||
9 0 8 5 2 7 4 4 1 6 5 0 1 5 4 9 2 2 7 1 3 2 4 0 2 5 0 2 5 0 4 1 4 5 0 7 3 8 6 2 5 7 5 3 1 4 0 4 5 2 1 7 9 0 2 1 9 1 8 0 7 5 1 2 6 5 9 2 3 5 6 0 7 4 5 3 1 6 0 7 0 4 4 7 0 4 8 2 4 1 6 1 1 7 5 5 1 9 6 9
|
||||
1 6 1 9 4 2 0 5 3 4 9 8 8 3 3 1 0 4 5 1 9 0 6 9 5 8 4 6 3 7 1 5 5 0 6 7 3 1 6 6 3 4 4 4 2 8 9 2 4 7 7 6 8 0 9 9 6 3 8 5 4 1 1 2 0 9 7 4 7 8 0 3 1 6 0 9 9 4 3 5 1 3 3 4 1 9 1 2 4 2 7 7 9 3 0 8 2 0 6 4
|
||||
7 5 2 4 5 2 0 9 8 8 3 5 3 5 8 0 1 7 3 8 3 8 9 4 8 4 2 8 2 2 2 9 8 5 3 7 3 1 5 7 4 8 5 3 2 1 6 8 6 4 8 9 9 5 4 8 5 1 9 9 8 6 9 6 7 1 4 9 0 7 8 7 6 0 9 3 1 8 5 2 2 1 1 3 5 6 3 0 4 3 4 7 5 7 4 0 3 6 9 6
|
||||
0 0 4 2 2 0 6 6 8 1 8 4 1 9 5 0 3 0 3 3 8 9 8 5 9 7 7 6 5 8 5 8 9 4 7 4 1 2 6 6 6 9 6 2 0 0 7 4 7 0 2 4 0 1 7 8 2 2 9 2 5 2 5 9 4 8 5 5 6 7 4 3 2 8 3 3 2 3 7 8 4 9 6 3 3 8 4 1 8 4 0 1 5 1 9 8 8 5 9 5
|
||||
6 3 5 0 8 5 4 2 7 3 5 8 6 9 6 4 2 2 1 8 9 8 8 8 4 5 0 8 7 2 6 3 2 9 7 7 7 4 9 6 9 2 2 8 0 2 7 4 7 2 6 6 3 0 2 3 1 6 6 2 0 6 3 1 4 3 5 4 5 7 9 3 2 4 4 3 0 6 1 1 9 3 5 0 1 1 4 3 0 2 5 2 2 3 2 9 0 4 8 9
|
||||
2 6 1 1 0 6 2 0 9 3 3 2 8 9 7 6 8 5 6 5 9 5 7 6 6 6 9 1 2 8 0 9 2 4 1 8 6 4 4 8 9 7 3 1 0 9 7 7 4 5 6 6 3 9 0 7 2 3 4 4 5 7 2 2 3 2 7 3 6 0 9 9 0 4 1 8 2 2 8 7 8 3 5 2 6 5 4 5 5 7 0 9 3 2 8 5 5 6 3 9
|
||||
5 7 5 0 1 9 3 0 2 8 5 3 0 3 7 5 6 7 1 2 4 8 5 1 2 0 2 1 1 1 8 9 4 9 7 7 0 2 8 4 2 0 8 6 9 7 7 0 5 6 4 2 1 6 0 1 2 6 3 8 8 4 1 0 9 4 0 2 7 7 9 1 6 6 6 6 6 8 7 3 9 9 7 8 5 3 7 3 0 2 0 5 5 4 0 0 5 9 3 3
|
||||
0 9 9 3 1 1 1 2 7 2 6 5 3 9 6 6 1 6 8 0 4 8 2 2 0 5 9 5 0 2 2 5 5 0 2 9 7 6 6 5 1 1 6 6 4 6 6 6 6 8 1 1 4 7 7 7 7 3 3 4 9 7 7 4 2 8 5 1 9 8 8 9 5 5 9 9 9 3 7 1 5 0 0 1 4 1 2 8 4 4 3 7 2 6 5 4 8 3 9 5
|
||||
3 8 8 5 3 6 5 3 5 7 7 2 6 3 7 1 1 5 1 7 4 3 6 7 3 4 7 3 1 9 8 1 3 9 7 3 9 7 6 2 2 4 7 2 2 0 4 8 4 5 3 7 7 9 1 2 4 9 7 9 9 6 3 6 8 7 9 7 3 5 7 9 5 8 8 2 5 4 2 7 4 6 5 7 5 9 4 5 8 2 9 5 4 8 0 5 7 5 0 4
|
||||
6 8 3 7 4 5 5 3 7 7 1 4 8 2 0 0 0 7 7 8 6 6 7 0 0 5 0 3 7 2 5 7 1 3 3 5 9 4 6 4 5 5 2 7 2 4 6 3 7 8 8 0 0 8 9 1 4 1 8 5 6 4 1 3 2 0 2 7 4 2 2 0 4 2 8 9 4 1 3 0 5 5 7 7 1 7 2 5 7 9 9 1 9 5 3 8 1 3 3 8
|
||||
4 2 7 8 3 5 2 8 0 1 7 8 0 0 7 5 4 9 6 8 7 9 6 9 0 7 1 7 3 7 2 5 7 8 9 9 6 1 9 8 3 3 4 2 6 5 2 7 5 6 5 3 5 5 3 1 6 6 8 4 8 7 3 3 4 6 0 4 8 5 1 7 8 7 7 6 3 2 9 0 8 7 4 2 9 6 7 7 2 3 2 4 8 7 4 2 5 7 4 0
|
||||
9 6 9 8 9 0 7 7 0 5 3 1 6 7 4 4 2 4 0 1 0 2 7 1 9 4 5 6 0 2 7 8 9 8 2 6 9 0 6 6 2 8 1 3 1 4 3 8 2 0 8 3 8 9 9 3 0 0 1 2 6 4 5 8 0 0 6 5 4 5 9 8 6 9 8 2 0 7 5 6 3 0 0 9 8 5 3 3 0 8 2 9 8 2 3 3 3 5 2 3
|
||||
0 6 9 9 0 4 2 2 5 4 1 4 1 1 8 0 1 2 6 8 2 1 3 7 4 7 5 2 5 4 6 8 4 8 9 3 1 4 7 8 3 1 8 8 6 7 0 3 1 5 5 9 1 7 3 2 5 7 0 8 2 4 0 8 5 5 0 8 1 8 6 9 5 1 5 4 1 9 5 4 2 0 7 1 7 4 8 2 6 9 6 8 3 2 1 8 6 4 5 1
|
||||
0 5 4 0 6 2 8 3 0 0 1 5 6 4 1 0 3 7 2 1 0 8 2 6 8 6 7 0 2 0 5 1 6 7 9 6 9 6 9 5 1 7 1 0 1 8 6 6 9 5 8 1 8 2 9 1 7 3 7 2 1 8 2 7 0 8 3 7 4 6 1 6 5 2 0 3 0 9 6 0 8 8 6 2 0 4 5 2 8 6 9 6 8 2 3 7 5 3 2 2
|
||||
6 0 2 3 6 4 9 3 3 0 7 8 2 5 8 2 2 4 2 1 4 3 2 0 5 8 0 1 9 8 2 5 6 5 4 9 3 9 5 1 7 5 7 2 3 8 6 0 8 0 0 0 8 5 3 6 4 0 8 5 4 9 4 2 9 4 3 3 2 4 0 5 4 2 4 4 9 0 8 4 3 9 4 6 9 6 2 6 9 5 1 4 6 5 0 8 3 9 4 3
|
||||
0 1 2 8 0 3 3 8 7 1 1 0 9 0 1 1 7 1 1 5 1 5 0 3 5 1 8 2 4 0 6 5 0 9 7 0 1 5 6 1 0 3 2 9 0 3 0 0 1 9 5 6 0 2 0 8 2 4 1 5 0 1 6 8 3 8 4 8 4 1 9 7 4 6 4 3 2 7 9 9 6 1 5 6 8 2 8 9 0 7 6 1 2 4 9 4 7 4 6 5
|
||||
6 8 0 3 8 0 6 6 5 1 1 6 7 6 2 1 7 0 7 0 8 9 5 8 6 3 4 0 9 5 2 9 8 5 4 7 5 1 3 1 3 5 0 8 1 9 1 2 8 4 8 7 2 3 5 8 9 3 7 8 5 3 5 7 1 3 9 6 0 1 1 1 6 4 2 6 1 3 4 5 0 6 5 2 5 7 3 0 5 9 4 5 4 3 1 8 9 5 8 0
|
||||
4 6 7 8 9 3 8 7 2 2 9 1 7 4 9 4 8 8 8 5 6 6 4 2 3 3 8 6 7 0 8 2 4 6 2 9 2 6 9 1 9 8 7 6 5 3 1 4 9 9 5 5 2 3 5 4 0 7 4 3 8 6 7 1 6 3 7 0 4 7 7 1 8 4 3 9 0 7 2 8 2 0 2 7 0 2 9 8 3 4 8 9 1 6 6 4 0 1 2 5
|
||||
7 9 5 9 3 8 2 1 4 0 4 0 3 8 0 0 5 2 2 9 2 1 9 4 3 7 1 8 0 5 4 8 8 9 8 6 3 9 3 7 2 0 0 9 7 2 7 6 2 6 9 7 0 8 6 9 7 2 9 1 6 3 4 3 5 6 7 6 7 9 5 9 4 1 3 0 1 0 2 9 0 3 4 1 7 8 2 4 8 2 4 4 3 5 6 7 8 7 2 6
|
||||
3 2 4 1 7 1 5 4 0 0 6 8 1 1 9 0 9 0 7 5 3 4 5 2 0 6 2 6 0 8 8 4 7 0 2 4 1 0 7 5 9 9 1 4 3 8 5 2 6 0 3 5 0 6 1 7 9 1 3 5 3 8 1 9 0 4 7 8 1 8 0 4 7 8 1 5 8 2 9 9 6 0 2 9 6 2 5 1 5 8 1 9 9 6 6 7 3 8 2 7
|
||||
0 5 9 2 3 4 1 0 2 1 1 4 1 0 4 3 7 3 2 8 2 5 5 8 1 6 7 0 0 8 5 5 6 6 3 4 5 8 6 3 5 8 5 8 6 1 4 7 4 0 9 8 4 3 8 6 7 0 6 1 1 4 7 9 1 9 2 4 9 7 7 9 2 9 7 4 9 1 6 7 4 9 1 7 1 2 3 0 2 0 9 3 9 1 1 7 5 1 4 0
|
||||
2 2 8 7 3 4 2 9 8 7 6 8 2 3 3 2 0 0 8 4 8 9 2 1 9 9 4 8 9 1 6 9 0 4 5 9 1 3 7 6 1 1 7 0 2 0 3 9 0 8 6 8 0 6 3 7 4 6 5 6 2 7 4 6 1 1 6 5 1 8 7 2 8 9 2 0 7 1 0 2 5 4 3 1 6 0 2 4 6 8 1 5 4 5 8 1 2 4 9 3
|
||||
6 9 9 4 1 0 6 1 8 5 9 5 7 5 9 5 7 3 2 5 7 1 4 5 6 1 6 8 1 8 2 5 5 6 6 4 7 8 3 0 8 9 6 7 8 3 3 3 8 2 8 1 5 1 1 3 8 6 6 4 4 4 4 9 6 8 2 5 0 5 7 2 8 4 1 0 4 2 8 4 4 3 1 9 6 9 0 5 5 5 0 6 7 2 4 2 8 0 7 4
|
||||
6 6 4 5 7 0 0 9 6 8 0 0 6 6 0 9 8 1 3 1 2 0 0 5 7 0 3 1 5 4 7 1 2 3 2 1 1 2 2 1 4 5 4 1 7 4 1 6 1 4 3 7 8 2 8 9 1 1 0 8 4 7 1 5 0 1 9 0 7 4 7 5 5 0 2 3 7 5 1 7 6 4 0 7 4 2 3 4 3 3 7 8 1 4 8 4 5 2 9 8
|
||||
0 0 9 1 0 5 5 6 0 2 5 3 4 6 9 4 3 7 1 0 3 5 0 0 7 9 1 8 3 9 0 4 1 5 1 1 3 4 8 7 1 4 2 8 3 9 3 5 9 7 3 3 0 8 7 8 3 3 5 9 9 3 5 0 6 8 5 8 4 3 5 7 5 3 3 5 7 4 9 6 7 5 1 1 4 2 1 2 2 4 1 5 8 2 9 4 8 6 8 5
|
||||
0 1 2 3 7 3 5 1 7 7 6 9 5 6 3 6 4 6 2 3 6 5 8 2 6 7 8 7 1 6 0 8 6 5 7 0 3 4 4 4 6 2 1 4 4 1 0 8 2 8 4 8 9 5 2 5 1 2 9 2 2 2 1 4 2 6 3 7 7 4 9 4 6 8 5 1 8 1 8 1 6 3 6 8 8 4 3 0 6 2 0 6 1 7 9 5 2 7 7 9
|
||||
5 4 4 3 3 0 2 7 2 5 7 1 6 2 4 3 0 4 1 3 7 4 5 7 0 9 8 6 8 2 0 0 8 4 7 9 2 3 5 1 8 9 4 0 7 8 0 2 6 5 4 4 2 3 3 3 7 3 2 2 2 5 0 0 3 4 0 3 3 4 9 4 1 4 8 7 6 8 0 1 0 4 0 5 9 3 5 2 0 0 7 9 4 0 6 5 8 1 7 8
|
||||
8 5 7 3 4 0 8 5 1 6 2 1 4 3 6 6 4 3 6 4 7 5 8 7 3 1 1 1 8 1 8 2 1 9 7 1 7 7 6 1 6 4 9 7 8 8 5 7 1 2 1 7 2 9 3 5 6 5 0 3 9 7 8 8 8 0 2 7 8 1 0 7 6 0 1 7 8 1 3 8 2 4 9 7 0 4 5 8 6 0 0 0 8 6 5 1 9 0 2 2
|
||||
9 9 7 7 7 6 8 3 3 5 9 9 4 4 8 5 6 0 3 6 9 1 3 4 8 7 1 6 8 7 6 0 4 8 4 6 0 9 1 2 2 0 6 1 1 0 9 5 4 2 5 0 7 1 1 1 8 5 0 3 6 3 9 5 6 0 6 6 5 4 7 5 0 0 4 0 3 6 4 0 6 6 2 2 4 8 1 7 8 7 1 7 1 0 2 8 0 2 9 0
|
||||
2 4 5 1 1 6 9 4 3 6 5 0 4 7 7 0 4 3 4 6 0 5 6 1 0 0 0 3 0 9 2 3 0 2 6 4 8 2 1 4 0 1 3 2 3 1 8 6 0 8 3 9 9 9 7 9 0 5 7 3 2 0 0 2 9 7 1 7 6 8 9 5 4 4 0 1 8 1 2 7 1 9 1 2 6 4 1 5 5 5 5 6 3 1 8 1 3 0 9 2
|
||||
4 4 5 4 1 4 4 1 7 1 6 6 0 4 8 1 7 6 8 6 6 2 0 6 0 4 5 2 6 8 2 4 1 6 2 8 9 6 6 8 2 1 6 3 3 5 3 9 4 4 7 6 6 7 0 4 4 7 7 9 4 2 9 1 2 2 8 6 2 7 9 9 9 7 3 7 1 8 3 7 7 6 3 9 7 5 5 8 6 2 2 0 3 1 2 5 0 9 1 4
|
||||
0 6 1 0 9 4 6 0 7 0 9 7 4 0 8 3 0 5 8 4 7 9 3 0 6 0 1 4 3 7 8 9 3 9 7 8 0 1 2 9 2 3 3 1 9 2 2 6 8 4 2 3 4 9 8 7 1 5 5 0 2 1 0 2 1 0 5 8 0 4 3 3 2 6 3 4 3 8 1 4 1 7 4 6 7 2 9 3 7 5 2 0 7 6 4 6 1 4 6 5
|
||||
0 0 9 1 0 6 3 4 0 7 3 9 0 6 4 0 3 1 1 3 1 0 3 4 4 0 8 6 8 5 5 6 7 9 1 7 6 1 9 3 6 6 8 5 9 3 0 1 4 2 3 5 5 6 1 9 2 0 3 8 5 5 7 0 0 8 2 5 1 3 9 1 9 5 4 9 4 6 8 4 9 6 5 9 2 3 9 3 8 1 9 7 8 5 5 8 4 4 8 0
|
||||
9 3 0 8 7 3 4 0 3 9 9 1 4 6 4 8 0 8 0 8 0 1 9 2 8 0 9 8 7 1 7 0 7 9 0 2 8 3 0 9 9 0 2 3 9 8 6 0 1 9 7 2 5 5 8 6 7 8 5 2 6 8 0 7 8 1 6 1 9 5 7 7 9 0 9 1 8 5 2 9 1 6 6 9 7 5 3 5 1 5 8 5 1 6 7 5 8 4 2 6
|
||||
8 2 6 9 9 5 8 8 4 6 3 8 9 4 9 9 2 8 6 5 2 8 0 0 2 8 9 2 5 2 9 1 8 9 3 8 8 4 0 5 2 0 5 8 7 1 7 5 4 0 0 6 2 3 5 7 2 3 3 8 9 3 9 9 9 0 2 3 7 9 8 2 9 8 7 2 3 2 5 9 0 7 6 1 7 6 5 0 6 5 3 4 6 0 2 3 2 6 1 0
|
||||
6 4 2 6 7 0 5 6 0 2 8 7 9 9 5 7 4 7 5 4 1 5 5 4 6 7 4 7 0 9 4 6 6 5 7 6 8 7 9 7 8 0 5 0 1 2 7 0 5 0 6 3 9 4 2 4 4 5 4 4 6 4 1 0 8 5 5 3 0 3 6 3 2 2 0 1 8 6 8 0 2 2 4 9 6 7 8 9 2 0 8 8 0 7 4 0 8 5 1 2
|
||||
8 6 1 0 5 0 1 9 1 0 1 2 4 2 5 6 3 9 1 6 8 6 7 1 0 2 2 1 9 2 1 8 8 0 8 0 3 8 3 4 2 9 1 9 1 8 5 5 4 0 1 9 9 1 6 2 3 0 6 9 7 4 7 5 7 9 3 6 3 1 9 0 1 4 8 5 2 5 5 7 7 6 3 8 0 0 7 8 8 4 7 0 7 0 8 9 2 2 2 4
|
||||
2 4 9 2 8 7 9 8 0 3 0 9 0 5 3 6 7 2 0 4 6 0 0 6 4 9 3 7 5 8 7 0 5 7 8 3 4 8 3 4 7 4 8 9 8 2 8 3 0 4 6 9 1 8 0 8 3 2 1 0 7 9 3 6 2 0 3 4 4 3 4 3 4 0 9 1 0 9 2 7 5 3 1 3 6 5 1 9 6 5 6 9 9 7 5 9 5 6 5 1
|
||||
0 7 8 9 3 3 3 8 0 5 4 0 3 1 8 6 0 8 6 0 7 3 6 6 5 8 4 7 9 7 8 5 8 3 6 5 1 2 0 4 1 4 5 0 6 6 9 6 9 3 5 1 5 3 0 5 7 7 9 4 0 0 7 9 2 3 7 7 3 4 8 3 0 5 0 8 9 3 8 2 7 6 3 0 8 2 2 5 1 9 7 6 4 6 7 3 2 7 9 2
|
||||
8 5 9 5 6 7 4 8 6 4 3 9 7 3 8 6 1 3 0 8 8 3 0 6 9 5 5 1 3 5 0 8 9 2 0 0 7 2 7 7 0 6 2 8 3 6 9 6 4 8 0 9 8 8 2 1 9 4 1 4 0 8 0 7 0 7 5 3 9 2 9 8 6 5 2 0 3 9 8 6 2 0 0 8 9 5 2 4 9 0 9 3 1 8 1 3 2 6 9 5
|
||||
9 7 4 4 4 1 1 5 7 8 1 4 7 1 0 3 7 2 8 7 9 2 9 3 7 7 0 7 2 6 6 9 1 9 3 6 9 9 7 0 4 4 2 7 2 2 4 8 9 7 4 1 6 7 6 3 8 7 9 6 6 6 3 7 5 4 1 9 6 5 0 5 1 2 1 7 9 9 2 1 4 0 5 3 6 2 3 5 2 9 5 0 9 1 3 7 5 3 5 1
|
||||
6 6 6 3 1 5 2 0 3 1 8 1 6 3 2 5 4 7 7 3 9 8 8 5 3 1 9 4 4 1 7 2 1 8 5 4 6 6 3 8 4 4 7 5 8 8 7 3 9 8 3 3 5 4 1 0 5 4 3 5 5 5 6 6 5 0 3 8 4 1 8 2 2 6 0 8 6 6 7 5 0 8 4 0 5 6 6 4 7 6 8 1 9 6 3 5 4 7 1 5
|
||||
6 0 5 7 0 0 2 4 2 0 8 6 5 2 2 6 8 6 7 7 8 7 8 9 7 0 2 5 9 2 4 8 2 6 9 2 2 3 1 9 8 4 2 8 1 1 5 0 9 1 1 7 0 1 4 3 1 7 5 6 2 6 7 2 6 2 9 5 0 3 7 0 1 8 4 2 5 9 1 7 9 8 7 3 3 4 8 5 4 6 5 1 3 3 8 3 9 0 3 5
|
||||
8 8 7 9 6 9 1 1 3 9 9 1 8 2 5 1 1 3 4 5 5 6 4 5 6 5 3 3 1 9 2 5 6 3 6 4 6 0 4 7 8 2 2 7 4 7 1 0 4 0 5 2 3 1 7 5 5 7 6 6 9 0 0 6 3 8 3 5 3 7 9 9 7 6 9 9 8 7 2 4 4 1 5 7 4 7 4 0 8 5 5 6 6 7 6 8 5 2 9 6
|
||||
0 5 2 1 9 0 2 4 1 9 2 0 7 0 9 9 6 7 1 2 5 1 6 2 5 0 5 6 3 3 6 4 6 1 5 3 6 9 2 8 2 8 4 7 9 9 5 0 2 1 4 3 0 5 4 6 6 6 6 6 9 5 2 9 4 6 3 7 4 6 2 9 8 4 7 6 5 0 8 8 6 0 3 9 9 7 4 7 6 8 0 1 3 5 3 8 6 6 6 5
|
||||
6 0 5 1 5 9 0 2 0 7 3 5 6 9 9 0 0 3 0 2 0 6 0 3 0 4 5 2 4 6 7 5 1 9 0 6 2 1 1 7 5 0 6 2 7 0 5 9 9 0 6 7 4 5 9 3 3 9 8 6 0 1 5 3 1 4 7 8 8 0 9 1 8 9 2 4 3 2 2 9 2 5 2 2 1 3 5 1 5 0 8 4 3 2 8 1 1 7 0 1
|
||||
0 4 3 2 7 1 0 1 9 2 2 1 6 8 6 8 6 1 7 2 3 0 3 2 8 4 8 5 6 3 7 6 9 3 9 8 8 6 8 7 1 7 8 7 1 2 3 9 2 8 6 0 5 4 6 6 3 3 1 2 7 4 7 7 2 4 7 4 5 3 7 9 1 3 3 2 5 9 1 1 8 6 8 2 0 1 8 9 6 7 0 4 3 3 9 4 4 3 3 9
|
||||
7 8 4 9 3 4 9 5 1 9 6 3 8 7 3 7 6 9 2 3 1 4 0 5 1 2 2 7 0 9 3 0 7 2 7 7 3 4 6 8 5 2 1 7 5 5 0 8 9 8 8 6 5 8 6 4 0 6 0 2 7 1 6 7 5 3 8 8 8 1 7 4 1 9 8 7 2 9 9 8 2 8 2 4 0 0 3 4 0 2 5 6 5 5 4 7 4 9 1 1
|
||||
0 9 8 9 7 1 1 6 0 5 7 0 7 4 0 8 9 0 1 0 6 5 7 2 9 8 5 8 3 5 3 3 8 4 2 7 4 6 2 8 4 6 3 5 2 3 7 2 8 9 8 2 3 2 6 3 8 4 3 6 5 4 5 1 4 6 2 3 9 1 8 9 5 5 6 6 9 4 8 5 1 2 7 9 9 4 3 6 6 6 1 5 2 8 7 3 5 9 8 2
|
||||
9 9 1 3 8 0 6 8 0 8 6 6 2 3 5 4 1 8 2 6 9 7 1 0 6 8 8 6 4 7 3 1 0 0 9 5 2 5 1 6 1 8 9 1 3 2 3 4 6 2 0 0 2 5 0 5 8 6 8 9 1 7 9 1 6 3 3 0 8 6 2 1 7 6 0 3 6 0 9 0 1 6 4 2 5 1 7 1 2 3 3 1 5 3 0 0 4 5 0 5
|
||||
4 4 6 0 2 7 1 3 5 0 8 6 4 3 7 1 7 4 4 3 1 0 1 8 8 4 3 0 7 1 8 6 1 4 4 8 5 2 9 9 0 3 0 8 2 0 4 3 7 2 7 4 5 7 7 5 0 1 5 8 4 5 3 4 1 2 9 9 0 0 7 4 9 8 9 2 6 9 9 0 3 6 1 9 2 5 1 2 5 9 5 0 4 6 4 4 6 1 8 6
|
||||
6 9 8 5 1 7 8 8 1 9 4 7 0 6 4 7 2 4 5 7 1 8 1 4 9 2 3 3 5 4 8 8 2 2 9 5 6 1 5 2 9 7 8 5 5 0 4 1 9 8 5 5 5 7 7 6 9 1 3 9 5 0 8 0 7 7 6 2 3 7 2 0 3 6 9 8 6 2 5 5 3 0 6 5 0 7 4 4 3 4 4 3 2 0 4 0 3 8 8 5
|
||||
6 8 0 9 9 2 9 6 3 9 2 1 7 6 8 6 2 5 7 4 9 3 3 8 3 8 0 8 4 8 3 2 0 2 2 1 6 6 3 2 3 0 6 4 0 8 3 8 4 9 7 9 9 2 0 7 8 4 4 0 1 8 4 2 9 2 8 4 2 8 1 0 3 5 2 3 6 3 9 6 9 6 1 3 2 7 0 7 9 2 8 1 8 2 4 8 2 2 9 8
|
||||
7 2 8 2 8 4 3 2 4 1 1 4 4 1 7 0 4 5 9 0 7 0 1 2 3 3 9 2 1 3 5 7 6 0 2 4 3 3 5 1 8 7 6 3 3 7 6 5 1 3 4 5 0 0 6 4 2 0 7 9 1 5 4 7 2 6 5 4 0 2 6 1 6 7 2 6 4 7 2 5 4 9 1 0 8 9 5 7 6 4 4 2 0 3 3 5 9 2 3 0
|
||||
7 7 3 2 7 5 1 5 9 2 9 7 7 7 6 5 6 3 1 3 4 1 8 3 2 5 7 6 7 3 7 7 9 5 3 6 3 5 6 0 5 1 3 1 9 9 5 2 2 3 4 7 6 7 8 9 2 5 1 0 7 0 6 9 2 5 3 6 7 0 6 7 7 2 3 2 9 3 0 1 2 8 6 8 5 7 5 6 9 9 6 4 2 2 2 3 4 8 5 3
|
||||
4 0 5 1 9 8 9 6 8 9 8 8 0 1 2 0 8 7 7 5 5 6 8 8 4 9 9 2 7 8 0 3 6 8 2 6 8 1 4 8 7 5 3 6 2 0 7 2 7 8 1 2 8 3 8 4 3 9 8 7 5 6 7 9 7 7 2 2 1 6 2 2 6 0 0 6 9 2 1 2 7 3 6 3 6 5 5 5 8 0 0 2 6 6 7 9 6 4 4 4
|
||||
6 3 5 0 0 4 2 2 1 1 2 2 7 9 5 6 9 6 6 5 6 5 3 5 0 0 0 1 2 4 9 0 5 3 2 8 8 1 7 9 4 4 9 1 5 5 5 6 1 0 0 1 2 6 7 4 5 5 6 5 3 4 6 6 3 6 1 9 2 8 5 4 2 8 9 0 6 0 4 2 7 1 6 7 5 1 4 4 3 0 2 3 3 3 2 5 4 0 7 2
|
||||
2 4 1 0 3 2 0 5 4 6 8 3 5 8 2 1 1 5 4 5 4 9 4 6 4 3 6 3 6 1 7 9 3 0 4 6 1 2 7 9 8 5 6 8 0 6 7 8 0 5 9 9 0 3 6 3 6 3 3 2 4 8 0 2 3 9 1 9 7 0 1 7 1 5 5 1 9 8 4 8 3 8 5 9 6 2 8 5 3 0 1 8 4 3 5 7 8 7 1 3
|
||||
1 0 4 7 4 2 1 0 9 8 5 7 6 3 7 5 9 5 1 2 8 5 7 5 6 9 4 1 6 6 7 8 3 6 3 2 3 7 4 7 2 2 8 2 5 1 3 1 5 2 9 1 1 7 3 5 8 0 0 1 6 7 4 3 8 6 0 3 0 6 3 5 5 8 8 9 1 3 4 0 7 9 2 6 0 1 6 2 6 2 6 9 2 6 2 0 0 9 4 8
|
||||
9 8 5 2 5 4 4 6 3 8 6 9 1 5 7 2 1 6 5 2 8 0 5 1 5 8 2 6 4 7 9 9 5 2 0 1 6 0 9 3 9 8 6 7 5 9 1 2 3 6 7 7 7 4 7 3 4 5 9 7 4 6 3 3 4 1 3 2 1 3 1 1 3 9 1 7 0 0 1 4 0 5 6 0 6 6 1 0 4 0 9 3 1 7 9 3 6 8 1 0
|
||||
8 1 1 2 4 2 7 2 4 9 0 4 4 6 2 4 8 8 3 1 4 3 8 3 1 3 9 7 5 5 4 1 7 3 8 9 4 1 5 9 4 5 1 8 8 1 9 1 0 8 4 8 7 4 9 4 5 9 7 0 2 1 3 0 4 3 3 7 1 9 0 2 6 7 6 0 3 5 5 2 9 0 2 5 4 6 2 1 3 1 1 3 4 7 2 4 1 0 5 5
|
||||
5 4 0 7 8 5 1 5 6 0 8 4 1 3 6 1 7 0 3 8 0 2 9 0 2 7 0 6 5 3 4 0 5 3 9 6 4 2 8 7 4 7 8 7 4 2 8 2 5 8 0 6 3 2 7 0 4 5 2 6 5 5 8 8 3 3 4 4 3 9 3 5 3 2 3 5 3 8 1 7 2 2 6 0 9 4 6 7 7 0 2 7 9 5 9 7 6 7 8 2
|
||||
6 3 6 7 1 4 8 8 5 5 4 3 5 1 7 4 1 9 1 8 4 0 2 8 1 5 9 1 8 0 6 7 5 1 2 2 3 6 3 0 2 2 6 7 0 9 4 1 9 2 2 6 0 5 1 1 9 1 8 5 3 9 8 6 3 1 4 3 7 0 3 8 1 2 9 7 7 9 2 1 8 2 6 4 0 1 2 6 5 0 6 8 0 1 7 5 6 2 0 0
|
||||
2 3 7 6 8 8 1 7 3 1 7 1 4 4 2 6 5 1 6 6 7 2 3 3 0 3 9 0 1 7 8 8 4 5 0 4 7 9 6 0 0 5 6 3 1 3 8 8 2 7 0 4 2 0 8 9 9 8 9 1 4 9 1 2 1 5 9 0 3 9 2 9 9 0 9 9 9 3 7 7 1 0 1 1 7 1 5 2 5 3 2 1 8 4 3 4 1 0 0 2
|
||||
6 2 1 6 8 4 9 7 9 2 2 3 4 2 2 6 8 9 5 0 3 4 0 9 9 1 8 0 7 5 2 7 2 7 8 1 9 6 1 4 6 3 6 6 1 8 1 8 6 0 1 6 7 8 8 6 6 1 5 0 1 6 7 2 7 2 1 0 7 6 0 4 0 6 7 5 5 5 4 7 1 3 7 8 8 0 3 1 1 0 4 2 1 3 8 2 9 7 4 2
|
||||
8 0 2 7 8 8 5 7 0 7 0 3 1 5 4 7 1 5 7 5 3 5 8 3 8 7 4 6 7 4 0 0 5 4 1 9 7 8 0 1 6 2 0 0 2 1 3 7 4 1 7 5 3 7 4 1 0 8 1 8 2 6 4 5 0 6 3 3 1 0 0 5 7 7 6 6 5 9 6 3 8 8 9 7 7 8 3 9 7 2 0 5 4 1 7 7 3 1 8 0
|
||||
9 5 6 9 4 3 6 0 5 0 9 1 4 3 7 1 4 9 6 2 7 7 4 9 3 3 1 3 4 8 7 7 6 0 8 8 0 6 8 4 7 8 5 9 9 1 3 0 7 5 0 0 4 7 9 6 1 7 3 8 9 8 6 5 4 4 7 2 5 8 8 3 6 5 4 9 1 2 6 2 6 9 1 9 8 7 3 2 6 0 9 8 2 9 9 7 5 8 9 7
|
||||
8 0 9 3 5 3 5 1 1 5 0 2 2 0 2 0 4 4 9 5 6 0 1 5 2 0 1 1 1 6 7 5 0 0 0 4 8 5 6 9 6 3 0 2 0 7 5 8 1 3 3 8 4 1 7 3 5 9 6 5 0 1 6 2 9 9 4 4 5 9 8 9 3 7 7 9 8 1 7 8 7 8 7 7 2 8 6 6 9 3 1 3 7 2 0 5 6 3 9 7
|
||||
8 8 5 7 5 1 5 6 9 3 9 9 7 2 9 7 3 8 7 9 7 1 6 0 3 7 4 8 2 5 3 8 4 9 6 2 3 1 5 8 9 9 4 2 4 0 9 0 9 3 4 4 2 8 2 4 8 0 7 4 8 8 3 6 1 2 0 1 4 3 8 7 3 4 9 8 2 1 3 3 3 0 4 9 0 1 6 9 8 9 2 7 4 1 3 9 3 1 6 4
|
||||
1 0 7 2 1 0 0 4 6 0 2 0 5 8 4 8 6 5 8 7 2 7 1 8 5 5 4 3 9 7 6 4 1 7 4 1 8 7 6 4 5 1 8 5 6 7 9 9 0 3 0 4 3 2 7 3 2 8 3 3 4 8 8 3 4 9 0 8 8 4 1 1 2 6 3 9 5 9 2 3 0 3 7 2 9 4 9 0 7 9 0 9 1 3 2 7 3 8 6 2
|
||||
1 7 6 1 5 1 7 1 3 0 6 0 8 0 7 7 2 7 7 8 1 6 3 1 7 0 0 4 9 7 8 7 6 3 0 9 4 4 7 9 0 1 7 5 3 2 6 3 1 9 2 7 2 2 3 5 9 7 7 9 8 3 6 9 4 6 9 0 6 4 2 9 9 7 6 1 4 7 8 8 5 2 7 1 7 8 7 3 1 8 5 7 5 3 6 6 4 1 8 6
|
||||
2 9 4 7 1 2 1 3 1 6 0 1 5 1 1 4 5 7 2 9 8 0 9 0 0 7 2 4 1 7 6 1 0 4 8 3 1 8 2 6 8 3 2 9 8 4 2 9 3 5 9 2 4 3 6 3 6 5 1 9 3 6 7 3 9 5 5 2 0 5 2 1 6 7 9 9 2 0 0 3 1 3 1 5 6 6 4 2 7 4 8 5 2 8 6 7 9 3 1 5
|
||||
7 3 6 4 3 3 1 6 1 9 4 1 5 8 3 7 7 4 9 5 3 1 1 8 7 8 5 7 5 0 0 7 0 4 1 5 5 8 3 9 3 7 7 1 9 7 5 8 6 2 9 1 0 2 7 8 7 0 9 7 4 0 3 8 9 0 8 2 2 3 2 0 8 7 8 8 3 5 8 0 3 4 5 3 6 7 8 3 5 4 8 2 4 1 9 8 9 8 7 9
|
||||
2 3 6 2 1 1 8 4 7 3 0 1 0 4 3 0 3 1 7 3 1 8 5 7 5 3 4 7 8 5 1 0 3 1 3 0 6 4 5 9 7 3 0 4 3 6 5 1 7 3 3 6 9 7 8 0 8 6 1 8 1 1 2 8 5 1 5 1 1 1 2 8 9 2 6 8 9 8 3 8 7 6 2 8 9 5 5 9 5 3 1 8 9 4 4 9 1 0 8 3
|
||||
5 1 9 3 7 6 9 4 0 4 1 9 7 2 6 6 4 7 9 7 7 8 4 8 2 4 6 9 3 9 2 9 2 8 8 6 6 1 6 0 6 2 8 3 8 7 2 4 7 2 0 6 6 2 1 6 5 2 0 0 9 8 3 9 6 3 4 4 4 5 8 1 9 2 3 2 8 1 5 7 8 0 9 7 4 2 9 4 0 6 3 3 0 3 3 7 2 5 4 8
|
||||
6 2 5 7 2 0 6 1 0 2 4 5 2 8 3 3 5 7 1 5 1 7 8 9 2 0 0 3 3 9 1 7 8 9 3 9 2 1 8 5 1 8 2 2 5 5 3 0 9 5 5 0 4 1 9 8 1 5 5 9 2 1 5 7 3 4 9 0 3 2 8 4 0 5 5 4 9 8 6 6 8 7 0 1 0 5 0 9 9 3 5 6 6 8 5 5 5 0 0 9
|
||||
6 8 3 2 1 1 3 9 4 9 3 9 0 6 1 2 3 2 5 9 3 6 3 2 0 1 1 1 8 9 4 2 2 2 7 6 0 4 5 2 8 1 8 8 1 4 3 3 0 9 1 4 8 3 6 6 1 6 7 1 7 0 4 9 1 9 2 2 4 5 0 7 5 2 4 5 9 7 5 1 6 9 0 0 5 8 1 4 6 1 5 1 9 2 0 9 2 6 1 2
|
||||
3 3 4 5 5 7 6 4 7 3 1 6 5 4 5 6 8 0 9 5 7 9 6 2 4 8 2 0 1 9 0 7 9 6 4 3 7 2 5 2 4 0 0 1 0 9 5 1 8 9 1 8 3 5 8 9 3 6 2 0 3 0 2 8 4 3 3 5 5 0 3 3 2 1 0 6 2 8 2 7 1 2 2 6 4 4 3 2 4 1 2 8 9 7 0 9 1 4 6 9
|
||||
6 3 8 6 6 0 3 6 0 6 7 7 6 3 8 9 7 9 4 8 2 2 8 3 2 4 0 1 1 7 5 4 2 7 7 6 9 2 0 2 4 4 8 2 6 5 2 2 9 3 5 8 6 9 2 9 7 0 7 9 6 4 8 6 5 5 3 4 9 0 9 0 8 7 5 7 8 8 5 1 2 0 3 7 9 4 8 9 6 6 2 8 2 4 7 8 7 1 3 4
|
||||
9 9 1 4 2 6 0 9 1 0 0 5 2 9 1 7 6 9 0 6 6 4 9 3 7 3 7 5 3 5 2 1 6 7 4 4 5 4 6 5 8 2 3 8 4 3 8 5 2 7 7 9 2 3 8 2 5 2 5 7 6 8 2 1 3 4 3 5 5 3 5 7 5 9 6 4 8 8 3 8 5 3 8 8 7 9 0 2 3 5 2 4 8 8 2 9 8 0 1 9
|
||||
3
03-MatrixAddition/matrices/vector1
Normal file
3
03-MatrixAddition/matrices/vector1
Normal file
@@ -0,0 +1,3 @@
|
||||
2 1
|
||||
1
|
||||
2
|
||||
3
03-MatrixAddition/matrices/vector2
Normal file
3
03-MatrixAddition/matrices/vector2
Normal file
@@ -0,0 +1,3 @@
|
||||
2 1
|
||||
5
|
||||
8
|
||||
BIN
05-RootVegFarm/.DS_Store
vendored
Normal file
BIN
05-RootVegFarm/.DS_Store
vendored
Normal file
Binary file not shown.
179
05-RootVegFarm/RootVegFarm.md
Normal file
179
05-RootVegFarm/RootVegFarm.md
Normal file
@@ -0,0 +1,179 @@
|
||||
## Introduction
|
||||
|
||||
The purpose of this lab is to design, code, and test a program that uses multi-threading with synchronization mechanisms.
|
||||
|
||||
The root vegetable farm grows turnips and radishes for customers. Customers arrive at the farm and wait in line to be served by the farmer. Once they reach the farmer, they place their order for how many turnips and radishes they want to order and go home with their purchase. After a while they need to get more turnips and radishes, so they go back to the farm to purchase more. Customers always order the same amount of vegetables each time they reach the farmer.
|
||||
|
||||
The root vegetable farm has a set number of fields. Each turnip takes a set amount of time to grow. Once the turnip is done maturing, the farmer's field hand puts it is put in a storage bin for the farmer to grab and sell to customers. The same is true for radishes.
|
||||
|
||||
Fields can only grow a set amount of vegetables each season. Your job is to write a program to simulate the root vegetable farm for a single season (customers purchasing vegetables and fields growing vegetables). The simulation ends when all the fields have finished producing for the season. At that time, any customers waiting to purchase vegetables are immediately sent home and the simulation ends.
|
||||
|
||||
## References
|
||||
|
||||
You will be using threads for this lab. Each customer, turnip field, and radish field must be a separate thread. You will also have to keep track of the turnips and radishes in the storage bins. There is one bin for each type of vegetable, however the farmer has extra-extra-large bins that never run out of space. You will have to control access to the bins to make sure that customers don't buy vegetables when there aren't enough available.
|
||||
|
||||
The following man pages might be helpful for review:
|
||||
|
||||
- man pthreads
|
||||
- man sem_overview
|
||||
- man usleep
|
||||
- man sem_wait
|
||||
- man sem_post
|
||||
- man pthread_mutex_lock
|
||||
- man pthread_mutex_unlock
|
||||
- man pthread_cond_wait
|
||||
- man pthread_cond_signal
|
||||
|
||||
NOTE: In order to view the man pages for the pthread library, they must be installed on your OS image. You can do that by running the command:
|
||||
|
||||
```text
|
||||
sudo apt-get install manpages-posix manpages-posix-dev
|
||||
```
|
||||
|
||||
## The Exercise
|
||||
|
||||
Your program must simulate the farm for a single season. Simulation parameters will be given to you in a text file on the command line like previous labs. The format for the text file will be as follows:
|
||||
|
||||
- The first line will contain three integers
|
||||
- The first is the number of turnip fields
|
||||
- The second is the amount of time it takes for a turnip to grow (in microseconds)
|
||||
- The third is the number of turnips each turnip field produces for the season
|
||||
- The second line will contain three integers
|
||||
- The first is the number of radish fields
|
||||
- The second is the amount of time it takes for a radish to grow (in microseconds)
|
||||
- The third is the number of radishes each radish field produces for the season.
|
||||
- The third line contains a single integer - the number of customers
|
||||
- The rest of the file contains lines of 3 integers (one for each customer)
|
||||
- The first is the number of turnips the customer buys when they reach the farmer
|
||||
- The second is the number of radishes the customer buys when they reach the farmer
|
||||
- The third is the amount of time the customer waits at home after ordering before they get back in line to buy more turnips and radishes (in microseconds)
|
||||
|
||||
All numbers in the line will be separated by spaces. Here is an example:
|
||||
|
||||
```text
|
||||
4 1000 100
|
||||
3 2000 125
|
||||
3
|
||||
1 2 500
|
||||
3 4 1000
|
||||
1 0 200
|
||||
```
|
||||
|
||||
The parameters in this file says to simulate the root vegetable farm with 4 turnip fields where turnips take 1000 microseconds to grow and each field grows 100 turnips a season; 3 radish fields where radishes take 2000 microseconds to grow and each field grows 50 radishes a season. There are 3 customers: the first purchases 1 turnip and 2 radishes at a time and waits 500 microseconds between orders; the second purchases 3 turnips and 4 radishes at a time and waits for 1000 microseconds between orders; the third orders 1 turnip and radishes each time and waits 200 microseconds between orders. This simulation has a total of 10 threads (4 for the turnip fields, 3 for the radish fields, and 3 for customers).
|
||||
|
||||
NOTE: a single field can produce only a single vegetable at a time. In the example above, one turnip field produces a single turnip every 1000 microseconds.
|
||||
|
||||
The simulation will always have at least one turnip field, one radish field, and one customer. Furthermore, the customer will buy at least 1 turnip or 1 radish. They may by 0 of one, however (customer 3 above).
|
||||
|
||||
When turnips and radishes are done growing, the farm hand immediately places them into the storage bin (in zero time). Similarly, when customer orders their vegetables, they immediately receive from the storage bin (in zero time). Customers can travel between their home and the farm in zero time as well (they are quite speedy).
|
||||
|
||||
All customers initially arrive at the same time and form a line (in any order). After their order is filled, they wait a set amount of time, then go to the end of the line and wait for all customers ahead of them to be served before they can order again.
|
||||
|
||||
Your simulation must ensure that a customer waits when they reach the front of the line if there are not enough vegetables in the storage bins. This holds up the line, and nothing can be purchased until enough turnips and radishes are grown. Do not let customers skip others in line even if a customer later in line can have their order satisfied.
|
||||
|
||||
You will have to keep a record of how many times a customer had their order filled. This will need to be printed out at the end of your simulation.
|
||||
|
||||
You will also have to keep track of how full each storage bin got. In other words, keep track of the largest number of turnips and radishes that were ever in the storage bin. Print this out at the end of your simulation.
|
||||
|
||||
Customers can't purchase vegetables that haven't been grown. Make sure your output makes sense. For example, if your simulation only has a single turnip field that grows 100 turnips a season and a single customer that buys 2 turnips at a time, their order can't be filled more than 50 times!
|
||||
|
||||
Here is a sample output for the above example parameter file:
|
||||
|
||||
```text
|
||||
The Root Vegetable Farm
|
||||
Turnip Fields - Number:4 Time:1000 Total:100
|
||||
Radish Fields - Number:3 Time:2000 Total:125
|
||||
Customer 0 - Turnips:1 Radishes:2 Wait:500
|
||||
Customer 1 - Turnips:3 Radishes:4 Wait:1000
|
||||
Customer 2 - Turnips:1 Radishes:0 Wait:200
|
||||
|
||||
Simulation finished:
|
||||
Max turnips in the turnip bin: 217
|
||||
Max radishes int the radish bin: 3
|
||||
Customer 0 got their order filled 65 times
|
||||
Customer 1 got their order filled 61 times
|
||||
Customer 2 got their order filled 110 times
|
||||
```
|
||||
|
||||
NOTE: due to the (more or less) random behavior of threads, the output from your root vegetable farm simulation may not exactly match this one. Make sure, however, that your output makes sense.
|
||||
|
||||
## Development Tips
|
||||
|
||||
- The parameter files can be read in easily with ```fscanf```, just like the previous labs
|
||||
- As the number of threads is dynamic (specified in the parameter file), you will need to malloc a space for storing statistics. Don't forget to free your mallocs!
|
||||
- You will need to use concurrency mechanisms for synchronization.
|
||||
- Semaphores store their count; you can use this to count items in a storage bin.
|
||||
- Mutex locks store their owner and allow only one thread to obtain the lock.
|
||||
- Condition variables combine a mutex lock with a condition that is either true or false.
|
||||
- Do NOT use empty 'while' loops to wait for vegetables.
|
||||
- All threads for the simulation should start more or less at the same time. Think about how you can do this. Check out the concurrency examples from class for tips.
|
||||
- Don't forget to synchronize access to the storage bins. All grown vegetables should end up in their bin and shouldn't be lost due to race conditions. Furthermore, only a single customer can buy from the farm at a time. Think mutual exclusion.
|
||||
- You will need to figure out how to stop your simulation when the day is over. This may take some thought to figure out how to do it correctly to avoid memory leaks.
|
||||
- The parameter passed to a thread function is a void pointer. Make sure that if you are passing the address of variables on the stack that the value is still good when the thread needs it. Pointers to local variables declared on the stack will become invalid when the stack frame is freed when the function returns.
|
||||
- Don't forget about using gdb to help with debugging (compile with -g to get additional debug symbols)
|
||||
|
||||
NOTE: when using gdb it is helpful to compile your program with additional debug symbols included. These allow gdb to show you more information when running commands like backtrace (bt). To compile with additional debug symbols use the -g flag on gcc. For example:
|
||||
|
||||
```text
|
||||
gcc -Wall -g -o myprog mysourcefile1.c mysourcefile2.c mysourcefile3.c
|
||||
```
|
||||
|
||||
- Using valgrind will be helpful in this lab to ensure you do not have any memory leaks.
|
||||
- When compiling your program you will need to include an additional compiler flag: -pthread. This tells the compiler to use the pthreads library. The examples use this in the Makefile, so you can see how to use it there as well. For example:
|
||||
|
||||
```text
|
||||
gcc -Wall -g -o myprog -pthread mysourcefile1.c mysourcefile2.c mysourcefile3.c
|
||||
```
|
||||
|
||||
NOTE: the -pthread flag can be anywhere on the command line. It does NOT need to be the last thing on the command line.
|
||||
|
||||
## Testing and Debugging
|
||||
|
||||
Use the example above to get you started with testing your lab. Creating a file with simpler parameters (fewer customers, turnip fields, and radish fields) might help you debug. You are also required to create some (more than one) of your own parameter files to show that you adequately tested your program. Include those in your submission. Don't forget to test large simulations.
|
||||
|
||||
## Deliverables
|
||||
|
||||
You will need to include all your source files, test case parameter files, and any other resources you used to complete lab. Please don't just google search for a solution, but if you do use Google for any help, include a description and URL of what you used to help you.
|
||||
|
||||
A makefile is useful, but optional for this assignment. If you created a makefile, include it in your submission.
|
||||
|
||||
All files should be well documented with function comment blocks and inline comments that explain complicated code routines. While no explicit style guidelines are set for programming in this course, code should be documented and readable. Include your name, section, and lab name in a comment block at the top of each file.
|
||||
|
||||
NOTE: do ***NOT*** submit any IDE configuration files (.idea, project files, etc.). Only submit your source files and report.
|
||||
|
||||
Prepare a lab report and submit it along with your source code. The report should include the following:
|
||||
|
||||
- Your name, section, date, and lab title
|
||||
- Introduction – a description of the lab in your own words
|
||||
- Design – a description of your design decisions in creating your solution
|
||||
- Resources – a description of any external resources you used to complete the lab
|
||||
- Build – instructions on how to build and run your program. Include the exact commands that are necessary
|
||||
- Analysis – Program needs to print out, for each customer, how many times they had their order filled. Use this information to evaluate the fairness of your implementation.
|
||||
- Is your implementation fair given the parameters for vegetables a customer orders and how long they wait between ordering?
|
||||
- What is "fair" in your own words?
|
||||
- In this implementation, when a customer arrives at the front of the line, if there are not enough vegetables, they hold up the entire line and wait until their vegetables have grown. What if instead, when a customer reached the front of the line if not enough vegetables were ready, they skip their ordering opportunity and immediately return to the end of the line without ordering? Given your definition of fair, is this behavior fair? Why or why not?
|
||||
- Deli counters, butcher stores, restaurants, etc. use a number system where a customer orders immediately, receives a number, and waits while their order is prepared. How would you change your implementation (in terms of how concurrency mechanisms are used) to handle this scenario?
|
||||
- The farm storage bins have limitless capacity. Does this make sense in practice? Why or why not? How would your code need to be modified to handle a bin with a capacity limit?
|
||||
- Conclusion
|
||||
- Summary of what you learned in the lab
|
||||
- What specifically was challenging about this lab?
|
||||
- What did you like about it?
|
||||
- What could we do to improve it for others?
|
||||
|
||||
NOTE: You should ensure that this program compiles without warning (-Wall and -Wextra) prior to submitting.
|
||||
|
||||
Prepare a zip file with all submitted files and upload the file to Canvas per your instructor's instructions.
|
||||
|
||||
## Grading Criteria
|
||||
|
||||
- (35 Points) Report
|
||||
- (5 Points) Report Introduction - Thorough description of the lab in your own words.
|
||||
- (5 Points) Design and Testing Methodology - Detailed description of design and method for testing your implementation.
|
||||
- (20 Points) Analysis - Answers to the analysis questions
|
||||
- (5 Points) Conclusion - Thorough conclusion with description of what you learned, what you liked, and suggestions for lab improvements.
|
||||
- (5 Points) Documented Resources - Description of external resources used to complete the lab
|
||||
- (5 Points) Correct Submission - Followed submission instructions (e.g. IDE project files are not submitted)
|
||||
- (5 Points) Build - Code compiles without warnings or errors
|
||||
- (10 Points) Test Cases - Thoroughness of submitted test cases
|
||||
- (35 Points) Instructor Tests - Implementation passes all instructor test cases
|
||||
- (5 Points) Memory Management - Program execution is free from memory leaks
|
||||
6
05-RootVegFarm/testcases/given
Normal file
6
05-RootVegFarm/testcases/given
Normal file
@@ -0,0 +1,6 @@
|
||||
4 1000 100
|
||||
3 2000 125
|
||||
3
|
||||
1 2 500
|
||||
3 4 1000
|
||||
1 0 200
|
||||
4
05-RootVegFarm/testcases/tc1
Normal file
4
05-RootVegFarm/testcases/tc1
Normal file
@@ -0,0 +1,4 @@
|
||||
1 1000 1
|
||||
1 1000 1
|
||||
1
|
||||
1 1 500
|
||||
9
05-RootVegFarm/testcases/tc2
Normal file
9
05-RootVegFarm/testcases/tc2
Normal file
@@ -0,0 +1,9 @@
|
||||
10 100 100
|
||||
10 100 100
|
||||
6
|
||||
1 1 10
|
||||
1 1 10
|
||||
1 1 10
|
||||
1 1 10
|
||||
1 1 10
|
||||
1 1 10
|
||||
28
05-RootVegFarm/testcases/tc3
Normal file
28
05-RootVegFarm/testcases/tc3
Normal file
@@ -0,0 +1,28 @@
|
||||
4 1000 100
|
||||
3 2000 125
|
||||
25
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
1 1 100
|
||||
6
05-RootVegFarm/testcases/tc4
Normal file
6
05-RootVegFarm/testcases/tc4
Normal file
@@ -0,0 +1,6 @@
|
||||
200 1000 10
|
||||
100 1000 10
|
||||
3
|
||||
1 2 500
|
||||
3 4 1000
|
||||
1 0 200
|
||||
7
05-RootVegFarm/testcases/tc5
Normal file
7
05-RootVegFarm/testcases/tc5
Normal file
@@ -0,0 +1,7 @@
|
||||
1 1000 10
|
||||
1 1000 10
|
||||
4
|
||||
1 0 200
|
||||
1 0 200
|
||||
1 0 200
|
||||
1 0 200
|
||||
4
05-RootVegFarm/testcases/tc6
Normal file
4
05-RootVegFarm/testcases/tc6
Normal file
@@ -0,0 +1,4 @@
|
||||
2 500 1
|
||||
2 500 1
|
||||
1
|
||||
100 100 200
|
||||
BIN
06-MemoryManager/.DS_Store
vendored
Normal file
BIN
06-MemoryManager/.DS_Store
vendored
Normal file
Binary file not shown.
16
06-MemoryManager/Makefile
Normal file
16
06-MemoryManager/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -pthread
|
||||
|
||||
all: testmemmgr pthread_testmemmgr
|
||||
|
||||
testmemmgr: memory_manager.o testmemmgr.o
|
||||
$(CC) -o testmemmgr $^
|
||||
|
||||
pthread_testmemmgr: memory_manager.o pthread_testmemmgr.o
|
||||
$(CC) -pthread -o pthread_testmemmgr $^
|
||||
|
||||
%: %.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f testmemmgr pthread_testmemmgr *.o
|
||||
1
06-MemoryManager/MemoryManager.drawio
Normal file
1
06-MemoryManager/MemoryManager.drawio
Normal file
@@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2020-10-15T14:29:28.033Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.7.9 Chrome/85.0.4183.121 Electron/10.1.3 Safari/537.36" etag="4XsUur8vGzt_dVvNh1po" version="13.7.9" type="device"><diagram id="JprUjM1ryZXmwLVKSzoi" name="Page-1">7VxRc6M2EP41nvE95AaBhM2jneQu7aSdzKSd9p46ipGBO4xckBO7v74SCGMQTogvIBv7JUGLJMTuftK3K+GBdb1Yf43x0v+NuiQcmIa7Hlg3A9N0DMT/CsEmE9gjMxN4ceBmIlAIHoP/iBQaUroKXJKUKjJKQxYsy8IZjSIyYyUZjmP6Uq42p2H5qUvsEUXwOMOhKv0rcJmfScfIKOR3JPD8/MnAkHcWOK8sBYmPXfqyI7JuB9Z1TCnLrhbraxIK3eV6ydp92XN3O7CYRKxJg1+fvvs/nLvknz+eNuaN/7AGzrcrU1ojYZv8jYnLFSCLNGY+9WiEw9tCOo3pKnKJ6NbgpaLOPaVLLgRc+J0wtpHWxCtGuchni1DeJeuA/b1z/U109RnJ0s1a9pwWNnkhYvFGNLoyPhswF+y0FMWiaVoqtX0gcbAgjMRSOKcRkyMEor9MEeLt9ypYihK6imfkFa2OpKPi2CPslXoAbP2A44dQPrx4wxvGJMQseC4PBEtP9rb1CmPzC2nvd9hejvIZhyv5pC8xIVwyDensx8CaDEw75MOfPsUlD7H/XQmfTRV4laQa5FUNAJfrVI35fX7lif+PRRUBjo/pk+uWBZHH60xcNyZJknVvKO5cdtYXP2DkcYlT873wGavsmPU+8UxiRtave4VqRNmAT4FZEzkB5jPHSzGbgJGU+TsziW20ZPaxYnZ1CojciZg7eWkW4iQJZhX85lg03ofDwyH3JpRG9UbY0TKqUXIuaww4+YQHGvABFjYGZRuPK7bLJgzZaHeKrvRjW+V+AKh0lKlB6Sj1g+1bH+4aACi+8fuf9/eKf3A0sLJH4DDwIuEu3HBihp0KzAR8GZ3IG4vAdbPFg3B446e0K+ETS/Ey6euh6QDdiL74epFIL2kHk6hir5GKyTpvMduCJDAVvd8R7PZO72bOBnMyqFnvJrqwn49nP6bdcM42xzrpTz7MDvmP0zL9AcdHf2CF/oAazHfLf0yV9/aBAFlGvR30MCDgHEqBzHJHyuTfMgUyVXrcSwo0qhpsrHstds6TAwHd5NMCio6PnQR1Nuu+yXXygO1trmPr5Dr5MHfANQk5y8GM27DVhM/Z53v0Ex44vgD8YIDDpgCHWgEONQEcorOPaOqyRx0DXE3bqYg/vYgGono76IloLOODIhrL6jaigWpysZcRjWNUcOloJtbQUhR/FhGNqTuUhPBCeA4nPKjp9Lwn4dQR4UF6CM8lojkCwoNUJR0pwNsEatNtlowAaANq99ssbQclSN021I1R+/gwekkrHo5tZDbENnJ0Yjsf5iXr0HnWwaoh2R0DXA1vVMSfXtYBHdVJMlg9AXZo1gHCbrMOCCrecRZZB2hoDn6RGhidRdbB0p3uQfaF8BxOeJoemUdagxmk48z82SccjoDrnMwWapsYdZpiFGrFqHqQ6JJwaD3hoB+j9slg9JQOc9tNQT/S+i2b3T3oLx+zcYKt/XBT/rCeZSHsPXk9PVkIdPBp7soHbXbHp7lHZ/pBG9K9BZ9/5X9uWQik+zT3SP1+YQg+ccEvUcACHL7DAiGZs2PXf2V+qdF+3WrUnvZVGjI0hfYXWOyLDIHxqd8GqPuMZPuTGJ2YYKwSgqG1YwKIem6CunNvHZtAXXWHUJhgzin5UFzgbJcwoFEqpQv+L52m+myYuq2B7Xdy3RhGXZWHaAcbSExPxhWPS/BCBBNeFqUYcxyESc+NU4eaTlfusbqfOrRz1OzDjNVzzNQR2e0a85Nm4cXi15eyiKP4CSvr9n8=</diagram></mxfile>
|
||||
287
06-MemoryManager/MemoryManager.md
Normal file
287
06-MemoryManager/MemoryManager.md
Normal file
@@ -0,0 +1,287 @@
|
||||
## Introduction
|
||||
|
||||
The purpose of this lab is to develop a dynamic memory manager. This memory manager will replace the functionality of the malloc and free routines built into the operating system.
|
||||
|
||||
The heap is considered a contiguous chunk of memory from which storage is allocated using malloc and deallocated using free. As storage is malloc'ed and freed, memory fragments may appear. A memory manager needs to keep track of the allocated spaces and fragments in order efficiently satisfy memory requests. Furthermore, as memory is freed, fragments must be coalesced to ensure optimal memory use.
|
||||
|
||||
Your goal for the lab is to implement a memory manager, provide a means for a user to allocate and free memory all while keeping statistics of the memory management system.
|
||||
|
||||
## References
|
||||
|
||||
Your memory manager will have to mimic the behavior of malloc and free. It might be helpful to refresh your memory on how malloc and free work. Furthermore, you will need to ensure synchronized access to the memory manager in the case where a client application is using pthreads.
|
||||
|
||||
The following man pages might be helpful for review:
|
||||
|
||||
- man malloc
|
||||
- man free
|
||||
- man pthread_mutex_init
|
||||
- man pthread_mutex_destroy
|
||||
- man pthread_mutex_lock
|
||||
- man pthread_mutex_unlock
|
||||
|
||||
To view the man pages for the pthread library, they must be installed on your OS image. You can do that by running the command:
|
||||
|
||||
```text
|
||||
sudo apt-get install manpages-posix manpages-posix-dev
|
||||
```
|
||||
## The Exercise
|
||||
|
||||
You must implement a set of functions that a program can call to access the memory manager used to allocate and free storage. In addition, you will need to keep track of allocated and free blocks of memory.
|
||||
|
||||
There are several ways this can be done; one way is to use a linked list. Elements in the list record, the size of the allocated and free blocks and the memory address at the start of the block. Calls to allocate and free storage modify the list based on the request size.
|
||||
|
||||
For example:
|
||||
1. Consider a heap of 100 bytes that starts at address 1000. Initially all heap memory is unallocated (free). So, there is 1 large free block of storage that is 100 bytes long. The list consists of one element.
|
||||
2. A call to malloc for 10 bytes modifies the free block to reduce it by 10 bytes and allocates memory to the process. The free block now has only 90 free bytes. In addition, an element for the allocated block is added to the list.
|
||||
3. Another call to malloc, this time for 45 bytes modifies the free block to reduce it by 45 bytes (leaving 45 left). The list would not have 3 elements: 1 for the first allocated block, 1 for the second allocated block, and one for the free block.
|
||||
4. A call to free the 10-byte block would convert the allocated block into a free block. A memory allocation request for 10 bytes or less could be satisfied by that free block.
|
||||
5. However, a call to malloc 50 bytes at this point would fail because there are no free blocks big enough to satisfy the request.
|
||||
6. If a call to free is made to free the 45-byte block allocated in step 3, now there are free blocks next to each other. These should be coalesced (combined) into a single free block
|
||||
|
||||
Here's what the list might look like at each step from the example:
|
||||
|
||||

|
||||
|
||||
Allocating from a free block essentially splits the block into two: One block for the allocated space and one block for the remaining free space.
|
||||
|
||||
NOTE: This splitting is correct except for cases where you have a free block that exactly matches the allocation request. You should not have any zero sized blocks in your data structure. If you find a free block that exactly matches the size that you need for an allocation, then there should be no free blocks after it.
|
||||
|
||||
As with malloc and free, the caller should not be aware of the mechanism that is being used for memory block record keeping. Whatever structure you choose to use should be hidden in your memory manager implementation. This can be done by creating a static structure in your memory manager implementation file. The internal implementation of the data structure that you use to keep track of blocks is up to you. Internally to the memory manager, you are free to use malloc and free (the system versions). This will simulate the overhead that the operating system uses to manage memory. Just make sure you have no memory leaks within your memory manager.
|
||||
|
||||
Normally the size of the heap is controlled using system calls to request modifications to the process address space. Your memory manager will work a little bit differently. A user of your memory manager will be required to pass a pointer to a location in memory and a size. This storage must be pre-allocated by the user.
|
||||
|
||||
Your implementation must support 3 different types of placement algorithms to satisfy allocation requests:
|
||||
|
||||
1. First fit – allocates from the first free block that is big enough
|
||||
2. Worst fit – allocates from the largest free block
|
||||
3. Best fit – allocates from the smallest free block that is large enough to satisfy the request
|
||||
|
||||
A summary of all required functions (including statistics functions) is below:
|
||||
|
||||
- ```void mmInit(void* start, int size)``` – Initialize the memory manager
|
||||
- ```void mmDestroy()``` – cleans up any storage used by the memory manager
|
||||
- ```void* mymalloc_ff(int nbytes)``` – Requests a block of memory be allocated using first fit placement algorithm
|
||||
- ```void* mymalloc_wf(int nbytes)``` – Requests a block of memory be allocated using worst fit placement algorithm
|
||||
- ```void* mymalloc_bf(int nbytes)``` – Requests a block of memory be allocated using best fit placement algorithm
|
||||
- ```void myfree(void* ptr)``` – Free the storage address by ptr
|
||||
- ```int get_allocated_space()``` – Returns the amount of currently allocated space in bytes
|
||||
- ```int get_remaining_space()``` – Returns the amount of current free space in bytes (sum of all free blocks)
|
||||
- ```int get_fragment_count()``` – Returns the number of free blocks (the count of all the blocks, not the size)
|
||||
- ```int get_mymalloc_count()``` – Returns the number of successful malloc's made (since the last ```mmInit```)
|
||||
|
||||
## Error Checking
|
||||
|
||||
Your memory manager can't trust the user so it must perform error checking. If the user tries to malloc storage that can't be satisfied, return a NULL pointer just like the system malloc.
|
||||
|
||||
Furthermore, if a user tries to free a block that isn't allocated this should cause a segmentation fault. In this case, your memory manager should send SIGSEGV to the process (see the man page for the kill system call in section 2):
|
||||
|
||||
```text
|
||||
man 2 kill
|
||||
```
|
||||
## Getting Started
|
||||
|
||||
Start by downloading the [starter files](memory_manager.zip) which includes a source file (memory_manager.c) and a header file (memory_manager.h) that contain a skeleton for the required functions for your memory manager. The starter code also contains the sample test cases (testmemmgr.c and pthread_testmemmgr.c see below) and a Makefile to help you build your project.
|
||||
|
||||
## Sample Usage
|
||||
|
||||
Here is a sample client program that uses the memory manager. This file is provided along with the starter code:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("1 -- Available Memory: %d, Fragment Count: %d\n",
|
||||
get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Allocate 10 bytes
|
||||
// shouldn't fail
|
||||
char* ptr1 = mymalloc_ff(10);
|
||||
if(ptr1 == NULL) {
|
||||
printf("ptr1 - mymalloc_ff(10) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strncpy(ptr1, "HELLO", 10);
|
||||
printf("ptr1 is %s\n", ptr1);
|
||||
|
||||
printf("2 -- Available Memory: %d, Fragment Count: %d\n",
|
||||
get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Allocate 45 bytes
|
||||
// shouldn't fail
|
||||
char* ptr2 = mymalloc_wf(45);
|
||||
if(ptr2 == NULL) {
|
||||
printf("ptr2 - mymalloc_ff(45) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strncpy(ptr2, "GOODBYE", 45);
|
||||
printf("ptr2 is %s\n", ptr2);
|
||||
|
||||
printf("3 -- Available Memory: %d, Fragment Count: %d\n",
|
||||
get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Attempt to allocate 50 bytes
|
||||
// should fail
|
||||
char* ptr3 = mymalloc_bf(50);
|
||||
if(ptr3 == NULL) {
|
||||
printf("ptr3 - mymalloc_bf(50) failed\n");
|
||||
}
|
||||
|
||||
printf("4 -- Available Memory: %d, Fragment Count: %d\n",
|
||||
get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Free the first two pointers
|
||||
myfree(ptr1);
|
||||
myfree(ptr2);
|
||||
|
||||
printf("5 -- Available Memory: %d, Fragment Count: %d\n",
|
||||
get_remaining_space(), get_fragment_count());
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
|
||||
// Double free, should cause a segmentation fault
|
||||
myfree(ptr2);
|
||||
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
This should produce the output:
|
||||
|
||||
```text
|
||||
1 -- Available Memory: 100, Fragment Count: 1
|
||||
ptr1 is HELLO
|
||||
2 -- Available Memory: 90, Fragment Count: 1
|
||||
ptr2 is GOODBYE
|
||||
3 -- Available Memory: 45, Fragment Count: 1
|
||||
ptr3 - mymalloc_bf(50) failed
|
||||
4 -- Available Memory: 45, Fragment Count: 1
|
||||
5 -- Available Memory: 100, Fragment Count: 1
|
||||
Total successful mallocs: 2
|
||||
Segmentation fault (core dumped)
|
||||
```
|
||||
|
||||
## Thread Safety
|
||||
|
||||
Your memory manager should be thread safe. In other words, all calls to any memory manager function must work correctly with a multithreaded program. Race conditions might exist if two threads attempt to allocate or free memory at the same time. Furthermore, depending on how you implement your statistics, there might be race conditions in those functions as well. Make sure you use concurrency mechanisms (semaphores, mutex locks, condition variables, etc.) to ensure that your block allocation data structure is never corrupted.
|
||||
|
||||
NOTE: you can assume mmInit() and mmDestroy() will only ever be called by a single thread. Mutual exclusion is not needed for those functions.
|
||||
|
||||
A sample test driver using pthreads is included with the starter code.
|
||||
|
||||
## Development Tips
|
||||
|
||||
- You'll need to come up with an efficient data structure to use. If you use the system malloc, make sure you don't have memory leaks. An OS should NEVER have memory leaks. Don't forget to free your mallocs!
|
||||
- You need to ensure thread safety so synchronize access to your memory manager.
|
||||
- Don't forget about using gdb to help with debugging (compile with -g to get additional debug symbols)
|
||||
|
||||
NOTE: when using gdb it is helpful to compile your program with additional debug symbols included. These allow gdb to show you more information when running commands like backtrace (bt). To compile with additional debug symbols use the -g flag on gcc. For example:
|
||||
|
||||
```text
|
||||
gcc -Wall -g -o myprog mysourcefile1.c mysourcefile2.c mysourcefile3.c
|
||||
```
|
||||
|
||||
- Using valgrind will be helpful in this lab to ensure you do not have any memory leaks.
|
||||
- When compiling your program you will need to include an additional compiler flag: -pthread. This tells the compiler to use the pthreads library. The examples use this in the Makefile, so you can see how to use it there as well. For example:
|
||||
|
||||
```text
|
||||
gcc -Wall -g -o myprog -pthread mysourcefile1.c mysourcefile2.c mysourcefile3.c
|
||||
```
|
||||
|
||||
NOTE: the -pthread flag can be anywhere on the command line. It does NOT need to be the last thing on the command line.
|
||||
|
||||
## Testing
|
||||
|
||||
Use the included test drivers to get you started with testing your lab. You are also required to create and submit your own test driver(s). Don't forget to test single threaded and multithreaded programs as well as each of the placement algorithms. Include your test driver(s) in your submission. Don't forget to test large and small amounts of memory (both for the managed space and for requests).
|
||||
|
||||
## Experimentation
|
||||
|
||||
Each of the three placement algorithms have advantages and disadvantages.
|
||||
|
||||
- First Fit – Relatively fast for malloc since it stops at the first block that fits the request but could potentially result in more fragments
|
||||
- Best Fit – Requires searching through all blocks but attempts to reduce the number of memory fragments by keeping as many larger fragments free as possible
|
||||
- Worst Fit – Requires searching through all blocks but attempts to keep the memory fragments as big as possible (on average) to allow more requests to be satisfied.
|
||||
|
||||
Despite the advantages and disadvantages, there is no perfect placement algorithm. It is possible to come with a combination of allocations and frees that cause lots of wasted space.
|
||||
|
||||
As part of your lab report, perform some experiments with the different placement algorithms. Create a series of allocations and frees and report the number of fragments, number of successful allocations along with the total amount of free space. A placement algorithm is considered 'bad' for a set of allocations and frees if the total amount of free space is large enough to satisfy requests, but the fragments themselves are not big enough to satisfy a contiguous block.
|
||||
|
||||
## Deliverables
|
||||
|
||||
You will need to include all your source files, test case parameter files, and any other resources you used to complete lab. Please don't just google search for a solution, but if you do use Google for any help, include a description and URL of what you used to help you.
|
||||
|
||||
A makefile is useful, but optional for this assignment. If you created a makefile, include it in your submission.
|
||||
|
||||
All files should be well documented with function comment blocks and inline comments that explain complicated code routines. While no explicit style guidelines are set for programming in this course, code should be documented and readable. Include your name, section, and lab name in a comment block at the top of each file.
|
||||
|
||||
NOTE: do ***NOT*** submit any IDE configuration files (.idea, project files, etc.). Only submit your source files and report.
|
||||
|
||||
Prepare a lab report and submit it along with your source code. The report should include the following:
|
||||
|
||||
- Your name, section, date, and lab title
|
||||
- Introduction – a description of the lab in your own words
|
||||
- Design – a description of your design decisions in creating your solution
|
||||
- Resources – a description of any external resources you used to complete the lab
|
||||
- Build – instructions on how to build and run your program. Include the exact commands that are necessary
|
||||
- Analysis - Discuss the key concepts from the lab and your experimental results and answer the following questions.
|
||||
- What placement algorithm worked the best for your experimental allocations and frees in terms of the number allocations that were successful? Why do you think this is the case?
|
||||
- The time complexity for an algorithm defines an estimate for how long it will run based on the input size. It is advantages to keep the OS CPU overhead as low as possible. Any OS algorithm that runs in longer than constant time O(1) is often considered to be too high although sometimes this is not possible.
|
||||
- What is the time complexity of your mymalloc and myfree?
|
||||
- Is your algorithm acceptable? Why or why not?
|
||||
- How could you implement your memory manager differently to improve the time for mymalloc and myfree?
|
||||
- The memory overhead consists of the amount of extra memory needed by the OS for keeping track of memory blocks. It is advantageous to keep the OS memory overhead as low as possible.
|
||||
- For a set of 'n' successful memory allocations, about how much additional memory (on average) does your memory manager use?
|
||||
- Can you think of a better way to implement your memory manager that uses less memory overhead with the potential cost of additional CPU usage?
|
||||
- Memory leaks can be a problem especially for long-lived processes (those that run for a long time or forever). Could you use the structures in your memory manager to detect client memory leaks? Explain your algorithm or explain why it's not possible.
|
||||
- Conclusion
|
||||
- Summary of what you learned in the lab
|
||||
- What specifically was challenging about this lab?
|
||||
- What did you like about it?
|
||||
- What could we do to improve it for others?
|
||||
|
||||
NOTE: You should ensure that this program compiles without warning (-Wall and -Wextra) prior to submitting.
|
||||
|
||||
Prepare a zip file with all submitted files and upload the file to Canvas per your instructor's instructions.
|
||||
|
||||
## Extra Credit
|
||||
|
||||
While dynamic memory allocation (e.g. the use of malloc) within the OS kernel is possible, it is often advantageous to limit the use of this as much as possible to avoid any potential for memory leaks within the kernel.
|
||||
|
||||
For example, internally in the Linux kernel kmalloc() is used ([https://www.kernel.org/doc/htmldocs/kernel-api/API-kmalloc.html](https://www.kernel.org/doc/htmldocs/kernel-api/API-kmalloc.html)) as a way to dynamically allocate blocks within the OS kernel's address space.
|
||||
|
||||
As a bonus challenge, can you find a way to implement your bookkeeping data structure so that it does not need to use malloc and free internally?
|
||||
|
||||
- It must still be able to manage a region of memory that is of varying size. The memory manager doesn't know how big the region is until the call to mmInit is made.
|
||||
- It must still be able to keep track of a potentially unlimited number of memory fragments and allocated blocks.
|
||||
- must still be thread safe
|
||||
- It must keep track of all required statistics
|
||||
|
||||
HINT: You can use a portion of the memory region given to you by the user. This will reduce the total amount of storage that can be allocated from the block, but that is fine provided you can avoid using malloc and free internally.
|
||||
|
||||
## Grading Criteria
|
||||
|
||||
- (35 Points) Report
|
||||
- (5 Points) Report Introduction - Thorough description of the lab in your own words.
|
||||
- (5 Points) Design and Testing Methodology - Detailed description of design and method for testing your implementation.
|
||||
- (20 Points) Analysis - Answers to the analysis questions
|
||||
- (5 Points) Conclusion - Thorough conclusion with description of what you learned, what you liked, and suggestions for lab improvements.
|
||||
- (5 Points) Documented Resources - Description of external resources used to complete the lab
|
||||
- (5 Points) Correct Submission - Followed submission instructions (e.g. IDE project files are not submitted)
|
||||
- (5 Points) Build - Code compiles without warnings or errors
|
||||
- (10 Points) Test Cases - Thoroughness of submitted test cases
|
||||
- (35 Points) Instructor Tests - Implementation passes all instructor test cases
|
||||
- (5 Points) Memory Management - Program execution is free from memory leaks
|
||||
BIN
06-MemoryManager/MemoryManager.png
Normal file
BIN
06-MemoryManager/MemoryManager.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
140
06-MemoryManager/memory_manager.c
Normal file
140
06-MemoryManager/memory_manager.c
Normal file
@@ -0,0 +1,140 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "memory_manager.h"
|
||||
|
||||
/*
|
||||
* Using static causes the compiler to
|
||||
* limit visibility of the variables to this file only
|
||||
* This can be used to simulate 'private' variables in c
|
||||
*/
|
||||
static int allocation_count = 0;
|
||||
|
||||
/* TODO Define additional structure definitions here */
|
||||
|
||||
/* mmInit()
|
||||
* Initialize the memory manager to "manage" the given location
|
||||
* in memory with the specified size.
|
||||
* Parameters: start - the start of the memory to manage
|
||||
* size - the size of the memory to manage
|
||||
* Returns: void
|
||||
*/
|
||||
void mmInit(void* start, int size)
|
||||
{
|
||||
allocation_count = 0;
|
||||
|
||||
// TODO more initialization needed
|
||||
}
|
||||
|
||||
/* mmDestroy()
|
||||
* Cleans up any storage used by the memory manager
|
||||
* After a call to mmDestroy:
|
||||
* all allocated spaces become invalid
|
||||
* future allocation attempts fail
|
||||
* future frees result in segmentation faults
|
||||
* NOTE: after a call to mmDestroy a call to mmInit
|
||||
* reinitializes the memory manager to allow allocations
|
||||
* and frees
|
||||
* Parameters: None
|
||||
* Returns: void
|
||||
*/
|
||||
void mmDestroy()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* mymalloc_ff()
|
||||
* Requests a block of memory be allocated using
|
||||
* first fit placement algorithm
|
||||
* The memory manager must be initialized (mmInit)
|
||||
* for this call to succeed
|
||||
* Parameters: nbytes - the number of bytes in the requested memory
|
||||
* Returns: void* - a pointer to the start of the allocated space
|
||||
*/
|
||||
void* mymalloc_ff(int nbytes)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* mymalloc_wf()
|
||||
* Requests a block of memory be allocated using
|
||||
* worst fit placement algorithm
|
||||
* The memory manager must be initialized (mmInit)
|
||||
* for this call to succeed
|
||||
* Parameters: nbytes - the number of bytes in the requested memory
|
||||
* Returns: void* - a pointer to the start of the allocated space
|
||||
*/
|
||||
void* mymalloc_wf(int nbytes)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* mymalloc_bf()
|
||||
* Requests a block of memory be allocated using
|
||||
* best fit placement algorithm
|
||||
* The memory manager must be initialized (mmInit)
|
||||
* for this call to succeed
|
||||
* Parameters: nbytes - the number of bytes in the requested memory
|
||||
* Returns: void* - a pointer to the start of the allocated space
|
||||
*/
|
||||
void* mymalloc_bf(int nbytes)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* myfree()
|
||||
* Requests a block of memory be freed and the storage made
|
||||
* available for future allocations
|
||||
* The memory manager must be initialized (mmInit)
|
||||
* for this call to succeed
|
||||
* Parameters: ptr - a pointer to the start of the space to be freed
|
||||
* Returns: void
|
||||
* Signals a SIGSEGV if a free is not valid
|
||||
* - memory manager is not initialized
|
||||
* - memory manager has been destroyed
|
||||
* - ptr is not allocated (e.g. double free)
|
||||
*/
|
||||
void myfree(void* ptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* get_allocated_space()
|
||||
* Retrieve the current amount of space allocated by the memory manager (in bytes)
|
||||
* Parameters: None
|
||||
* Returns: int - the current number of allocated bytes
|
||||
*/
|
||||
int get_allocated_space()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get_remaining_space()
|
||||
* Retrieve the current amount of available space in the memory manager (in bytes)
|
||||
* (e.g. sum of all free blocks)
|
||||
* Parameters: None
|
||||
* Returns: int - the current number of free bytes
|
||||
*/
|
||||
int get_remaining_space()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get_fragment_count()
|
||||
* Retrieve the current amount of free blocks (i.e. the count of all the block, not the size)
|
||||
* Parameters: None
|
||||
* Returns: int - the current number of free blocks
|
||||
*/
|
||||
int get_fragment_count()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get_mymalloc_count()
|
||||
* Retrieve the number of successful malloc calls (for all placement types)
|
||||
* Parameters: None
|
||||
* Returns: int - the total number of successful mallocs
|
||||
*/
|
||||
int get_mymalloc_count()
|
||||
{
|
||||
return allocation_count;
|
||||
}
|
||||
119
06-MemoryManager/memory_manager.h
Normal file
119
06-MemoryManager/memory_manager.h
Normal file
@@ -0,0 +1,119 @@
|
||||
#ifndef MEMORY_MANAGER_H
|
||||
#define MEMORY_MANAGER_H
|
||||
|
||||
/* memory_manager.h
|
||||
*
|
||||
* External (public) declarations for a memory manager in c.
|
||||
*
|
||||
* Clients begin by initializing the memory manager. They can
|
||||
* then allocate and free blocks of memory. The memory manager
|
||||
* keeps track of allocated and free blocks to maintain efficient
|
||||
* use of memory.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Structures */
|
||||
/* No "public" structure, the user of the memory manager
|
||||
* should have no knowledge of the structures used for managing
|
||||
* allocated and free blocks
|
||||
*/
|
||||
|
||||
/* Memory Manager Methods */
|
||||
|
||||
/* mmInit()
|
||||
* Initialize the memory manager to "manage" the given location
|
||||
* in memory with the specified size.
|
||||
* Parameters: start - the start of the memory to manage
|
||||
* size - the size of the memory to manage
|
||||
* Returns: void
|
||||
*/
|
||||
void mmInit(void* start, int size);
|
||||
|
||||
/* mmDestroy()
|
||||
* Cleans up any storage used by the memory manager
|
||||
* After a call to mmDestroy:
|
||||
* all allocated spaces become invalid
|
||||
* future allocation attempts fail
|
||||
* future frees result in segmentation faults
|
||||
* NOTE: after a call to mmDestroy a call to mmInit
|
||||
* reinitializes the memory manager to allow allocations
|
||||
* and frees
|
||||
* Parameters: None
|
||||
* Returns: void
|
||||
*/
|
||||
void mmDestroy();
|
||||
|
||||
/* mymalloc_ff()
|
||||
* Requests a block of memory be allocated using
|
||||
* first fit placement algorithm
|
||||
* The memory manager must be initialized (mmInit)
|
||||
* for this call to succeed
|
||||
* Parameters: nbytes - the number of bytes in the requested memory
|
||||
* Returns: void* - a pointer to the start of the allocated space
|
||||
*/
|
||||
void* mymalloc_ff(int nbytes);
|
||||
|
||||
/* mymalloc_wf()
|
||||
* Requests a block of memory be allocated using
|
||||
* worst fit placement algorithm
|
||||
* The memory manager must be initialized (mmInit)
|
||||
* for this call to succeed
|
||||
* Parameters: nbytes - the number of bytes in the requested memory
|
||||
* Returns: void* - a pointer to the start of the allocated space
|
||||
*/
|
||||
void* mymalloc_wf(int nbytes);
|
||||
|
||||
/* mymalloc_bf()
|
||||
* Requests a block of memory be allocated using
|
||||
* best fit placement algorithm
|
||||
* The memory manager must be initialized (mmInit)
|
||||
* for this call to succeed
|
||||
* Parameters: nbytes - the number of bytes in the requested memory
|
||||
* Returns: void* - a pointer to the start of the allocated space
|
||||
*/
|
||||
void* mymalloc_bf(int nbytes);
|
||||
|
||||
/* myfree()
|
||||
* Requests a block of memory be freed and the storage made
|
||||
* available for future allocations
|
||||
* The memory manager must be initialized (mmInit)
|
||||
* for this call to succeed
|
||||
* Parameters: ptr - a pointer to the start of the space to be freed
|
||||
* Returns: void
|
||||
* Signals a SIGSEGV if a free is not valid
|
||||
* - memory manager is not initialized
|
||||
* - memory manager has been destroyed
|
||||
* - ptr is not allocated (e.g. double free)
|
||||
*/
|
||||
void myfree(void* ptr);
|
||||
|
||||
/* get_allocated_space()
|
||||
* Retrieve the current amount of space allocated by the memory manager (in bytes)
|
||||
* Parameters: None
|
||||
* Returns: int - the current number of allocated bytes
|
||||
*/
|
||||
int get_allocated_space();
|
||||
|
||||
/* get_remaining_space()
|
||||
* Retrieve the current amount of available space in the memory manager (in bytes)
|
||||
* (e.g. sum of all free blocks)
|
||||
* Parameters: None
|
||||
* Returns: int - the current number of free bytes
|
||||
*/
|
||||
int get_remaining_space();
|
||||
|
||||
/* get_fragment_count()
|
||||
* Retrieve the current amount of free blocks (i.e. the count of all the block, not the size)
|
||||
* Parameters: None
|
||||
* Returns: int - the current number of free blocks
|
||||
*/
|
||||
int get_fragment_count();
|
||||
|
||||
/* get_mymalloc_count()
|
||||
* Retrieve the number of successful malloc calls (for all placement types)
|
||||
* Parameters: None
|
||||
* Returns: int - the total number of successful mallocs
|
||||
*/
|
||||
int get_mymalloc_count();
|
||||
|
||||
#endif
|
||||
53
06-MemoryManager/pthread_testmemmgr.c
Normal file
53
06-MemoryManager/pthread_testmemmgr.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 4096
|
||||
#define ALLOC_SIZE 1024
|
||||
#define THREAD_COUNT 10
|
||||
|
||||
void* thread_routine(void* args)
|
||||
{
|
||||
for(int i = 0; i < 25; i++) {
|
||||
char* myptr = mymalloc_ff(ALLOC_SIZE);
|
||||
usleep(20);
|
||||
if(myptr != NULL) {
|
||||
printf("Thread %lu allocated %d byte(s): %p\n", pthread_self(), ALLOC_SIZE, myptr);
|
||||
*myptr = 'a' + i;
|
||||
printf("Thread %lu write %c\n", pthread_self(), *myptr);
|
||||
myfree(myptr);
|
||||
printf("Thread %lu freed %p\n", pthread_self(), myptr);
|
||||
} else {
|
||||
printf("Thread %lu could not allocate %d byte(s)\n", pthread_self(), ALLOC_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
pthread_t mythreads[THREAD_COUNT];
|
||||
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
for(int i = 0; i < THREAD_COUNT; i++) {
|
||||
if(pthread_create(&mythreads[i], NULL, thread_routine, NULL) == -1) {
|
||||
printf("COULD NOT CREATE A THREAD\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < THREAD_COUNT; i++) {
|
||||
pthread_join(mythreads[i], NULL);
|
||||
}
|
||||
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
53
06-MemoryManager/testcases/pthread_testmemmgr.c
Normal file
53
06-MemoryManager/testcases/pthread_testmemmgr.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 4096
|
||||
#define ALLOC_SIZE 1024
|
||||
#define THREAD_COUNT 10
|
||||
|
||||
void* thread_routine(void* args)
|
||||
{
|
||||
for(int i = 0; i < 25; i++) {
|
||||
char* myptr = mymalloc_ff(ALLOC_SIZE);
|
||||
usleep(20);
|
||||
if(myptr != NULL) {
|
||||
printf("Thread %lu allocated %d byte(s): %p\n", pthread_self(), ALLOC_SIZE, myptr);
|
||||
*myptr = 'a' + i;
|
||||
printf("Thread %lu write %c\n", pthread_self(), *myptr);
|
||||
myfree(myptr);
|
||||
printf("Thread %lu freed %p\n", pthread_self(), myptr);
|
||||
} else {
|
||||
printf("Thread %lu could not allocate %d byte(s)\n", pthread_self(), ALLOC_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
pthread_t mythreads[THREAD_COUNT];
|
||||
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
for(int i = 0; i < THREAD_COUNT; i++) {
|
||||
if(pthread_create(&mythreads[i], NULL, thread_routine, NULL) == -1) {
|
||||
printf("COULD NOT CREATE A THREAD\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < THREAD_COUNT; i++) {
|
||||
pthread_join(mythreads[i], NULL);
|
||||
}
|
||||
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
23
06-MemoryManager/testcases/tc0.c
Normal file
23
06-MemoryManager/testcases/tc0.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("TC0: init and destroy\n");
|
||||
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
35
06-MemoryManager/testcases/tc1.c
Normal file
35
06-MemoryManager/testcases/tc1.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC1: Single allocate with mymalloc_ff\n");
|
||||
printf("1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
// Allocate 10 bytes
|
||||
// shouldn't fail
|
||||
char* ptr1 = mymalloc_ff(10);
|
||||
if(ptr1 == NULL) {
|
||||
printf("ptr1 - mymalloc_ff(10) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strncpy(ptr1, "HELLO", 10);
|
||||
printf("ptr1 is %s\n", ptr1);
|
||||
|
||||
printf("2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
myfree(ptr1);
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
47
06-MemoryManager/testcases/tc10.c
Normal file
47
06-MemoryManager/testcases/tc10.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 4096
|
||||
#define MUL_COUNT 100
|
||||
|
||||
int* heap_multiply(int a, int b)
|
||||
{
|
||||
int* result = mymalloc_ff(sizeof(int));
|
||||
if(result == NULL) {
|
||||
printf("COULD NOT mymalloc_ff an int\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*result = a * b;
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int* results[MUL_COUNT];
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC10: allocate multiple integers and perform multiplications\n");
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
printf("%d -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", i, get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
results[i] = heap_multiply(i, i + 2);
|
||||
}
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
printf("%d * %d = %d\n", i, i+2, *results[i]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
myfree(results[i]);
|
||||
}
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
72
06-MemoryManager/testcases/tc11.c
Normal file
72
06-MemoryManager/testcases/tc11.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 4096
|
||||
#define MUL_COUNT 100
|
||||
|
||||
int* results[MUL_COUNT];
|
||||
int ids[MUL_COUNT];
|
||||
|
||||
int* heap_multiply(int a, int b)
|
||||
{
|
||||
int* result = mymalloc_ff(sizeof(int));
|
||||
if(result == NULL) {
|
||||
printf("COULD NOT mymalloc_ff an int\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*result = a * b;
|
||||
return result;
|
||||
}
|
||||
|
||||
void* thread_function(void* args)
|
||||
{
|
||||
int* localId = mymalloc_ff(sizeof(int));
|
||||
if(localId == NULL) {
|
||||
printf("%lu could not allocate space for local ID\n", pthread_self());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*localId = *(int*)args;
|
||||
printf("%d -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", *localId, get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
results[*localId] = heap_multiply(*localId, *localId + 2);
|
||||
myfree(localId);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
pthread_t mythreads[MUL_COUNT];
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC11: pthreads allocate multiple integers and perform multiplications\n");
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
ids[i] = i;
|
||||
if(pthread_create(&mythreads[i], NULL, thread_function, (void*)&ids[i]) == -1) {
|
||||
printf("Could not create thread %d\n", i);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
pthread_join(mythreads[i], NULL);
|
||||
}
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
printf("%d * %d = %d\n", i, i+2, *results[i]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
myfree(results[i]);
|
||||
}
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
72
06-MemoryManager/testcases/tc12.c
Normal file
72
06-MemoryManager/testcases/tc12.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 4096
|
||||
#define MUL_COUNT 1
|
||||
|
||||
int* results[MUL_COUNT];
|
||||
int ids[MUL_COUNT];
|
||||
|
||||
int* heap_multiply(int a, int b)
|
||||
{
|
||||
int* result = mymalloc_ff(sizeof(int));
|
||||
if(result == NULL) {
|
||||
printf("COULD NOT mymalloc_ff an int\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*result = a * b;
|
||||
return result;
|
||||
}
|
||||
|
||||
void* thread_function(void* args)
|
||||
{
|
||||
int* localId = mymalloc_ff(sizeof(int));
|
||||
if(localId == NULL) {
|
||||
printf("%lu could not allocate space for local ID\n", pthread_self());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*localId = *(int*)args;
|
||||
printf("%d -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", *localId, get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
results[*localId] = heap_multiply(*localId, *localId + 2);
|
||||
myfree(localId);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
pthread_t mythreads[MUL_COUNT];
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC12: pthreads allocate single integer and perform multiplication\n");
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
ids[i] = i;
|
||||
if(pthread_create(&mythreads[i], NULL, thread_function, (void*)&ids[i]) == -1) {
|
||||
printf("Could not create thread %d\n", i);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
pthread_join(mythreads[i], NULL);
|
||||
}
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
printf("%d * %d = %d\n", i, i+2, *results[i]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < MUL_COUNT; i++) {
|
||||
myfree(results[i]);
|
||||
}
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
35
06-MemoryManager/testcases/tc2.c
Normal file
35
06-MemoryManager/testcases/tc2.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC2: Single allocate with mymalloc_bf\n");
|
||||
printf("1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
// Allocate 10 bytes
|
||||
// shouldn't fail
|
||||
char* ptr1 = mymalloc_bf(10);
|
||||
if(ptr1 == NULL) {
|
||||
printf("ptr1 - mymalloc_ff(10) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strncpy(ptr1, "HELLO", 10);
|
||||
printf("ptr1 is %s\n", ptr1);
|
||||
|
||||
printf("2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
myfree(ptr1);
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
35
06-MemoryManager/testcases/tc3.c
Normal file
35
06-MemoryManager/testcases/tc3.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC3: Single allocate with mymalloc_wf\n");
|
||||
printf("1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
// Allocate 10 bytes
|
||||
// shouldn't fail
|
||||
char* ptr1 = mymalloc_wf(10);
|
||||
if(ptr1 == NULL) {
|
||||
printf("ptr1 - mymalloc_ff(10) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strncpy(ptr1, "HELLO", 10);
|
||||
printf("ptr1 is %s\n", ptr1);
|
||||
|
||||
printf("2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
myfree(ptr1);
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
32
06-MemoryManager/testcases/tc4.c
Normal file
32
06-MemoryManager/testcases/tc4.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC4: Large allocation should fail\n");
|
||||
printf("1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
// Allocate 10 bytes
|
||||
// shouldn't fail
|
||||
char* ptr1 = mymalloc_ff(200);
|
||||
if(ptr1 != NULL) {
|
||||
printf("ptr1 - mymalloc_ff(10) succeeded\n");
|
||||
myfree(ptr1);
|
||||
}
|
||||
|
||||
printf("2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
06-MemoryManager/testcases/tc5.c
Normal file
41
06-MemoryManager/testcases/tc5.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 4096
|
||||
#define ALLOC_COUNT 100
|
||||
#define ALLOC_SIZE 10
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
void* ptr[ALLOC_COUNT];
|
||||
|
||||
printf("TC5: Heap size: %d: allocation count: %d, allocation size: %d - Lots of small allocationsl\n", MY_HEAP_SIZE, ALLOC_COUNT, ALLOC_SIZE);
|
||||
|
||||
for(int i = 0 ; i < ALLOC_COUNT; i++) {
|
||||
|
||||
printf("%d - 1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", i, get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
ptr[i] = mymalloc_ff(ALLOC_SIZE);
|
||||
if(ptr[i] == NULL) {
|
||||
printf("ptr[%d] - mymalloc_ff(%d) failed\n", i, ALLOC_SIZE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("%d 2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", i, get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
}
|
||||
for(int i = 0; i < ALLOC_COUNT; i++) {
|
||||
printf("Freeing ptr[%d]\n", i);
|
||||
myfree(ptr[i]);
|
||||
}
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
45
06-MemoryManager/testcases/tc6.c
Normal file
45
06-MemoryManager/testcases/tc6.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 4096
|
||||
#define ALLOC_COUNT 100
|
||||
#define ALLOC_SIZE 10
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
void* ptr[ALLOC_COUNT];
|
||||
|
||||
printf("TC6: Heap size: %d: allocation count: %d, allocation size: %d - Lots of small allocations with interleaved frees\n", MY_HEAP_SIZE, ALLOC_COUNT, ALLOC_SIZE);
|
||||
|
||||
for(int i = 0 ; i < ALLOC_COUNT; i++) {
|
||||
|
||||
printf("%d - 1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", i, get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
ptr[i] = mymalloc_ff(ALLOC_SIZE);
|
||||
if(ptr[i] == NULL) {
|
||||
printf("ptr[%d] - mymalloc_ff(%d) failed\n", i, ALLOC_SIZE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("%d 2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", i, get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
}
|
||||
for(int i = 0; i < ALLOC_COUNT; i += 2) {
|
||||
printf("Freeing ptr[%d], Fragment Count: %d\n", i, get_fragment_count());
|
||||
myfree(ptr[i]);
|
||||
}
|
||||
for(int i = 1; i < ALLOC_COUNT; i += 2) {
|
||||
myfree(ptr[i]);
|
||||
printf("Freeing ptr[%d], Fragment Count: %d\n", i, get_fragment_count());
|
||||
}
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
62
06-MemoryManager/testcases/tc7.c
Normal file
62
06-MemoryManager/testcases/tc7.c
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC7: Test interleaved allocations FF\n");
|
||||
printf("1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
void* ptr1 = mymalloc_ff(20);
|
||||
printf("2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr2 = mymalloc_ff(10);
|
||||
printf("3 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr3 = mymalloc_ff(10);
|
||||
printf("4 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
if(ptr1 == NULL) {
|
||||
printf("Unable to allocate ptr1\n");
|
||||
} else {
|
||||
myfree(ptr1);
|
||||
}
|
||||
if(ptr3 == NULL) {
|
||||
printf("Unable to allocate ptr3\n");
|
||||
} else {
|
||||
myfree(ptr3);
|
||||
}
|
||||
printf("5 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
void* ptr4 = mymalloc_ff(10);
|
||||
printf("6 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr5 = mymalloc_ff(20);
|
||||
printf("7 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
if(ptr4 == NULL) {
|
||||
printf("Unable to allocate ptr1\n");
|
||||
} else {
|
||||
myfree(ptr4);
|
||||
}
|
||||
|
||||
if(ptr2 == NULL) {
|
||||
printf("Unable to allocate ptr2\n");
|
||||
} else {
|
||||
myfree(ptr2);
|
||||
}
|
||||
if(ptr5 == NULL) {
|
||||
printf("Unable to allocate ptr5\n");
|
||||
} else {
|
||||
myfree(ptr5);
|
||||
}
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
62
06-MemoryManager/testcases/tc8.c
Normal file
62
06-MemoryManager/testcases/tc8.c
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC8: Test interleaved allocations BF\n");
|
||||
printf("1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
void* ptr1 = mymalloc_bf(20);
|
||||
printf("2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr2 = mymalloc_bf(10);
|
||||
printf("3 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr3 = mymalloc_bf(10);
|
||||
printf("4 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
if(ptr1 == NULL) {
|
||||
printf("Unable to allocate ptr1\n");
|
||||
} else {
|
||||
myfree(ptr1);
|
||||
}
|
||||
if(ptr3 == NULL) {
|
||||
printf("Unable to allocate ptr3\n");
|
||||
} else {
|
||||
myfree(ptr3);
|
||||
}
|
||||
printf("5 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
void* ptr4 = mymalloc_bf(10);
|
||||
printf("6 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr5 = mymalloc_bf(20);
|
||||
printf("7 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
if(ptr4 == NULL) {
|
||||
printf("Unable to allocate ptr1\n");
|
||||
} else {
|
||||
myfree(ptr4);
|
||||
}
|
||||
|
||||
if(ptr2 == NULL) {
|
||||
printf("Unable to allocate ptr2\n");
|
||||
} else {
|
||||
myfree(ptr2);
|
||||
}
|
||||
if(ptr5 == NULL) {
|
||||
printf("Unable to allocate ptr5\n");
|
||||
} else {
|
||||
myfree(ptr5);
|
||||
}
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
62
06-MemoryManager/testcases/tc9.c
Normal file
62
06-MemoryManager/testcases/tc9.c
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("TC9: Test interleaved allocations WF\n");
|
||||
printf("1 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
void* ptr1 = mymalloc_wf(20);
|
||||
printf("2 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr2 = mymalloc_wf(10);
|
||||
printf("3 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr3 = mymalloc_wf(10);
|
||||
printf("4 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
if(ptr1 == NULL) {
|
||||
printf("Unable to allocate ptr1\n");
|
||||
} else {
|
||||
myfree(ptr1);
|
||||
}
|
||||
if(ptr3 == NULL) {
|
||||
printf("Unable to allocate ptr3\n");
|
||||
} else {
|
||||
myfree(ptr3);
|
||||
}
|
||||
printf("5 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
|
||||
void* ptr4 = mymalloc_wf(10);
|
||||
printf("6 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
void* ptr5 = mymalloc_wf(20);
|
||||
printf("7 -- Available Memory: %d, Alloc Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_allocated_space(), get_fragment_count());
|
||||
if(ptr4 == NULL) {
|
||||
printf("Unable to allocate ptr1\n");
|
||||
} else {
|
||||
myfree(ptr4);
|
||||
}
|
||||
|
||||
if(ptr2 == NULL) {
|
||||
printf("Unable to allocate ptr2\n");
|
||||
} else {
|
||||
myfree(ptr2);
|
||||
}
|
||||
if(ptr5 == NULL) {
|
||||
printf("Unable to allocate ptr5\n");
|
||||
} else {
|
||||
myfree(ptr5);
|
||||
}
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
62
06-MemoryManager/testcases/testmemmgr.c
Normal file
62
06-MemoryManager/testcases/testmemmgr.c
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("1 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Allocate 10 bytes
|
||||
// shouldn't fail
|
||||
char* ptr1 = mymalloc_ff(10);
|
||||
if(ptr1 == NULL) {
|
||||
printf("ptr1 - mymalloc_ff(10) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strncpy(ptr1, "HELLO", 10);
|
||||
printf("ptr1 is %s\n", ptr1);
|
||||
|
||||
printf("2 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Allocate 45 bytes
|
||||
// shouldn't fail
|
||||
char* ptr2 = mymalloc_wf(45);
|
||||
if(ptr2 == NULL) {
|
||||
printf("ptr2 - mymalloc_ff(45) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strncpy(ptr2, "GOODBYE", 45);
|
||||
printf("ptr2 is %s\n", ptr2);
|
||||
|
||||
printf("3 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Attempt to allocate 50 bytes
|
||||
// should fail
|
||||
char* ptr3 = mymalloc_bf(50);
|
||||
if(ptr3 == NULL) {
|
||||
printf("ptr3 - mymalloc_bf(50) failed\n");
|
||||
}
|
||||
printf("4 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Free the first two pointers
|
||||
myfree(ptr1);
|
||||
myfree(ptr2);
|
||||
printf("5 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
|
||||
// Double free, should cause a segmentation fault
|
||||
//myfree(ptr2);
|
||||
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
62
06-MemoryManager/testmemmgr.c
Normal file
62
06-MemoryManager/testmemmgr.c
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "memory_manager.h"
|
||||
|
||||
#define MY_HEAP_SIZE 100
|
||||
|
||||
int main()
|
||||
{
|
||||
char my_heap[MY_HEAP_SIZE];
|
||||
mmInit(my_heap, MY_HEAP_SIZE);
|
||||
|
||||
printf("1 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Allocate 10 bytes
|
||||
// shouldn't fail
|
||||
char* ptr1 = mymalloc_ff(10);
|
||||
if(ptr1 == NULL) {
|
||||
printf("ptr1 - mymalloc_ff(10) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strncpy(ptr1, "HELLO", 10);
|
||||
printf("ptr1 is %s\n", ptr1);
|
||||
|
||||
printf("2 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Allocate 45 bytes
|
||||
// shouldn't fail
|
||||
char* ptr2 = mymalloc_wf(45);
|
||||
if(ptr2 == NULL) {
|
||||
printf("ptr2 - mymalloc_ff(45) failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strncpy(ptr2, "GOODBYE", 45);
|
||||
printf("ptr2 is %s\n", ptr2);
|
||||
|
||||
printf("3 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Attempt to allocate 50 bytes
|
||||
// should fail
|
||||
char* ptr3 = mymalloc_bf(50);
|
||||
if(ptr3 == NULL) {
|
||||
printf("ptr3 - mymalloc_bf(50) failed\n");
|
||||
}
|
||||
printf("4 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
// Free the first two pointers
|
||||
myfree(ptr1);
|
||||
myfree(ptr2);
|
||||
printf("5 -- Available Memory: %d, Fragment Count: %d\n", get_remaining_space(), get_fragment_count());
|
||||
|
||||
printf("Total successful mallocs: %d\n", get_mymalloc_count());
|
||||
|
||||
// Double free, should cause a segmentation fault
|
||||
myfree(ptr2);
|
||||
|
||||
mmDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
337
07-FunWithFileSystems/FunWithFileSystems.md
Normal file
337
07-FunWithFileSystems/FunWithFileSystems.md
Normal file
@@ -0,0 +1,337 @@
|
||||
## Introduction and Background
|
||||
|
||||
A mass storage device such as a disk drive, solid state drive, or USB "stick" can be considered a large contiguous block of storage like memory. Like memory, mass storage devices are accessed via an address, however mass storage devices address are for 'blocks' not bytes. A read from a block device reads the entire block and a write, writes an entire block. For mass storage devices, a block is typically 512 bytes. The OS creates an abstraction of 'files' and 'directories' (folder) over the top of mass storage devices to give the user (and applications) the appearance of a file system. A contemporary operating system such as Linux contains drivers for many file systems, with many being quite complex.
|
||||
|
||||
In this lab you will experiment with creating different file systems in Linux as well as interpret a file system architecture for a brand-new file system, teeny tiny file system (TTFS).
|
||||
|
||||
In Linux the file system is organized as a tree of files and directories starting at the root directory (/). The "mount" command allows a system administrator to hang (mount) file systems from a branch of the tree. Kind of like how you might hang an ornament on a tree during the holidays. To mount a file system, you first need to create what is known as a "mount point" i.e., an empty directory that will serve as the entry point for the file system.
|
||||
|
||||
## Create and Mount a RAM Disk
|
||||
|
||||
A RAM disk creates a functional file system directly in random access memory (RAM). Reads and writes to this file system will be an order of magnitude faster than mass storage device operations. This fast access speed is a huge advantage.
|
||||
|
||||
What are the drawbacks? 1) Size – all file systems are limited based on the size of their backing media. For a RAM disk that backing media is RAM which is on the order of a few gigabytes. 2) Persistence – When the system is shutdown or rebooted, the data stored in RAM is lost. For a RAM disk this means that any files stored the file system will also be lost.
|
||||
|
||||
Why use a RAM disk then? Temporary files – many applications use short-lived files, either for inter process communication, storing intermediate results, or logging status. For example, gcc runs through several phases to build an executable program: 1) running the processor, 2) generating assembly, 3) building object code 4) linking the final executable. The output from each of these phases is one or more temporary files that are ultimately thrown away when the final executable is built. Storing these intermediate files in a RAM disk may be able to increase compile speeds. RAM disks are also used during boot to place a minimal system in memory which can then start loading the actual system.
|
||||
|
||||
To start, see how much free memory you have.
|
||||
|
||||
```text
|
||||
user@pc:~$ free -h
|
||||
total used free shared buff/cache available
|
||||
Mem: 3.9G 263M 3.1G 7.8M 469M 3.4G
|
||||
Swap: 4.3G 0B 4.3G
|
||||
```
|
||||
|
||||
You should see two rows in the output. One for physical memory and one for swap (the disk space reserved for the kernel to use for 'kicking out' pages from memory).
|
||||
|
||||
For a description of what each field in the table means you can run: man free
|
||||
|
||||
There are two file system drivers that can be used for RAM disks, ramfs and tmpfs. Large tmpfs disks can actually be swapped out to physical disk, which sort of defeats the purpose, but it is a little more full-featured than ramfs.
|
||||
|
||||
Now, make a mount point for the RAM disk. /media is a common location for mount points. To do this you will need administrator (root) authority. The 'sudo' command allows you to temporarily escalate your system privileges to admin. You'll need to type your password to escalate your privileges.
|
||||
|
||||
```text
|
||||
user@pc:/$ sudo mkdir /media/ramdisk
|
||||
```
|
||||
|
||||
Now we can mount the drive with the mount command and proper options. The following will create a 512 MB RAM disk with file system type tmpfs in /media/ramdisk. See man mount for full details.
|
||||
|
||||
```text
|
||||
user@pc:/$ sudo mount -t tmpfs -o size=512m tmpfs /media/ramdisk
|
||||
```
|
||||
|
||||
The disk is now usable.
|
||||
|
||||
Because the disk was made transiently, it will not be recreated on a reboot. This is because Linux does not keep a record of file systems that were mounted when it shuts down. There is, however, a file that Linux uses determine which file systems to mount at boot up. This file is the file system table (fstab) and is locate in the /etc directory. You can have a look opening /etc/fstab or just use the "cat" command to print it out. You can have a RAM disk be created on every boot by adding an entry to /etc/fstab. If you do this, the ram disk will be there on every boot, but any files present will be gone.
|
||||
|
||||
To complete this activity, perform the following and record your answers to the questions:
|
||||
|
||||
1. View the man page for free with "man free". What does each column mean? In your own words, what is the difference between free memory and available memory?
|
||||
2. View the man page for mount with "man mount". Use the information in the man page to record which file system types your Linux installation supports.
|
||||
3. Pick one of the file systems supported by our Linux installation and learn more about how it works (use Google to help). Give a summary of the file system. Document your resources.
|
||||
4. Create the RAM disk as outlined above. What do each of the parameters to "mount" mean?
|
||||
5. Record the output of free -h after creation of the RAM disk. What is different? Why?
|
||||
6. Based on the observation of the free command before adding the ram disk, and after adding it and adding files to it, in which category of memory does the ram drive appear to reside?
|
||||
7. Record the status of the RAM disk with the command df -h. What can you learn about the file system by running df?
|
||||
8. Copy or download a large file into the RAM disk. I suggest a large pdf file (maybe around 25M). Interact with this file (such as opening a pdf with a viewer) in the RAM disk as well as a copy on the normal file system. What differences do you notice (e.g. performance, etc.)? Why do you think these difference happen or not?
|
||||
9. Record the output of free -h and df -h now that the RAM disk has a file in it. How does the output compare to what you recorded before? Does the output make sense? Why?
|
||||
10. Record the contents /etc/fstab. What does each entry mean? Consult "man fstab" for help.
|
||||
11. What would an entry in /etc/fstab need to look like to create the 512MB tmpfs RAM disk when the system boots?
|
||||
|
||||
When done, the drive should be unmounted to tell Linux that it's no longer needed:
|
||||
|
||||
```text
|
||||
user@pc:/media$ sudo umount /media/ramdisk
|
||||
```
|
||||
|
||||
Remember, that since this is a RAM disk, unmounting the file system will destroy the contents of the file system.
|
||||
|
||||
## Mount a File as a File System
|
||||
|
||||
Linux represents all block devices as a file in a special file system directory '/dev'. This directory contains a representation of devices on the system.
|
||||
|
||||
List the contents of '/dev' on your Linux VM, you should see several 'files' sdaX (X will be a number). These represent the disk partitions of the disk on your system. Partitioning a disk is a way to create logical sub-disks that can each contain a file system that Linux can mount into the directory tree. The 'file' in '/dev' will contain the binary representation of the file system.
|
||||
|
||||
The entire disk (all partitions) is represented by the file '/dev/sda'. View the partitions created on the disk by running the following:
|
||||
|
||||
```text
|
||||
user@pc:/$ sudo fdisk -l /dev/sda
|
||||
```
|
||||
|
||||
Run the following to view the binary data by reading from the file:
|
||||
|
||||
```text
|
||||
user@pc:/$ sudo hexdump -C /dev/sda1
|
||||
```
|
||||
|
||||
This will print out the contents of the device '/dev/sda1' in hexadecimal.
|
||||
|
||||
Run 'mount' (with no arguments) to see all the file systems currently mounted on your Linux VM. Several of them are RAM disks used for temporary file systems. You should be able to see where your sdaX partitions are mounted.
|
||||
|
||||
While a file system will typically be backed by a physical device represented in '/dev', it doesn't have to be. A file system can also be created using an ordinary file. This could be used to create an image to be written to an optical disk or a removable flash drive, or to simply explore file systems without having to install and partition a physical hard drive.
|
||||
|
||||
Run the following to create a FAT16 image file:
|
||||
|
||||
```text
|
||||
user@pc:~$ sudo mkdir /media/myimage
|
||||
user@pc:~$ sudo mkdosfs -C -s 1 -S 512 -F 16 flash.img 5000
|
||||
mkfs.fat 4.1 (2017-01-24)
|
||||
```
|
||||
|
||||
This will create a file called flash.img which contains the raw bytes for a FAT16 file system with a sector size of 512 bytes and 5000 data blocks (a data block in FAT16 is 1024 bytes). A disk drive is organized as an array of logical blocks indexed by logical block address (LBA), however this image file is a contiguous array of the bytes that would be placed in the logical blocks if it were to be stored on a disk drive. On Linux, we can view the file bytes by using hexdump:
|
||||
|
||||
```text
|
||||
hexdump –C flash.img
|
||||
```
|
||||
|
||||
Now mount the image into the Linux directory tree and list its contents by running the following:
|
||||
|
||||
```text
|
||||
user@pc:~$ sudo mount flash.img /media/myimage -o uid=YOURUSERNAME
|
||||
user@pc:~$ cd /media/myimage/
|
||||
user@pc:/media/myimage$ ls -al
|
||||
total 20
|
||||
drwxr-xr-x 2 root 0 16384 Dec 31 1969 .
|
||||
drwxr-xr-x 8 root 0 4096 Nov 4 19:21 ..
|
||||
```
|
||||
|
||||
NOTE: replace YOURUSERNAME with the name of your logged-in user.
|
||||
|
||||
Now add some files to the file system image that you mounted. You can use touch to create an empty file or cp to copy a file into the /media/myimage directory. While this appears to be just creating or copying files into the directory, since the flash.img is mounted at /media/myimage, the files will be written to the file system image (flash.img) using the FAT16 file system driver.
|
||||
|
||||
**Specifically, add four text files, and delete two of them. Also create at least one file with a long filename (longer than 8 characters).**
|
||||
|
||||
Unmount the file system with umount when done. When you have completed the steps above answer the following questions:
|
||||
|
||||
1. Where are the mounted partitions of '/dev/sda' mounted? Why do suspect that two partitions are used? What is an advantage of partitioning the disk in this way?
|
||||
2. Look at the image file with hexdump (hexdump –C flash.img | more). NOTE: make sure the image is **unmounted** before you do this. Can you find your files? How about the ones you deleted? How did you find them or why couldn't you?
|
||||
3. Show a capture of the hexdump (of the flash.img) containing the directory entries for the files you added to the image as well as the ones you added and then deleted. What is different?
|
||||
4. Remount the image, change directory to the directory where the file system is mounted. Now try to unmount the file system with "umount /media/myimage". Did it work successfully? Why or why not?
|
||||
|
||||
## Interpreting a File System - TTFS
|
||||
|
||||
Linux supports many file system types. Each has their own intended use along with advantages and disadvantages. New file systems are being developed all the time to fit the needs of newer backing storage and application purposes. In this activity you will be given the format for a new file system (teeny tiny file system – TTFS). Study the file system format and use the information to interpret a binary file containing a TTFS file system image.
|
||||
|
||||
TTFS stores files and directories of varying sizes. Each file is allocated one or more blocks of data. An index node (inode) stores information about a file or directory in the file system. A TTFS file system image is a binary file divided into the following regions:
|
||||
|
||||
1. File system super block – contains information about the entire file system
|
||||
2. inode bitmap – a bit map that indicates which inodes are free and which are used to store file information
|
||||
3. block bitmap – a bit map that indicates which blocks are free and which hare used to store file data
|
||||
4. inode table – an array of inodes for files and directories in the file system
|
||||
5. block array – the array of data blocks for files and directories in the file system
|
||||
|
||||
An image for TTFS is laid out like this:
|
||||
|
||||

|
||||
|
||||
Regions of the file system follow immediately after each other. The super block contains offset values that can be used to find where regions begin. Data blocks are 512 bytes long and are accessed via their block index. The block index is zero based, so the first block is block 0, the second is block 1, etc.
|
||||
|
||||
### TTFS Super Block
|
||||
|
||||
Each field in the super block is 4 bytes. The offset numbers indicate where the region begins from the ***start of the file system image***. Here is a diagram of each of the fields contained in the super block.
|
||||
|
||||
<table style="border-collapse:collapse;" border="1">
|
||||
<thead>
|
||||
<tr><th>TTFS Super Block</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>TTFS Magic Value</td></tr>
|
||||
<tr><td>inode count</td></tr>
|
||||
<tr><td>block count</td></tr>
|
||||
<tr><td>offset to inode bitmap</td></tr>
|
||||
<tr><td>offset to block bitmap</td></tr>
|
||||
<tr><td>offset to inode table</td></tr>
|
||||
<tr><td>offset to data blocks</td></tr>
|
||||
<tr><td>unused pads to 32 bytes</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
- TTFS Magic Value – an eye-catcher – must contain the string value "TTFS"
|
||||
- inode count – The total number of index nodes in the file system (used or unused)
|
||||
- block count – the total number of blocks in the file system (used or not)
|
||||
- offset to inode bitmap – the offset (in bytes) from the start of the file system image to the start of the inode bitmap
|
||||
- offset to block bitmap – the offset (in bytes) from the start of the file system image to the start of the block bitmap
|
||||
- offset to inode table – the offset (in bytes) from the start of the file system image to the start of the inode table
|
||||
- offset to data blocks – the offset (in bytes) from the start of the file system image to the start of the data block array
|
||||
|
||||
The last field "unused" is just a padding to make the super block 64 bytes (makes it easier to read when printed via a hex dump).
|
||||
|
||||
To be a valid TTFS file system the image must begin with the characters "TTFS", this is a common way for operating systems to know which driver to load to interpret file a file system.
|
||||
|
||||
The inode count represents the total number of index nodes in the file system. Each file or directory in the file system needs to have an index node. This count tells how many files or directories the file system can support.
|
||||
|
||||
The block count represents the total number of data blocks that are in the file system. Each file or directory needs to be allocated at least one block to store data. This count tells how much space is available in the file system.
|
||||
|
||||
The inode and block bitmap are arrays of bit representing which inodes and blocks are used for files, and which are not. For example, if a file system had 16 inodes and 2 were used for files, then the remaining inodes would be free. Used inodes are represented with a bit value of 1 and free inodes have a bit value of 0. So, for this example the inode bitmap would contain 2 bytes (8 bits per byte and 16 inodes requires 2 bytes) and would look like this:
|
||||
|
||||
```text
|
||||
Byte 0 Byte 1
|
||||
Binary: 00000011 00000000
|
||||
Hexadecimal: 03 00
|
||||
```
|
||||
|
||||
Notice that the numbers are in little endian. In other words, the byte ordering goes from low to high from left to the right, but the bit ordering goes from low to high from right to left.
|
||||
|
||||
The super block for a TTFS image consisting of 20 inodes and 100 data blocks would look like this in a hexadecimal dump. NOTE: numbers in an x86 created binary image are little endian.
|
||||
|
||||
<pre>
|
||||
<span style="background:yellow">54 54 46 53</span> <span style="background:lime">14 00 00 00</span> <span style="background:cyan">64 00 00 00</span> <span style="background:magenta">20 00 00 00</span> |TTFS....d... ...|
|
||||
<span style="background:gray">23 00 00 00</span> <span style="background:darkgrey;color:red">30 00 00 00</span> <span style="background:red">30 05 00 00</span> 00 00 00 00 |#...0...0.......|
|
||||
</pre>
|
||||
|
||||
<code style="background:yellow;color:black">54 54 46 53</code> is the TTFS magic value<br/>
|
||||
<code style="background:lime;color:black">14 00 00 00</code> is the number of inodes – hex 00 00 00 14 -> 20 in decimal<br/>
|
||||
<code style="background:cyan;color:black">64 00 00 00</code> is the number of blocks – hex 00 00 00 64 -> 100 in decimal<br/>
|
||||
<code style="background:magenta;color:black">20 00 00 00</code> is the offset to the inode bitmap – hex 00 00 00 20 -> 32 in decimal<br/>
|
||||
<code style="background:gray;color:black">23 00 00 00</code> is the offset to the block bitmap – hex 00 00 00 23 -> 35 in decimal<br/>
|
||||
<code style="background:darkgrey;color:red">30 00 00 00</code> is the offset to the inode table – hex 00 00 00 30 -> 48 in decimal<br/>
|
||||
<code style="background:red;color:black">30 05 00 00</code> is the offset to the block array – hex 00 00 05 30 -> 1328 in decimal
|
||||
|
||||
### TTFS Index Node
|
||||
|
||||
An index node contains metadata (data about the data) for a file or directory. The inode table contains an array of inodes, each inode is 64 bytes long and contains several fields.
|
||||
|
||||
The structure of an inode is as follows:
|
||||
|
||||

|
||||
|
||||
- U – used bit – a single bit that indicates if this inode is used for a file (or directory) or not
|
||||
- D – directory bit – a single bit that indicates if this inode is for a regular file or a directory
|
||||
- block count – (1 byte) the total number of data blocks this file is using
|
||||
- file name – (22 bytes) a string of characters representing the name of the file (null terminated). The file name in TTFS cannot be longer than 21 characters to make room for the null terminator
|
||||
- file size – (4 bytes – little endian) represents the total size of the file in bytes. Block are 512 bytes long and a file might not end exactly at the end of a block
|
||||
- allocated block table – (up to 9 entries 4 bytes each little endian) represents the block numbers that are allocated to this file. The block count indicates which entries in this table are valid. NOTE: Entries in the table indicate the block number for the allocated block number, not an offset in bytes.
|
||||
|
||||
The inode for a file consisting of 1 data block, that is using 10 bytes might look like this in a hexadecimal dump:
|
||||
|
||||
<pre>
|
||||
<span style="background:yellow">01</span> <span style="background:lime">01</span> <span style="background:cyan">74 65 73 74 2e 74 78 74</span> 00 00 00 00 00 00 |..test.txt......|
|
||||
00 00 00 00 00 00 00 00 <span style="background:gray">0a 00 00 00</span> <span style="background:magenta">01 00 00 00</span> |................|
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
..... rest of the inode is zeros .....
|
||||
</pre>
|
||||
|
||||
<code style="background:yellow;color:black">01</code> shows the used bit is on but the directory bit is not<br/>
|
||||
<code style="background:lime;color:black">01</code> indicates the is 1 used block in the file<br/>
|
||||
<code style="background:cyan;color:black">74 65 73 74 2e 74 78 74</code> is the name of the file - ASCII text "test.txt"<br/>
|
||||
<code style="background:gray;color:black">0a 00 00 00</code> is the size of the file in bytes – hex 00 00 00 0a -> 10 in decimal<br/>
|
||||
<code style="background:magenta;color:black">01 00 00 00</code> is the index of the first (and only) data block – hex 00 00 00 01 -> 1 in decimal
|
||||
|
||||
### TTFS Directory
|
||||
|
||||
Directories (folders) in TTFS are special files. The inode for a directory has the directory bit flipped to indicate that is a directory and not an ordinary file. The data blocks for a directory entry to not contain file data. Instead, they indicate the inodes for the files (or directories) that are contained in the directory. The structure for a directory entry data block is:
|
||||
|
||||

|
||||
|
||||
The first 4 bytes indicates an integer number (little endian) of the number of entries contained in the block. The rest of the data block contains 4-byte integers (little endian) for the inodes for entries (files or directories).
|
||||
|
||||
For example, consider a directory 'mydir' that contains two files 'file1.txt' and 'file2.txt'
|
||||
|
||||

|
||||
|
||||
The inode for 'mydir' (inode 3) would contain a single data block. The directory data block would look like:
|
||||
|
||||
<pre>
|
||||
<span style="background:yellow">02 00 00 00</span> <span style="background:lime">05 00 00 00</span> <span style="background:cyan">06 00 00 00 00</span> 00 00 00 |................|
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
..... rest of the block is zeros .....
|
||||
</pre>
|
||||
|
||||
<code style="background:yellow;color:black">02 00 00 00</code> is the number of files in the block<br/>
|
||||
<code style="background:lime;color:black">05 00 00 00</code> is the inode number for file1.txt – hex 00 00 00 05 -> 5 in decimal<br/>
|
||||
<code style="background:cyan;color:black">06 00 00 00</code> is the inode number for file2.txt – hex 00 00 00 06 -> 6 in decimal<br/>
|
||||
|
||||
TTFS always contains a single special directory with no name (the file name is all zeros). This directory represents the root directory of the file system. All files and directories are contained in the root directory. The root director will always use inode 0.
|
||||
|
||||
NOTE: a TTFS directory might use multiple data blocks. Each data block has the same structure. This allows for more than 127 entries in a directory (512 / 4 = 128 but one 4-byte value is used for the entry count).
|
||||
|
||||
Download the [ttfs.img](ttfs.img) file. This contains a binary image for a TTFS file system. Using the output from hexdump -C and the specification for TTFS answer the following questions:
|
||||
|
||||
NOTE: All integers are stored as little endian on x86. So, make sure you read the values correctly
|
||||
|
||||
1. What is the largest file that TTFS can support? How did you compute this number?
|
||||
2. What is the maximum number of files that can exist in a single TTFS directory? HINT: a TTFS directory might have more than one data block.
|
||||
|
||||
For the following questions refer to the [ttfs.img](ttfs.img) provided:
|
||||
|
||||
5. How may inodes and data blocks are in the file system?
|
||||
6. How many inodes are free (not used by files or directories?
|
||||
7. Draw a diagram of the directory hierarchy, include this diagram with your submission.
|
||||
8. What are the names and sizes of each file in the file system?
|
||||
9. How many blocks is each file in the file system?
|
||||
10. For each file, what is the offset (from the start of the file system) for each data block? How did you compute this?
|
||||
11. Find one of the text files in the file system. Write the data (as a string) for the file contents. How were you able to find the data?
|
||||
|
||||
## Extra Credit - TTFS Dump
|
||||
|
||||
Using the specification from "Interpreting a File System - TTFS" and the included header file [ttfs.h](ttfs.h) that defines the file system structures, write a program that will read in a TTFS file system image and print the directory structure and contents for each file. For example:
|
||||
|
||||
```text
|
||||
user@pc:~$ ttfsdump ./ttfstest.img
|
||||
/file2.txt – 10 bytes
|
||||
(the contents of file2.txt printed here)
|
||||
/dir1/file1.txt – 100 bytes
|
||||
(the contents of file1.txt printed here)
|
||||
/dir1/dir2/file3.txt – 20 bytes
|
||||
(the contents of file3.txt printed here)
|
||||
(continue for all files)
|
||||
```
|
||||
|
||||
Also add the following in your report:
|
||||
|
||||
- Design – a description of your design decisions in creating your solution
|
||||
- Build – instructions on how to build and run your program. Include the exact commands that are necessary
|
||||
|
||||
Include your source code along with your report in your Canvas submission.
|
||||
|
||||
## Deliverables
|
||||
|
||||
You will need to include all your source files (if any) and any resources you used to complete lab. Please don't just google search for a solution, but if you do use Google for any help, include a description and URL of what you used to help you.
|
||||
|
||||
Once you've completed all the lab activities and have answers to all the lab questions, create a report (text, doc, or pdf file) including the following:
|
||||
|
||||
- Your name, section, date, and lab title
|
||||
- Introduction – a description the lab in your own words
|
||||
- Resources – a description of any external resources you used to complete the lab
|
||||
- Analysis – a description of your experiences working with file systems in Linux as a result of this lab
|
||||
- Include the answers to the questions asked in the lab.
|
||||
- Conclusion
|
||||
- Summary of what you learned in the lab
|
||||
- What specifically was challenging about this lab?
|
||||
- What did you like about it?
|
||||
- What could we do to improve it for others?
|
||||
|
||||
Be sure to include documentation of any external resources (man pages, stackoverflow, etc.) that you used to complete the lab.
|
||||
|
||||
Upload your report to Canvas per your instructor's instructions.
|
||||
|
||||
## Grading Criteria
|
||||
|
||||
- (5 Points) Report Introduction - Thorough description of the lab in your own words.
|
||||
- (5 Points) Conclusion - Thorough conclusion with description of what you learned, what you liked, and suggestions for lab improvements.
|
||||
- (5 Points) Documentation of Resources - Description of external resources used to complete the lab.
|
||||
- (25 Points) Create and Mount a RAM disk - Responses to the "create a RAM disk" questions
|
||||
- (25 Points) Mount a File as a File System - Responses to the "file as a file system" questions
|
||||
- (35 Points) Interpreting a File System - TTFS - Responses to the TTFS interpretation questions
|
||||
- (10 Points) Bonus - Implementation of the extra credit
|
||||
1
07-FunWithFileSystems/dir.drawio
Normal file
1
07-FunWithFileSystems/dir.drawio
Normal file
@@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2020-11-02T15:06:28.625Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.7.9 Chrome/85.0.4183.121 Electron/10.1.3 Safari/537.36" etag="SV2yda06R5R9tws0U6qs" version="13.7.9" type="device"><diagram id="qYH77iOIGeU9Z4i7EPOW" name="Page-1">7VZdb9MwFP01eezkxHFZH/sxQEhIQ5sEPCEvvkuMkjhy3TbZr+e6dpqvThswAZN4iu+x77HvuSdOArou6neaV9lHJSAPIiLqgG6CKArJ5RwfFmkcckk8kGop/KIOuJEP0GZ6dCcFbAcLjVK5kdUQTFRZQmIGGNdaHYbL7lU+3LXiKUyAm4TnU/SzFCbzVTDS4e9Bplm7c0j8TMHbxR7YZlyoQw+iVwFda6WMGxX1GnIrXquLy3v7yOzpYBpK85yE6sPtIa7iu1vCE6LfLMn3T99mnmXP850vuGiE1AjNbGqJ/cQn9RWYppXFQI2brjJT5AiEOOS5TEscJ3gc0AjsQRuJQi79RCGFsOkrDVv5wO+OVATjSsnSHNvEVgHbWK6dUVtnBUvtz4h8UD9afHiSFL0IqgCjG1ziE9B3LsXbMKQ+PnRNXXgo6/WzbR73NkpPzJ3SOPBi/4Tw0UT4e5lDeGFQ16H47PWLT0biL6bin96bP6I+Pat+dEb9+atXn7J/Tf14ov5EZCjF0t7eGJWqhKHeWLhuvlgJL2I2b4GvR2DRhpvaa+yiph9dg5ZYiu2VA2tpHB8LfWjZZuQi8mHHZoOmF4y5XCkgJp+VUb+wXLXTCTx9RxiuUzBPXeLT/vf6y860t8U05NzI/fC453rud7i2nu3sFY9e7jge2caV6bP636cx0cindDEicjpMiI4WPJX9665kL+dKNvIk+z1TxiNTxn/TlPS/KV/ElBh2/35uefcHTa9+AA==</diagram></mxfile>
|
||||
BIN
07-FunWithFileSystems/dir.png
Normal file
BIN
07-FunWithFileSystems/dir.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
1
07-FunWithFileSystems/dirblock.drawio
Normal file
1
07-FunWithFileSystems/dirblock.drawio
Normal file
@@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2020-11-19T19:07:59.919Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.7.9 Chrome/85.0.4183.121 Electron/10.1.3 Safari/537.36" etag="148tzwbpLXTsa0UH6v0t" version="13.7.9" type="device"><diagram id="0Z0EK_m_mWr8dVZr8u3I" name="Page-1">7ZhRU6MwEMc/DY/eAGmqfZTq1dO70RmdUx9TkkLOlMWQ2uKnvwRCKdDW6mg9Z64vZf+ETfLb3XSpg4bTxUiSNP4FlAnHd+nCQSeO73vuUV9/GSUvlSPXCpHk1A6qhWv+zKonrTrjlGWNgQpAKJ42xRCShIWqoREpYd4cNgHRnDUlEesI1yERXfWWUxXbXWC31s8Yj+JqZs+1d6akGmyFLCYU5isSOnXQUAKo8mq6GDJh4FVcyue+b7i7XJhkidrlgQM2uJgNB7/Pb3iWg1Kj+x/BgfXyRMTMblh7k3kBdKb9litXeYVDapUy49F1UDCPuWLXKQnN3blOAK3Faiq05enL7gqr6ZhUbLEi2RWPGExZOf0ygSy9ZfqU5ryOhdezWrwSh0ojNvzR0nNNSF9YSK8A5m8ExhOd/I4JAvrnsHn+HrmNLwN0e5aeBxe9Y4pvLifh4+OaROtAYlRXnjVBqhgiSIg4rdWgibEe8xMgtfD+MKVye4yQmYJ1aM1EG4vIShnMZMi2JAK2hxGREVNbxvXXB0oyQRR/aq7j3al3s/U/9Xelvm2RX+2M6H/22dr/ktx89NncDneo8oQem25IWwkkpqopyeKCmtckZPQrohSTSaH4LtJqpiQ8LDsgTScoQnNnqH/DlXlvfRTGycKGpLRya7299vs71j5ee95047kSL7wmXJW285lhZ7gCbhqnKl16rXTptdOg3Ld9arV/azvCTUdo0HJUguk4KlJque23Z9lRJ8t62gxypdvzdrrpXjc1l6GELBsT+XJh1lVsLEHGTAQkfIgKfQgCZOEZTYrPx1Qy3rGQ/Y8q5MHLhbwHshKUTngw5T/YWrGvIN3Hrd8a3EU92Cfq6v1yhTX2/I0JrfepmliJ4JFBFGoqzITB0OD6xfHY3phySsv+iWX8mYwLV4Znaiq02A8OHHxifOmWKSu7p/1lv49aMVmT/ofvExJt1u+55XlU/1uATv8C</diagram></mxfile>
|
||||
BIN
07-FunWithFileSystems/dirblock.png
Normal file
BIN
07-FunWithFileSystems/dirblock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
1
07-FunWithFileSystems/inode.drawio
Normal file
1
07-FunWithFileSystems/inode.drawio
Normal file
@@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2021-11-14T19:28:39.382Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.7.9 Chrome/85.0.4183.121 Electron/10.1.3 Safari/537.36" etag="urC6ZLM37bueH1rSPxqJ" version="13.7.9" type="device"><diagram id="T3rH0xRinKpGynSwAKey" name="Page-1">7Zpbc6IwFMc/jY/d4S4+Vu22D7szO9PpbvcxQgqMQGwIVfvpN8GEW7yggtCZ9cXkhATyO3+Tc4IjfRZtHjFY+T+RC8ORpribkT4faZqq2Bb9YpbtzmIr3ODhwOUXFYbn4BOKntyaBi5MKhcShEISrKpGB8UxdEjFBjBG6+plbyis3nUFPCgZnh0QytY/gUt8PgtTKexPMPB8cWdV4S0REBdzQ+IDF61LJv1hpM8wQmRXijYzGDJ4gsuu3/cDrfmDYRiTJh2iH+/z5TueoZe7p8nj7yfs3T/c8VE+QJjyCfOHJVtBAKM0diEbRBnp07UfEPi8Ag5rXVOfU5tPopDWVFqUH0rcAWICNyUTf8hHiCJI8JZeIlp1DowrZsKr6wK/KtThl9CLboB73MtHLqDQAudyBiNNYrQIkbPMRJfSafYNTDMGBkxvWVQJwWgJZyhEmFpiFMN2wOnmwMAZXwScYQ0MnCmBewsoMU2JQQSHybC+zKmaDNEw9kDMybZO0TpEMWHbct/LXB1YrqZTwDpT3VjiBUK6MwBCqWiK2CTiNFpATAvK8BBafSO0T694MHbvWSBX/PpKUOAmIK+cHyv/LZXnm3JlKyoxfe5X0Z1V/pZbik5ZTfQ6CD9BKXbg6c2QAOxBcnrth24lHpVdWXKVucdTwoZhCEjwUY1i97mP3+EXClgok6/wtZgir4shdvPmvcpRZ32gSXUgfVIbaAdGGihTUz7tywU2aUlgaklg6qAEZn5JgZm1EEI1LxSYVU8X7JvqS2zGlwtMyEUpy0U9IZfzZdm9wMxhCWzcksBMuzaQctsVTG2Qo1+gsFML0r6d9b/CysKQIviLFVbbI6UIv2uFySccdLNQplsCE0lqiQ9WrOhglCQLgE8HrkWUK+dTIxpaZh/aEoIFDKfAWXpZj9Ilb9mnmxjYbBgCa12FwKp8XPIiUT8rU2gA8rAXWkCcszp8PKDdMslQ5UQtjdOEZWlfGXODg9LxTTHLydzRfFi9Dn8HBPchvG0+rMr5ylGGcijQN0O96TlWd+f1ckh+lKE+PIZNN6XuGMpB51GGxvAY2r0zlMOqowzNwTE01N4ZysHRUYbW8BgavTOUXysdZTgeHsNx7wzldyMSpWszo6viSYwIzWVRTM2TluJL3da+mRU/aJOxsJQ9oZuyJzpLl7Qzo0x7cGo2ld7VLEeZ1uGMn06TVKGAMPCY0hwKBTKdMxiBA8J73hAFrsu6TzFMgk+wyIZitFfsDCObjjkdmXM2VkpQsvvbT8MfQQsuqZ/paXuCBWuPR7o7BJDfYM+vE27f2Wn+vrPzQwBaLf5FtTsTK/6Lpj/8Aw==</diagram></mxfile>
|
||||
BIN
07-FunWithFileSystems/inode.png
Normal file
BIN
07-FunWithFileSystems/inode.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
1
07-FunWithFileSystems/ttfs.drawio
Normal file
1
07-FunWithFileSystems/ttfs.drawio
Normal file
@@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2020-11-02T14:59:45.961Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.7.9 Chrome/85.0.4183.121 Electron/10.1.3 Safari/537.36" etag="c_etp6RsLqb3VisMrdBP" version="13.7.9" type="device"><diagram id="fw7Wd_Siw-Zg11o-hQoO" name="Page-1">3ZnbcpswEIafhst2QAISX8bOoZ3paepO0+ZOBhk0EYgRIrbz9JVAGINwm6SxIc7kAi1Ch2//RcvagrNkfcNRFn9mIaYWsMO1BS8tABwXAEv92+GmspzXhoiTUHdqDHPyiLXR1taChDhvdRSMUUGytjFgaYoD0bIhztmq3W3JaHvWDEXYMMwDRE3rLQlFrHfh2Y39AyZRXM/s2PpOgurO2pDHKGSrHRO8suCMMyaqq2Q9w1TBq7lUz13vubtdGMepeMoDDNwtv35Pi+Uq/xHdLW6+kE8X7/QoD4gWesN5kWEuTQvKgnu9crGpcXBWpCFWI9oWnK5iIvA8Q4G6u5ICkLZYJFS2HHlprrCeDnOB1zsmveIbzBIs+EZ2qe8Cr3pEy8c50zRXjTMcV9viHUf42oa0/6Pt0A0ieaEpPYMYMIiRVKpeESMikQjGhgzAoZFBA5kW12iRTYZG5u5VmUALiWlsxKA3NDFvr8jkMYA2oyPmOkMT8w1iBiR5ZmXqMuAszxeI/5tUg7VqCSQIS2VzYr8OR+B3ToSeWPV7MIJDYZwYGKFqTzdC5i1doHKTog0MURIpPhQv1R0Fgsj040KbExKG6uEpxzl5LGO/UmzGSCrKvXhTy7tUIxWC5VUCpQamaIHpFAX3UemTGaOMl4uAy/LvddwB7ZG5ow6rNy5r0PNCPS5HMzX8iTipTh+7TNSBT5VkFzJd9CN15VRHeplnqxwSoyBW81RH13ChcACdA9czX9+gx0HwYA4yM9G3KHTYcw4eV+hm5vBSofd/M71toW/bwwn9NBIV2PPpelyhnz1f6HL75Z5O/n0O/cFlfn4SMnd7yg3HlbmZkL9M5qf4NnfB0DIHT8jPcRpeqNqtUjpFeU6CNvHSXb8Uxvde3fytqZaNy3WrtdGtvUAF4hEWfxNV1Q+HrWqxiX0Hq9dDtbZxTGUcPrRrzH2o9QzflFQarzqTzkdX11s5K3iA9VNgpybcGcjvFiUmnYEqMMZApee32/4PMZgfGXM5pVohWyq/xCpmPyaqSA/sa9JT+dofj4H0MuZji0gHdnzXVweCx3xhArM++2oR6RwsIr1RR6TnvDAiQbeecn7kiDQrz1dpeNLxaPd77gDxKJvN732Vx5pfTeHVHw==</diagram></mxfile>
|
||||
37
07-FunWithFileSystems/ttfs.h
Normal file
37
07-FunWithFileSystems/ttfs.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef TTFS_H
|
||||
#define TTFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define TTFS_MAGIC "TTFS"
|
||||
#define FILE_NAME_MAX_LENGTH 22
|
||||
#define MAX_FILE_BLOCKS 9
|
||||
#define BLOCK_SIZE 512
|
||||
|
||||
typedef struct __attribute__((packed)) ttfs_super_block {
|
||||
char ttfs_magic[4];
|
||||
uint32_t inode_count;
|
||||
uint32_t block_count;
|
||||
uint32_t offset_to_inode_map;
|
||||
uint32_t offset_to_block_map;
|
||||
uint32_t offset_to_inode_table;
|
||||
uint32_t offset_to_data_blocks;
|
||||
uint32_t unused;
|
||||
} ttfs_super_block;
|
||||
|
||||
typedef struct __attribute__((packed)) ttfs_inode {
|
||||
uint8_t inode_used:1;
|
||||
uint8_t is_directory:1;
|
||||
uint8_t unused:6;
|
||||
uint8_t block_count;
|
||||
char file_name[FILE_NAME_MAX_LENGTH];
|
||||
uint32_t file_size;
|
||||
uint32_t blocks[MAX_FILE_BLOCKS];
|
||||
} ttfs_inode;
|
||||
|
||||
typedef struct __attribute__((packed)) ttfs_directory_block {
|
||||
uint32_t entry_count;
|
||||
uint32_t inodes_inodes[BLOCK_SIZE/sizeof(uint32_t) - 1];
|
||||
} ttfs_directory_block;
|
||||
|
||||
#endif // TTFS_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user