Group 1
Group 2
Group 3
Group 4
Group 5
© 2023 Vedesh Kungebeharry. All rights reserved.
© 2023 Vedesh Kungebeharry. All rights reserved.

https://drive.google.com/drive/folders/1Uc8Hbr1tgQlf6XjMbn2h2MaIL9c86iXE?usp=drive_link
This is what the animation was based upon:
#include <stdio.h>
#include <stdlib.h>
void bubbleSort (int a [ ], int numItems);
void bubbleSort2 (int a [ ], int numItems);
void print(int a[], int numItems);
int main()
{
int myArray[] = {4, 3, 1, 2, -1};
// Calculate the number of items in the array
int numItems = sizeof(myArray) / sizeof(myArray[0]);
// Display the array
print(myArray, numItems);
//bubbleSort the array
bubbleSort2(myArray,numItems);
//Display the array after sorting
print(myArray, numItems);
return 0;
}
//bubble sort
void bubbleSort (int a [ ], int numItems)
{
int i, j, temp;
for(i=0;i<numItems -1; i++)
{
for (j = 0; (j<numItems-i-1); j++)
{
if (a[j]>a[j+1])
{
temp =a[j] ;
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
//bubble sort for debugging and demonstration
void bubbleSort2 (int a [ ], int numItems)
{
int i, j, temp;
for(i=0;i<numItems -1; i++)
{
printf("i=%d\n",i);
printf("\tInner loop , j values: ");
for (j = 0; (j<numItems-i-1); j++)
{
printf("%d",j);
if (a[j]>a[j+1])
{
temp =a[j] ;
a[j]=a[j+1];
a[j+1]=temp;
}
}
print(a,numItems);
printf("\n");
}
}
// Function to print an array of integers
void print(int a[], int numItems)
{
printf("\nThe array: ");
for(int i = 0; i < numItems; i++) {
printf("%d ", a[i]);
}
printf("\n\n");
}
(downloadable here from the link above)
not that in this code, the array values are different and contain negative numbers
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h> // For Windows API functions
#else
#include <unistd.h> // For usleep
#endif
// ANSI escape codes for colors
#define RESET_COLOR "\x1b[0m"
#define RED "\x1b[31m"
#define GREEN "\x1b[32m"
#define BLUE "\x1b[34m"
#define YELLOW "\x1b[33m"
// Global sleep time definitions (in milliseconds)
#define SLEEP_TIME_MS 1000
int findMaxAbsValue(int a[], int numItems) {
int maxAbsValue = abs(a[0]);
for (int i = 1; i < numItems; i++) {
if (abs(a[i]) > maxAbsValue) {
maxAbsValue = abs(a[i]);
}
}
return maxAbsValue;
}
void printArrayAsColumns(int a[], int numItems, int maxAbsValue, int compareIndex, int swapped, int pass, int sortedIndex) {
printf("Pass number: %d\n", pass); // Print the pass number at the top
for (int level = maxAbsValue; level > 0; level--) {
for (int i = 0; i < numItems; i++) {
if (i >= sortedIndex) {
printf(YELLOW);
} else if (i == compareIndex || i == compareIndex + 1) {
printf(swapped ? (i == compareIndex ? RED : BLUE) : GREEN);
}
if (a[i] >= level) {
printf("| ");
} else {
printf(" ");
}
printf(RESET_COLOR);
}
printf("\n");
}
for (int i = 0; i < numItems; i++) {
printf("--");
}
printf("\n");
for (int level = 1; level <= maxAbsValue; level++) {
for (int i = 0; i < numItems; i++) {
if (i >= sortedIndex) {
printf(YELLOW);
} else if (i == compareIndex || i == compareIndex + 1) {
printf(swapped ? (i == compareIndex ? RED : BLUE) : GREEN);
}
if (a[i] <= -level) {
printf("| ");
} else {
printf(" ");
}
printf(RESET_COLOR);
}
printf("\n");
}
for (int i = 0; i < numItems; i++) {
if (i >= sortedIndex) {
printf(YELLOW);
} else if (i == compareIndex || i == compareIndex + 1) {
printf(swapped ? (i == compareIndex ? RED : BLUE) : GREEN);
}
printf("%d ", a[i]);
printf(RESET_COLOR);
}
printf("\n");
}
void animateBubbleSort(int a[], int numItems, int stepThrough) {
int maxAbsValue = findMaxAbsValue(a, numItems);
int i, j, temp, pass = 0;
for (i = 0; i < numItems - 1; i++) {
pass++;
for (j = 0; j < numItems - i - 1; j++) {
int swapped = 0;
// Clear the screen
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
printArrayAsColumns(a, numItems, maxAbsValue, j, swapped, pass, numItems - i);
// Print the initial comparison statement
printf("Now comparing %d and %d.\n", a[j], a[j + 1]);
if (a[j] > a[j + 1]) {
printf("%d is greater than %d, will swap.\n", a[j], a[j + 1]);
swapped = 1;
if (stepThrough) {
printf("Press enter to continue to the next step...\n");
while (getchar() != '\n'); // Wait for user to press enter
} else {
#ifdef _WIN32
Sleep(SLEEP_TIME_MS); // Sleep for Windows
#else
usleep(SLEEP_TIME_MS * 1000); // Sleep for Unix, converting milliseconds to microseconds
#endif
}
// Perform the swap
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
// Clear the screen for swap update
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
printArrayAsColumns(a, numItems, maxAbsValue, j, swapped, pass, numItems - i);
// Print the swap confirmation
printf("Swapped: %d (red) and %d (blue).\n", a[j + 1], a[j]);
} else {
// Print the no swap statement
printf("No swap needed: %d is not greater than %d.\n", a[j], a[j + 1]);
}
if (stepThrough) {
printf("Press enter to continue to the next step...\n");
while (getchar() != '\n'); // Wait for user to press enter
} else {
#ifdef _WIN32
Sleep(SLEEP_TIME_MS); // Sleep for Windows
#else
usleep(SLEEP_TIME_MS * 1000); // Sleep for Unix, converting milliseconds to microseconds
#endif
}
}
}
}
int main() {
int myArray[] = {4, -3, 1, -2, 5};
int numItems = sizeof(myArray) / sizeof(myArray[0]);
char userChoice;
printf("Do you want to step through the animation (s) or run it in full (f)? [s/f]: ");
scanf(" %c", &userChoice); // Note the space before %c to consume any whitespace characters
// Consume the newline character left in the input buffer by scanf
while (getchar() != '\n');
// Call the animateBubbleSort function
if (userChoice == 's' || userChoice == 'S') {
animateBubbleSort(myArray, numItems, 1); // Step through
} else {
animateBubbleSort(myArray, numItems, 0); // Run in full
}
return 0;
}
© 2023 Vedesh Kungebeharry. All rights reserved.

This animation was based on the code/algorithm in this post: Binary Search Implementation
Download the code and executable file here: https://drive.google.com/drive/folders/1i0TilBMD4eECj6nkjHcP6HHvfEBalMEF?usp=sharing
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h> // For Windows API functions
#else
#include <unistd.h> // For usleep on Unix
#endif
// ANSI escape codes for colors
#define RESET_COLOR "\x1b[0m"
#define HIGHLIGHT "\x1b[44m" // Blue background
#define GREY "\x1b[90m" // Grey text
// Global sleep time definition (in milliseconds)
#define SLEEP_TIME_MS 2000
void clearScreen() {
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
}
void sleepMs(int milliseconds) {
#ifdef _WIN32
Sleep(milliseconds);
#else
usleep(milliseconds * 1000); // convert to microseconds
#endif
}
void printAnnotation(int position, const char* annotation, int listSize) {
for (int i = 0; i < position * 4 + 11; i++) { // Adjust position for correct alignment
printf(" ");
}
printf("%s\n", annotation); // Print the annotation (Fir, Mid, Las)
}
void printAnnotations(int listSize, int first, int last, int middle) {
if (first >= 0) printAnnotation(first, "Fir", listSize);
if (middle >= 0) printAnnotation(middle, "Mid", listSize);
if (last >= 0) printAnnotation(last, "Las", listSize);
}
void printArray(int list[], int listSize, int first, int last, int middle, int initialDisplay) {
printf("+");
for (int i = 0; i < listSize * 4 + 9; i++) { // Adjust border size based on array size
printf("-");
}
printf("+\n");
printf("|Elements |");
for (int i = 0; i < listSize; i++) {
if (!initialDisplay && (i < first || i > last)) {
printf(GREY); // Grey out discarded elements during search
} else if (i == first || i == last || i == middle) {
printf(HIGHLIGHT); // Highlight the first, last, and middle elements during search
}
printf(" %2d" RESET_COLOR "|", list[i]);
}
printf("\n");
printf("+");
for (int i = 0; i < listSize * 4 + 9; i++) { // Adjust border size based on array size
printf("-");
}
printf("+\n");
printf("|Index |");
for (int i = 0; i < listSize; i++) {
if (!initialDisplay && (i < first || i > last)) {
printf(GREY); // Grey out discarded indexes during search
} else if (i == first || i == last || i == middle) {
printf(HIGHLIGHT); // Highlight the first, last, and middle indexes during search
}
printf(" %2d" RESET_COLOR "|", i);
}
printf("\n");
printf("+");
for (int i = 0; i < listSize * 4 + 9; i++) { // Adjust border size based on array size
printf("-");
}
printf("+\n");
}
void displayInitialArray(int list[], int listSize) {
printf("\nInitial array:\n");
printArray(list, listSize, -1, -1, -1, 1); // Display all elements normally
printf("\nPress Enter to start the search...");
getchar(); // Wait for user to press enter to continue
}
int binarySearch(int key, int list[], int listSize, int stepThrough, int *comparisonCount) {
int first = 0;
int last = listSize - 1;
int middle = first + (last - first) / 2;
while (first <= last) {
(*comparisonCount)++; // Increment the comparison count
clearScreen();
printArray(list, listSize, first, last, middle, 0);
printAnnotations(listSize, first, last, middle); // Print the annotations
if (key == list[middle]) {
printf("\nKey %d found at index %d.\n", key, middle);
return middle;
} else if (key < list[middle]) {
printf("\nKey %d is less than %d, searching lower half.\n", key, list[middle]);
last = middle - 1;
} else {
printf("\nKey %d is greater than %d, searching upper half.\n", key, list[middle]);
first = middle + 1;
}
middle = first + (last - first) / 2;
if (stepThrough) {
printf("Press Enter to continue...");
getchar(); // Wait for user to press enter to continue to the next step
} else {
sleepMs(SLEEP_TIME_MS);
}
}
printf("\nKey %d not found.\n", key);
return -1;
}
int main() {
// Modify the array here for different demonstrations
//int list[10] = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50};
int list[] = {3, 6, 8, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51};
int listSize = sizeof(list) / sizeof(list[0]); // Calculate the size of the array
int key, stepThrough, comparisonCount;
printf("Enter 1 for step through, 0 for full animation: ");
scanf("%d", &stepThrough);
getchar(); // Consume the newline character left in the input buffer by scanf
displayInitialArray(list, listSize); // Display the array before starting the search
printf("\nEnter a search key (-1 to exit): ");
scanf("%d", &key);
while (key != -1) {
getchar(); // Consume the newline character left in the input buffer by scanf
comparisonCount = 0; // Reset comparison count for each search
binarySearch(key, list, listSize, stepThrough, &comparisonCount);
printf("Number of comparisons made: %d\n", comparisonCount);
printf("\nEnter a search key (-1 to exit): ");
scanf("%d", &key);
}
return 0;
}
© 2023 Vedesh Kungebeharry. All rights reserved.
Compilers produce complete file of executable code for execution at a later time, whereas an interpreter translates source code one line or block of code at a time and executes it during the program’s run.
Compilers detect all errors (syntax and semantic) before the final executable can be produced, a programmer must fix all errors before the final executable is produced. The most common error that is produced during execution are runtime errors.
Interpreters detect errors as they arise during execution one line or block of code at a time, the most common errors are datatype errors.
Note that both compilers and interpreters are susceptible to syntax and runtime errors.
© 2023 Vedesh Kungebeharry. All rights reserved.
This question tested the following topics/items:
A client server network has one or more computer nodes providing all the services needed by all other client computers. E.g web server, ftp server etc.
Hardware and resources are easily configured.
Servers can be administered to allow connection only to authorized computers on the network thus benefit from better security.
The sever can easily undergo regular backups easily since all data is centralized.
For P2P each computer on the network can act as a server for all others on the network.
Each node on the P2P is not guaranteed to be powerful, and mostly have the average power as clients.
This configuration is difficult to keep secure, additional third party software is usually required to implement security.
P2P networks add strain on the network as more peers are added to the network since sometimes one node would be responsible for routing a lot of traffic to all others. It is impractical to attempt backup on this network configuration.
A firewall is a hardware and/or software security measure which protects against external network threats in the form of unauthorized connections or attacks. It also filters connections within the network to prevent malicious activity.
New computer threats emerge every day, and thus the firewall must apply frequent updates which protect against new computer threats.
Fddi uses fibre optic cables , and transfers data using token ring topology, and can be much faster over long distances (200 Km). The ring technology includes additional rings in the event that one ring fails, another exists to carry on data communication.
Ethernet mainly uses copper wires, and transfers data using packet switching (Star Topology), over shorter distances (100 m) and is slower than FDDI. Ethernet does not typically have backup lines to help prevent network failure.
The Transport layer is responsible for segmenting packets and reliable communications across the transport layer by implementing end to end communication with error checking and data flow control (speed changes between networks)
The network layer is responsible for efficiently routing data from network to network by choosing the best paths using IP protocol which gives each node on the network a unique IP address.
It is designed to provide wireless network connectivity over a cellular network so that traditional network tasks, e.g. connecting to the internet, can be facilitated. It was developed for wireless POS systems, MMS, tracking and navigation , wireless electricity meters , etc.
© 2023 Vedesh Kungebeharry. All rights reserved.
This question tested the following operating system concepts:
| Concept1 | Description |
|---|---|
| Program vs. Process | Differentiation between a program (a set of instructions on storage) and a process (an executing program with allocated resources in the CPU and memory). |
| Process States and Transitions | Understanding the various states a process can be in (running, ready, waiting, finished) and the reasons for transitions between these states. |
| Deadlock | Comprehension of the condition where two or more processes are waiting indefinitely for each other to release resources. |
| Multitasking vs. Multiprocessing | Distinction between multitasking (managing multiple tasks by time-sharing a single CPU) and multiprocessing (managing tasks across multiple CPUs for parallel execution). |
| Virtual Memory | Discussion on why modern computers use virtual memory, how it works through paging and swapping, and the disadvantages of excessive reliance on virtual memory, such as thrashing. |
A program is a set of computer instructions that is stored on secondary storage, and a process is a program that is currently being executed on the cpu, it’s instructions and data are stored in main memory – RAM and registers in the CPU.
It’s time on the CPU has expired.
It is waiting on data from an IO operation and cannot continue until it receives the data.
The process has completed all of its instructions and no longer needs any of it’s previous system resources.
P1 is using d1,
P2 is using d1,
Eventually p1 needs d2 also, it is put into a waiting state.
P2 needs d1, but d1 is in use by p1 and p1 is waiting on p2 to release d2.
P2 will be put into a waiting state
Both process are waiting on each other and will not release the DVD resources that they are allocated, thus neither process can complete and thus we say they are deadlocked.
Windows 10, is a multitasking operating system, tasks share time on the CPU.
Linux is a multiprocessing operating system allowing for the running of separate tasks on separate CPUs, thus achieving higher performance.
All present-day operating systems support multitasking and multiprocessing, there are cases where multiprocessing may not be used, e.g where an embedded system is designed for specific task that doesn’t require much processing power.
Sometimes many processes need to be run simultaneously, and the needs for physical memory can exceed the actual memory that is available.
Multiple page frames are created for each process. Ideally, the currently running’s process’s frames are stored in physical ram, and all other ready or waiting processes are stored in ram. As more processes are run which exceed the physical ram capacity, the page frames for the ready and waiting processes are swapped out of physical ram onto the page file on the hard disk to accommodate running processes. When a running process is put into waiting/ready state, it may be put on the virtual page file, and the next process to be run can be put from the virtual page file back into the physical ram to be run.
The system can operate inefficiently since a lot of swapping may occur, and this is dependent on the much slower hard disk memory access for each swap. This condition is know as thrashing.
© 2023 Vedesh Kungebeharry. All rights reserved.
int numseq[21];
21 locations needed for numbers 0 to 20)
| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| numSeq | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
19
int binarySearch(int key, int list[], int low, int high) {
int result = -1;
int keyFound = 0; //sentinel to end loop on a successful search
while (low <= high && !keyFound) {
int middle = (high-low) / 2 + low;//determine middle of the range
if (key == list[middle])
{
result = middle;
keyFound=1; // Key found, exit loop
}
else if (key < list[middle])
{
high = middle - 1; // Narrow the search to the lower half
}
else
low = middle + 1; // Narrow the search to the upper half
}
}
return result; //Returns -1 if not found,
//otherwise, the index of the key
}
(See this note1)
int binarySearch(int key, int list[], int low, int high) {
int result = -1; //result is -1 if not found
int keyFound = 0; //sentinel to end loop on a successful search
while (low <= high && !keyFound) //while there is more locations
//to search and the key has not
//been found
{
int middle = (high-low) / 2 + low;//determine middle of the range
if (key == list[middle]) //if the key is found..
{
result = middle;
keyFound=1; // Key found, exit loop
}
else if (key < list[middle]) //if key may be in the lower half...
{
high = middle - 1; // Narrow the search to the lower half
}
else //else the key may be in the upper half
{
low = middle + 1; // Narrow the search to the upper half
}
}
return result; // Returns -1 if not found, otherwise the key
int binarySearch(int key, int list[], int low, int high)
{
int result=-1;
int middle = (high-low)/2+low;
if (low<=high)//if low and high have not crossed...
{
if(key==list[middle])//if the key is found....
{
result=middle;
return result
}
else//the key was not found
{
if(key<list[middle])
{
result= binarySearch(key,list,low,middle-1);
return result;
}
else
{
result= binarySearch(key,list,middle+1,high);
return result;
}
}
}
return result;
int binarySearch(int key, int list[], int low, int high)
{
/*we use low and high to represent a
portion of the array. Initially, low and high
points to the start of the array and the end of
the array respectively. Middle indexes the location
to the middle of the array.
*/
int result=-1;//-1 represents a failed search
int middle = (high-low)/2+low;
if (low<=high)//if low and high have not crossed...
{
if(key==list[middle])//if the key is found....
{
result=middle;
return result;//return the current index and exit function
}
else//the key was not found
{
if(key<list[middle])//if the key would be found
{ //from low to middle
//we now search the lower half
result= binarySearch(key,list,low,middle-1);
return result;
}
else //key would be found from middle to high
{
result= binarySearch(key,list,middle+1,high);//we now search the upper half
return result;
}
}
}
return result;
//assume integer array
void swap(int array[], int a, int b) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
}
void selectionSort (int arr[], int low, int high)
{
for (int i = low; i<high; i++)
{
int smallest = getSmallest(arr,i,high);
swap(arr,i,smallest);
}
}
The following complete program in C tests that the selection sort is working.
#include <stdio.h>
//function declarations
void selectionSort(int arr[], int low, int high);
void swap(int array[], int a, int b);
int getSmallest(int arr[], int low, int high);
int main()
{
int array[] = {64, 25, 12, 22, 11};
int size = sizeof(array) / sizeof(array[0]);
printf("Original array: ");
for (int i = 0; i < size; i++)
printf("%d ", array[i]);
printf("\n");
//sort the array
selectionSort(array, 0, size-1);
printf("Sorted array: ");
for (int i = 0; i < size; i++)
printf("%d ", array[i]);
printf("\n");
printf("\nEnding program...");
return 0;
}
void selectionSort(int arr[], int low, int high) {
// Traverse up to the
// second-to-last element
for (int i = low; i < high; i++)
{
/*find the index of the smallest
element in the range
*/
int smallest = getSmallest(arr, i, high);
/*if the smallest element
should be put in the first
position that was
traversed ...
*/
if(arr[smallest]<arr[i])
swap(arr, i, smallest);//swap elements
}
}
void swap(int array[], int a, int b) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
}
int getSmallest(int arr[], int low, int high) {
int smallestIndex = low;
// Include the high in the search
for (int i = low + 1; i <= high; i++)
{
if (arr[i] < arr[smallestIndex]) {
smallestIndex = i;
}
}
return smallestIndex;
}
| Location | 0 | 1 | 2 | 3 | 4 |
| Value | 30 | 50 | 40 | 60 | 20 |
| Pass 1 | 30 | 40 | 50 | 20 | 60 |
| Pass 2 | 30 | 40 | 20 | 50 | 60 |
(See this note2)
© 2023 Vedesh Kungebeharry. All rights reserved.
In a linear search, each element of the array is traversed by using iteration. Each element in the traversal is compared against a search key. If the key is found, the location of the array index is returned. If the entire array is traversed without finding the key, dummy value is returned (e.g. -1)
(see this note [1])
In a binary search, an ordered list is searched for a key starting with the item at the middle of the list. If the item is not found at the location , a determination is made on which half of the list may contain the key, either the upper or lower half. This method is applied to search the midpoint of the half of the list which may contain the key. This repeats until the key is found, or until the search space is reduced to a single location and the list can no longer be divided into halves. If the key is found, the location of the element is returned, otherwise a dummy value is returned (e.g -1)
(see this note [2])
//Code to store values in array
int arr[] = {3,12,9,10,5,4};
int arrayLength = sizeof(arr)/sizeof(int);
//selection sort
for ( int i = 0; i<arrayLength; ++i)
{
int smallest = i;
for (int k = i ; k<arrayLength; ++k)
{
if (arr[k]<arr[smallest])
smallest=k;
}
//if the first element was not the smallest,
//swap the first item with the smallest
if (smallest!=i)
{
int temp = arr[i];
arr[i] = arr[smallest];
arr[smallest]=temp;
}
}
Search midpoint of [0-9], location 4, it is not the key, 16<27 so the left portion is searched
Search midpoint of [0-3], location 1, it is not the key, 16>9 so the right portion is searched
Search midpoint of [2-3], location 2, it is the key, thus the search function returns 2.
The search concludes with the algorithm returning index 2 as the position where the key 16 is located in the array.
[1] https://islandclass.org/2020/09/01/linear-search/
[2] https://islandclass.org/2020/11/12/binary-search-implementation/
Non Pre-emptive scheduling runs processes on a first come first serve basis, pre-emptive scheduling determines the length of time the processes will take to be executed , and then executes the shortest process first, followed by the next shortest and so on. Pre-emptive scheduling can also be accomplished by other algorithms , e.g round robin.
(See this note1)
The process’s instruction from it’s local program counter is placed on the CPU and executed one after the other until an interrupt is generated.
The process scheduler prepares to move the process of the CPU. The process’ updated program counter and state information is saved to its process control block, the process is now in the “ready” queue.
The process is interrupted by an I/O or event interrupt. The process’ updated program counter and state information is saved to its process control block, it is placed in the “waiting” queue to wait for an I/0 or event completion.
The process is moved to the ready queue from the waiting queue. If the process was waiting on an I/O operation, it’s PCB and local memory would be updated before it was moved to the ready queue.
The interrupt is a scheduling one, P5’s program counter and other information is saved to its PCB. P5 is put into a “ready” state since it was not blocked by IO or another event.
P2’s instruction from its Program counter is put on the cpu for execution, P2’s PCB is updated to “running” . P2 will run to completion assuming no error interrupts are generated. When P2 is complete, it’s state is set to terminated. Assuming that there are no other high priority tasks to be run than P5, P5 will be go from ready to running, and it’s instructions are executed from it’s program counter until it terminates and enters a terminated state.

R0 is locked to P0, it cannot be accessed.
P1 wants to access R1, because it is locked to P0.
For P1 to access R0, P0 must run to completion and terminate.
However, P0 is waiting on P1 to complete in order to access R1 (Which is locked to P1 in the diagram)
Thus both processes cannot run to completion since the resources they need are locked either one. This produces a deadlock.
Advantages:
Advanced operations can be performed at the command line.
For an advanced user, It is faster than using a gui
It is uses comparatively less system resources.
Disadvantages:
It is difficult to learn and use for an inexperienced user.
Unable to perform multitasking.
Encrypt the files.
Password protect the files.
Employ the use of access permissions to the sender and receiver only to be able to access the file.
Send over a reliable medium which can verify and ensure that the file was sent I.e the use of an application layer protocol running over a connection oriented protocol, e.g using an email client which implements SMTP which in turn uses the IP TCP.
© 2023 Vedesh Kungebeharry. All rights reserved.
Handles Host to host communication on the subnet (subnetwork to subnetwork, thus implementing a wide area network) level occurs here using packets. Packets are routed from host to host across the subnets or within a single subnet. Separate subnets may be implemented with differing protocols, the network layer will overcome these challenges by modifying packets to conform to the various protocols.
Here is where raw data is transferred over the physical mediums which make up the network, protocol example : RS-232-C
(See this video1)
The application layer is where applications communicate with each other through high level protocols e.g HTTP, FTP. The application itself is only responsible for adhering to those protocols and not responsible for routing, sequencing etc that is required to send information through the lower layers which make up the network infrastructure.
Difficult to guess
Contains a combination of Uppercase and lowercase letters
Contains Special Characters
Is sufficiently long
Can be remembered easily by its creator even though it is difficult to guess.
(See this note2)
Any of the 3 responses below:
Router with access to internet, all other devices connected to the router similar to the diagram below
© 2023 Vedesh Kungebeharry. All rights reserved.